context-dependent resolve and type inference, restore TypeDfaInstance but don't activate yet

This commit is contained in:
peter
2012-08-31 22:02:12 +02:00
parent 9de2fdc08c
commit 031fbb8fdf
11 changed files with 259 additions and 64 deletions
@@ -15,12 +15,12 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
@@ -49,6 +49,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMe
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -64,16 +65,11 @@ import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*;
* @author ven
*/
public class GroovyExpectedTypesProvider {
private static final Key<CachedValue<TypeConstraint[]>> CACHED_EXPECTED_TYPES = Key.create("CACHED_EXPECTED_TYPES");
private GroovyExpectedTypesProvider() {
}
public static TypeConstraint[] calculateTypeConstraints(@NotNull final GrExpression expression) {
CachedValue<TypeConstraint[]> cached = expression.getUserData(CACHED_EXPECTED_TYPES);
if (cached == null) {
expression.putUserData(CACHED_EXPECTED_TYPES, cached = CachedValuesManager.getManager(expression.getProject()).createCachedValue(new CachedValueProvider<TypeConstraint[]>() {
public Result<TypeConstraint[]> compute() {
return TypeInferenceHelper.getCurrentContext().getCachedValue(expression, new Computable<TypeConstraint[]>() {
@Override
public TypeConstraint[] compute() {
MyCalculator calculator = new MyCalculator(expression);
final PsiElement parent = expression.getParent();
if (parent instanceof GroovyPsiElement) {
@@ -91,14 +87,12 @@ public class GroovyExpectedTypesProvider {
if (!custom.isEmpty()) {
custom.addAll(0, Arrays.asList(result));
return Result.create(custom.toArray(new TypeConstraint[custom.size()]), PsiModificationTracker.MODIFICATION_COUNT);
return custom.toArray(new TypeConstraint[custom.size()]);
}
return Result.create(result, PsiModificationTracker.MODIFICATION_COUNT);
return result;
}
}, false));
}
return cached.getValue();
});
}
public static Set<PsiType> getDefaultExpectedTypes(@NotNull GrExpression element) {
@@ -0,0 +1,123 @@
/*
* Copyright 2000-2012 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;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.ResolveResult;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import java.util.Map;
import static com.intellij.util.containers.ContainerUtil.newHashMap;
/**
* @author peter
*/
public interface InferenceContext {
InferenceContext TOP_CONTEXT = new InferenceContext() {
@Nullable
@Override
public PsiType getVariableType(@NotNull GrReferenceExpression ref) {
return TypeInferenceHelper.getInferredType(ref);
}
@Override
public <T> T getCachedValue(@NotNull GroovyPsiElement element, final Computable<T> computable) {
return CachedValuesManager.getManager(element.getProject()).getCachedValue(element, new CachedValueProvider<T>() {
@Nullable
@Override
public Result<T> compute() {
return Result.create(computable.compute(), PsiModificationTracker.MODIFICATION_COUNT);
}
});
}
@Override
public <T extends PsiPolyVariantReference> GroovyResolveResult[] multiResolve(@NotNull T ref,
boolean incomplete,
ResolveCache.PolyVariantResolver<T> resolver) {
ResolveResult[] results = ResolveCache.getInstance(ref.getElement().getProject()).resolveWithCaching(ref, resolver, true, incomplete);
return results.length == 0 ? GroovyResolveResult.EMPTY_ARRAY : (GroovyResolveResult[])results;
}
};
@Nullable
PsiType getVariableType(@NotNull GrReferenceExpression ref);
<T> T getCachedValue(@NotNull GroovyPsiElement element, Computable<T> computable);
<T extends PsiPolyVariantReference> GroovyResolveResult[] multiResolve(@NotNull T ref, boolean incomplete, ResolveCache.PolyVariantResolver<T> resolver);
class PartialContext implements InferenceContext {
private final Map<String, PsiType> myTypes;
private final Map<PsiElement, Map<Object, Object>> myCache = newHashMap();
public PartialContext(Map<String, PsiType> types) {
myTypes = types;
}
@Nullable
@Override
public PsiType getVariableType(@NotNull GrReferenceExpression ref) {
return myTypes.get(ref.getReferenceName());
}
@Override
public <T> T getCachedValue(@NotNull GroovyPsiElement element, Computable<T> computable) {
return _getCachedValue(element, computable, computable.getClass());
}
private <T> T _getCachedValue(PsiElement element, Computable<T> computable, Object key) {
Map<Object, Object> map = myCache.get(element);
if (map == null) {
myCache.put(element, map = newHashMap());
}
if (map.containsKey(key)) {
//noinspection unchecked
return (T)map.get(key);
}
T result = computable.compute();
map.put(key, result);
return result;
}
@Override
public <T extends PsiPolyVariantReference> GroovyResolveResult[] multiResolve(@NotNull final T ref,
final boolean incomplete,
final ResolveCache.PolyVariantResolver<T> resolver) {
return _getCachedValue(ref.getElement(), new Computable<GroovyResolveResult[]>() {
@Override
public GroovyResolveResult[] compute() {
return (GroovyResolveResult[])resolver.resolve(ref, incomplete);
}
}, Pair.create(incomplete, resolver.getClass()));
}
}
}
@@ -16,13 +16,12 @@
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiIntersectionType;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
@@ -38,9 +37,11 @@ import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstru
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ArgumentInstruction;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAEngine;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DFAType;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.DfaInstance;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.DefinitionMap;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsDfaInstance;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.ReachingDefinitionsSemilattice;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypesSemilattice;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import java.util.*;
@@ -50,8 +51,24 @@ import java.util.*;
*/
@SuppressWarnings("UtilityClassWithoutPrivateConstructor")
public class TypeInferenceHelper {
private static final Logger LOG = Logger.getInstance(TypeInferenceHelper.class);
private static final ThreadLocal<InferenceContext> ourInferenceContext = new ThreadLocal<InferenceContext>();
public static <T> T doInference(Map<String, PsiType> bindings, Computable<T> computation) {
InferenceContext old = ourInferenceContext.get();
ourInferenceContext.set(new InferenceContext.PartialContext(bindings));
try {
return computation.compute();
}
finally {
ourInferenceContext.set(old);
}
}
public static InferenceContext getCurrentContext() {
InferenceContext context = ourInferenceContext.get();
return context != null ? context : InferenceContext.TOP_CONTEXT;
}
@Nullable
public static PsiType getInferredType(@NotNull final GrReferenceExpression refExpr) {
@@ -73,7 +90,6 @@ public class TypeInferenceHelper {
if (type == null) return null;
return type.getResultType();
}
});
}
@@ -90,6 +106,34 @@ public class TypeInferenceHelper {
return type != null ? type.getResultType() : null;
}
@Nullable
public static PsiType getInferredTypeNew(@NotNull final GrReferenceExpression refExpr) {
final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(refExpr);
if (scope == null) return null;
final Instruction[] flow = scope.getControlFlow();
return inferVariableType(refExpr.getReferenceName(), scope, flow, findInstruction(refExpr, flow));
}
@Nullable
public static PsiType getInferredTypeNew(@NotNull PsiElement place, String variableName) {
final GrControlFlowOwner scope = ControlFlowUtils.findControlFlowOwner(place);
if (scope == null) return null;
final Instruction[] flow = scope.getControlFlow();
return inferVariableType(variableName, scope, flow, findInstructionAt(place, flow));
}
private static PsiType inferVariableType(String variableName, GrControlFlowOwner scope, Instruction[] flow, Instruction instruction) {
if (instruction == null) return null;
ArrayList<Map<String, PsiType>> list = performTypeDfa(scope, flow);
if (list == null) return null;
return list.get(instruction.num()).get(variableName);
}
public static boolean isTooComplexTooAnalyze(GrControlFlowOwner scope) {
return getDefUseMaps(scope) == null;
}
@@ -298,31 +342,58 @@ public class TypeInferenceHelper {
return null;
}
/*@Nullable
private static PsiType getInferredType(@NotNull String varName,
@NotNull Instruction instruction,
@NotNull GrControlFlowOwner scope) {
final ArrayList<Map<String, DFAType>> dfaResult = getDefUseMaps(scope);
if (dfaResult == null) return null;
final Map<String, DFAType> allDefs = dfaResult.get(instruction.num());
final DFAType dfaType = allDefs.get(varName);
if (dfaType == null) return null;
return dfaType.getType();
@Nullable
private static ArrayList<Map<String, PsiType>> performTypeDfa(GrControlFlowOwner owner, Instruction[] flow) {
final TypeDfaInstance dfaInstance = new TypeDfaInstance(owner);
final TypesSemilattice semilattice = new TypesSemilattice(owner.getManager());
final DFAEngine<Map<String, PsiType>> engine = new DFAEngine<Map<String, PsiType>>(flow, dfaInstance, semilattice);
return engine.performDFAWithTimeout();
}
private static ArrayList<Map<String, DFAType>> getDefUseMaps(final GrControlFlowOwner scope) {
return CachedValuesManager.getManager(scope.getProject()).getCachedValue(scope, new CachedValueProvider<ArrayList<Map<String, DFAType>>>() {
@Override
public Result<ArrayList<Map<String, DFAType>>> compute() {
final Instruction[] flow = scope.getControlFlow();
final DFAEngine<Map<String, DFAType>> engine = new DFAEngine<Map<String, DFAType>>(flow, new TypeDFAInstance(), new TypesSemilattice(scope.getManager()));
final ArrayList<Map<String, DFAType>> result = engine.performDFAWithTimeout();
return Result.create(result, PsiModificationTracker.MODIFICATION_COUNT);
static class TypeDfaInstance implements DfaInstance<Map<String, PsiType>> {
private final PsiElement scope;
TypeDfaInstance(PsiElement scope) {
this.scope = scope;
}
public void fun(final Map<String, PsiType> map, final Instruction instruction) {
if (instruction instanceof ReadWriteVariableInstruction && ((ReadWriteVariableInstruction) instruction).isWrite()) {
final PsiElement element = instruction.getElement();
if (element != null) {
map.put(((ReadWriteVariableInstruction)instruction).getVariableName(), doInference(map, new Computable<PsiType>() {
@Override
public PsiType compute() {
return TypesUtil.boxPrimitiveType(getInitializerType(element), scope.getManager(), scope.getResolveScope());
}
}));
}
}
});
}*/
if (instruction instanceof ArgumentInstruction) {
final String varName = ((MixinTypeInstruction)instruction).getVariableName();
map.put(varName, doInference(map, new Computable<PsiType>() {
@Override
public PsiType compute() {
PsiType original = map.get(varName);
final PsiType mixin = ((MixinTypeInstruction)instruction).inferMixinType();
if (mixin == null) return original;
if (original == null) return mixin;
return PsiIntersectionType.createIntersection(original, mixin);
}
}));
}
}
@NotNull
public Map<String, PsiType> initial() {
return ContainerUtil.newHashMap();
}
public boolean isForward() {
return true;
}
}
}
@@ -39,6 +39,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrI
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor;
@@ -136,7 +137,7 @@ public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAs
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, false, incompleteCode);
return TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, RESOLVER);
}
@Override
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinary
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
/**
@@ -115,7 +116,7 @@ public abstract class GrBinaryExpressionImpl extends GrExpressionImpl implements
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, false, incompleteCode);
return TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, RESOLVER);
}
@Override
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.text.StringUtil;
@@ -314,13 +315,12 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
assert upToArgument == null;
return CachedValuesManager.getManager(getProject())
.getCachedValue(this, new CachedValueProvider<Pair<Boolean, GroovyResolveResult[]>>() {
@Override
public Result<Pair<Boolean, GroovyResolveResult[]>> compute() {
return Result.create(doResolveByShape(false, null), PsiModificationTracker.MODIFICATION_COUNT);
}
});
return TypeInferenceHelper.getCurrentContext().getCachedValue(this, new NullableComputable<Pair<Boolean, GroovyResolveResult[]>>() {
@Override
public Pair<Boolean, GroovyResolveResult[]> compute() {
return doResolveByShape(false, null);
}
});
}
private Pair<Boolean, GroovyResolveResult[]> doResolveByShape(boolean allVariants, @Nullable GrExpression upToArgument) {
@@ -593,7 +593,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
if (result!=null) return result;
final PsiType inferred = refExpr.getQualifier() == null ? TypeInferenceHelper.getInferredType(refExpr) : null;
final PsiType inferred = refExpr.getQualifier() == null ? TypeInferenceHelper.getCurrentContext().getVariableType(refExpr) : null;
final PsiType nominal = refExpr.getNominalType();
if (inferred == null || PsiType.NULL.equals(inferred)) {
if (nominal == null) {
@@ -772,7 +772,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl<GrExpressi
}
public GroovyResolveResult advancedResolve() {
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, POLY_RESOLVER, true, false);
ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, false, POLY_RESOLVER);
return results.length == 1 ? (GroovyResolveResult)results[0] : GroovyResolveResult.EMPTY_RESULT;
}
@@ -12,11 +12,13 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisSuperReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
/**
* @author Maxim.Medvedev
@@ -56,7 +58,7 @@ public abstract class GrThisSuperReferenceExpressionBase extends GrExpressionImp
@Override
public PsiElement resolve() {
final ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, OUR_RESOLVER, false, false);
final ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, false, OUR_RESOLVER);
if (results.length == 1) return results[0].getElement();
return null;
}
@@ -117,7 +119,7 @@ public abstract class GrThisSuperReferenceExpressionBase extends GrExpressionImp
public ResolveResult[] resolve(@NotNull GrThisSuperReferenceExpressionBase ref, boolean incompleteCode) {
final PsiElement resolved = ref.resolveInner();
if (resolved == null) return ResolveResult.EMPTY_ARRAY;
return new ResolveResult[]{new GroovyResolveResultImpl(resolved, true)};
return new GroovyResolveResult[]{new GroovyResolveResultImpl(resolved, true)};
}
}
}
@@ -37,6 +37,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpres
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
@@ -123,7 +124,7 @@ public class GrUnaryExpressionImpl extends GrExpressionImpl implements GrUnaryEx
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(this, OUR_RESOLVER, false, incompleteCode);
return TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, OUR_RESOLVER);
}
@Override
@@ -242,7 +242,7 @@ public class GrIndexPropertyImpl extends GrExpressionImpl implements GrIndexProp
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(myReference, RESOLVER, false, incompleteCode);
return TypeInferenceHelper.getCurrentContext().multiResolve(myReference, incompleteCode, RESOLVER);
}
public PsiType getType() {
@@ -35,6 +35,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCa
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -185,6 +186,6 @@ public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafe
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
return (GroovyResolveResult[])ResolveCache.getInstance(getProject()).resolveWithCaching(this, OUR_RESOLVER, false, incompleteCode);
return TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, OUR_RESOLVER);
}
}
@@ -50,6 +50,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrReferenceElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint;
@@ -113,7 +114,7 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
@Nullable
public PsiElement resolve() {
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, true, false);
ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, false, RESOLVER);
return results.length == 1 ? results[0].getElement() : null;
}
@@ -544,13 +545,13 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
private static final OurResolver RESOLVER = new OurResolver();
public GroovyResolveResult advancedResolve() {
ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, true, false);
ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, false, RESOLVER);
return results.length == 1 ? (GroovyResolveResult) results[0] : GroovyResolveResult.EMPTY_RESULT;
}
@NotNull
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
final ResolveResult[] results = ResolveCache.getInstance(getProject()).resolveWithCaching(this, RESOLVER, true, incompleteCode);
final ResolveResult[] results = TypeInferenceHelper.getCurrentContext().multiResolve(this, incompleteCode, RESOLVER);
if (results.length == 0) {
return GroovyResolveResult.EMPTY_ARRAY;
}