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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// 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.
|
||||
|
||||
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,
|
||||
@Nullable final PsiElement lastParent,
|
||||
@NotNull final PsiElement place);
|
||||
|
||||
@Nullable
|
||||
PsiType getOwnerType();
|
||||
}
|
||||
|
||||
+23
-40
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// 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.
|
||||
|
||||
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.PsiScopeProcessor;
|
||||
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.PsiModificationTracker;
|
||||
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.dataFlow.types.TypeInferenceHelper;
|
||||
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.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.resolve.MethodTypeInferencer;
|
||||
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 (!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;
|
||||
|
||||
return true;
|
||||
@@ -295,28 +278,28 @@ public class GrClosableBlockImpl extends GrBlockImpl implements GrClosableBlock
|
||||
return res;
|
||||
}
|
||||
|
||||
private PsiVariable getOwner() {
|
||||
return CachedValuesManager.getCachedValue(this, () -> {
|
||||
final GroovyPsiElement context = PsiTreeUtil.getParentOfType(this, GrTypeDefinition.class, GrClosableBlock.class, GroovyFile.class);
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
|
||||
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);
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType getOwnerType() {
|
||||
return CachedValuesManager.getCachedValue(this, () -> Result.create(doGetOwnerType(), PsiModificationTracker.MODIFICATION_COUNT));
|
||||
}
|
||||
|
||||
PsiVariable owner = new GrLightVariable(getManager(), OWNER_NAME, type, this);
|
||||
return CachedValueProvider.Result.create(owner, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
});
|
||||
@Nullable
|
||||
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
|
||||
|
||||
+9
-18
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// 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.
|
||||
package org.jetbrains.plugins.groovy.lang.typing
|
||||
|
||||
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.resolve.delegatesTo.getDelegatesToInfo
|
||||
|
||||
class GrClosureDelegateTypeCalculator : GrTypeCalculator<GrReferenceExpression> {
|
||||
class GrClosureOwnerDelegateTypeCalculator : GrTypeCalculator<GrReferenceExpression> {
|
||||
|
||||
override fun getType(expression: GrReferenceExpression): PsiType? {
|
||||
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)
|
||||
if (closureClass == null || closureClass != method.containingClass) 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"/>
|
||||
|
||||
<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"
|
||||
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 {
|
||||
PsiReference ref = configureByFile("closureOwner/A.groovy")
|
||||
PsiElement resolved = ref.resolve()
|
||||
assertInstanceOf(resolved, PsiVariable)
|
||||
assertEquals((resolved as PsiVariable).type.canonicalText, "W")
|
||||
assertInstanceOf(resolved, PsiMethod)
|
||||
}
|
||||
|
||||
void testLocal1() throws Exception {
|
||||
|
||||
+10
@@ -818,4 +818,14 @@ def bar() {
|
||||
void 'test enum values() type'() {
|
||||
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