mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[groovy] compute Closure.getOwner() type without light variable
This commit is contained in:
+4
-15
@@ -1,18 +1,4 @@
|
|||||||
/*
|
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
* Copyright 2000-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks;
|
package org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks;
|
||||||
|
|
||||||
@@ -63,4 +49,7 @@ public interface GrClosableBlock extends GrExpression, GrCodeBlock, GrParameters
|
|||||||
@NotNull final ResolveState _state,
|
@NotNull final ResolveState _state,
|
||||||
@Nullable final PsiElement lastParent,
|
@Nullable final PsiElement lastParent,
|
||||||
@NotNull final PsiElement place);
|
@NotNull final PsiElement place);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
PsiType getOwnerType();
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-40
@@ -1,18 +1,4 @@
|
|||||||
/*
|
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
* Copyright 2000-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks;
|
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks;
|
||||||
|
|
||||||
@@ -21,7 +7,7 @@ import com.intellij.psi.*;
|
|||||||
import com.intellij.psi.scope.ElementClassHint;
|
import com.intellij.psi.scope.ElementClassHint;
|
||||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.util.CachedValueProvider;
|
import com.intellij.psi.util.CachedValueProvider.Result;
|
||||||
import com.intellij.psi.util.CachedValuesManager;
|
import com.intellij.psi.util.CachedValuesManager;
|
||||||
import com.intellij.psi.util.PsiModificationTracker;
|
import com.intellij.psi.util.PsiModificationTracker;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
@@ -43,10 +29,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterLi
|
|||||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
|
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
|
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
|
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterListImpl;
|
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterListImpl;
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.ClosureSyntheticParameter;
|
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.ClosureSyntheticParameter;
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable;
|
|
||||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
|
||||||
import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer;
|
import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer;
|
||||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
|
||||||
@@ -98,7 +82,6 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
|
|||||||
|
|
||||||
if (!super.processDeclarations(processor, state, lastParent, place)) return false;
|
if (!super.processDeclarations(processor, state, lastParent, place)) return false;
|
||||||
if (!processParameters(processor, state, place)) return false;
|
if (!processParameters(processor, state, place)) return false;
|
||||||
if (ResolveUtil.shouldProcessProperties(processor.getHint(ElementClassHint.KEY)) && !ResolveUtil.processElement(processor, getOwner(), state)) return false;
|
|
||||||
if (!processClosureClassMembers(processor, state, lastParent, place)) return false;
|
if (!processClosureClassMembers(processor, state, lastParent, place)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -295,28 +278,28 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PsiVariable getOwner() {
|
@Nullable
|
||||||
return CachedValuesManager.getCachedValue(this, () -> {
|
@Override
|
||||||
final GroovyPsiElement context = PsiTreeUtil.getParentOfType(this, GrTypeDefinition.class, GrClosableBlock.class, GroovyFile.class);
|
public PsiType getOwnerType() {
|
||||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
return CachedValuesManager.getCachedValue(this, () -> Result.create(doGetOwnerType(), PsiModificationTracker.MODIFICATION_COUNT));
|
||||||
PsiType type = null;
|
}
|
||||||
if (context instanceof GrTypeDefinition) {
|
|
||||||
type = factory.createType((PsiClass)context);
|
|
||||||
}
|
|
||||||
else if (context instanceof GrClosableBlock) {
|
|
||||||
type = GrClosureType.create((GrClosableBlock)context, true);
|
|
||||||
}
|
|
||||||
else if (context instanceof GroovyFile) {
|
|
||||||
final PsiClass scriptClass = ((GroovyFile)context).getScriptClass();
|
|
||||||
if (scriptClass != null && GroovyNamesUtil.isIdentifier(scriptClass.getName())) type = factory.createType(scriptClass);
|
|
||||||
}
|
|
||||||
if (type == null) {
|
|
||||||
type = TypesUtil.getJavaLangObject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
PsiVariable owner = new GrLightVariable(getManager(), OWNER_NAME, type, this);
|
@Nullable
|
||||||
return CachedValueProvider.Result.create(owner, PsiModificationTracker.MODIFICATION_COUNT);
|
private PsiType doGetOwnerType() {
|
||||||
});
|
final GroovyPsiElement context = PsiTreeUtil.getParentOfType(this, GrTypeDefinition.class, GrClosableBlock.class, GroovyFile.class);
|
||||||
|
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
||||||
|
if (context instanceof GrTypeDefinition) {
|
||||||
|
return factory.createType((PsiClass)context);
|
||||||
|
}
|
||||||
|
else if (context instanceof GrClosableBlock) {
|
||||||
|
return ((GrClosableBlock)context).getType();
|
||||||
|
}
|
||||||
|
else if (context instanceof GroovyFile) {
|
||||||
|
final PsiClass scriptClass = ((GroovyFile)context).getScriptClass();
|
||||||
|
if (scriptClass != null && GroovyNamesUtil.isIdentifier(scriptClass.getName())) return factory.createType(scriptClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+9
-18
@@ -1,18 +1,4 @@
|
|||||||
/*
|
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
* Copyright 2000-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.jetbrains.plugins.groovy.lang.typing
|
package org.jetbrains.plugins.groovy.lang.typing
|
||||||
|
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.JavaPsiFacade
|
||||||
@@ -24,16 +10,21 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
|
|||||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE
|
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE
|
||||||
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getDelegatesToInfo
|
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getDelegatesToInfo
|
||||||
|
|
||||||
class GrClosureDelegateTypeCalculator : GrTypeCalculator<GrReferenceExpression> {
|
class GrClosureOwnerDelegateTypeCalculator : GrTypeCalculator<GrReferenceExpression> {
|
||||||
|
|
||||||
override fun getType(expression: GrReferenceExpression): PsiType? {
|
override fun getType(expression: GrReferenceExpression): PsiType? {
|
||||||
val method = expression.resolve() as? PsiMethod ?: return null
|
val method = expression.resolve() as? PsiMethod ?: return null
|
||||||
if ("getDelegate" != method.name || method.parameterList.parametersCount != 0) return null
|
|
||||||
|
val methodName = method.name
|
||||||
|
val delegate = "getDelegate" == methodName
|
||||||
|
if (!delegate && "getOwner" != methodName) return null
|
||||||
|
|
||||||
|
if (method.parameterList.parametersCount != 0) return null
|
||||||
|
|
||||||
val closureClass = JavaPsiFacade.getInstance(expression.project).findClass(GROOVY_LANG_CLOSURE, expression.resolveScope)
|
val closureClass = JavaPsiFacade.getInstance(expression.project).findClass(GROOVY_LANG_CLOSURE, expression.resolveScope)
|
||||||
if (closureClass == null || closureClass != method.containingClass) return null
|
if (closureClass == null || closureClass != method.containingClass) return null
|
||||||
|
|
||||||
val closure = PsiTreeUtil.getParentOfType(expression, GrClosableBlock::class.java) ?: return null
|
val closure = PsiTreeUtil.getParentOfType(expression, GrClosableBlock::class.java) ?: return null
|
||||||
return getDelegatesToInfo(closure)?.typeToDelegate
|
return if (delegate) getDelegatesToInfo(closure)?.typeToDelegate else closure.ownerType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
implementation="org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrDGMTypeCalculator"/>
|
implementation="org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrDGMTypeCalculator"/>
|
||||||
|
|
||||||
<typeCalculator forClass="org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression"
|
<typeCalculator forClass="org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression"
|
||||||
implementationClass="org.jetbrains.plugins.groovy.lang.typing.GrClosureDelegateTypeCalculator"/>
|
implementationClass="org.jetbrains.plugins.groovy.lang.typing.GrClosureOwnerDelegateTypeCalculator"/>
|
||||||
<typeCalculator forClass="org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall"
|
<typeCalculator forClass="org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall"
|
||||||
implementationClass="org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrDescriptorReturnTypeCalculator"/>
|
implementationClass="org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.path.GrDescriptorReturnTypeCalculator"/>
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -37,8 +37,7 @@ class ResolvePropertyTest extends GroovyResolveTestCase {
|
|||||||
void testClosureOwner() throws Exception {
|
void testClosureOwner() throws Exception {
|
||||||
PsiReference ref = configureByFile("closureOwner/A.groovy")
|
PsiReference ref = configureByFile("closureOwner/A.groovy")
|
||||||
PsiElement resolved = ref.resolve()
|
PsiElement resolved = ref.resolve()
|
||||||
assertInstanceOf(resolved, PsiVariable)
|
assertInstanceOf(resolved, PsiMethod)
|
||||||
assertEquals((resolved as PsiVariable).type.canonicalText, "W")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testLocal1() throws Exception {
|
void testLocal1() throws Exception {
|
||||||
|
|||||||
+10
@@ -818,4 +818,14 @@ def bar() {
|
|||||||
void 'test enum values() type'() {
|
void 'test enum values() type'() {
|
||||||
doExprTest 'enum E {}; E.values()', 'E[]'
|
doExprTest 'enum E {}; E.values()', 'E[]'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void 'test closure owner type'() {
|
||||||
|
doTest '''\
|
||||||
|
class W {
|
||||||
|
def c = {
|
||||||
|
<caret>owner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
''', 'W'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user