tests fixed, restored ourGraphGuard for IDEA-CR-33227

This commit is contained in:
Alexey Kudravtsev
2018-06-04 16:57:57 +03:00
parent a1c859de11
commit 6abeba7858
5 changed files with 54 additions and 38 deletions
@@ -30,9 +30,7 @@ import com.intellij.psi.scope.PsiConflictResolver;
import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
@@ -158,8 +156,9 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
}
private static JavaResolveResult getStaticFactory(@NotNull PsiNewExpression newExpression, @NotNull PsiElement context) {
return JavaResolveCache.getInstance(newExpression.getProject()).getNewExpressionStaticFactory(newExpression, context,
PsiDiamondTypeImpl::getStaticFactoryCandidateInfo);
return context != newExpression || MethodCandidateInfo.isOverloadCheck() ? getStaticFactoryCandidateInfo(newExpression, context) :
JavaResolveCache.getInstance(newExpression.getProject()).getNewExpressionStaticFactory(newExpression,
newExp -> getStaticFactoryCandidateInfo(newExp, newExp));
}
public static DiamondInferenceResult resolveInferredTypesNoCheck(@NotNull PsiNewExpression newExpression, @NotNull PsiElement context) {
@@ -44,7 +44,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.lang.ref.Reference;
import java.util.*;
import java.util.function.BiFunction;
public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements PsiField, PsiVariableEx, Queryable {
private volatile Reference<PsiType> myCachedType;
@@ -266,15 +265,6 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
}
private static class OurConstValueComputer implements BiFunction<PsiFieldImpl, Set<PsiVariable>, Object> {
private static final OurConstValueComputer INSTANCE = new OurConstValueComputer();
@Override
public Object apply(PsiFieldImpl variable, Set<PsiVariable> visitedVars) {
return variable.doComputeConstantValue(visitedVars);
}
}
@Nullable
private Object doComputeConstantValue(@Nullable Set<PsiVariable> visitedVars) {
PsiType type = getType();
@@ -295,7 +285,7 @@ public class PsiFieldImpl extends JavaStubPsiElement<PsiFieldStub> implements Ps
public Object computeConstantValue(Set<PsiVariable> visitedVars) {
if (!hasModifierProperty(PsiModifier.FINAL)) return null;
return JavaResolveCache.getInstance(getProject()).computeConstantValueWithCaching(this, visitedVars, OurConstValueComputer.INSTANCE);
return JavaResolveCache.getInstance(getProject()).getFieldConstantValue(this, visitedVars, (field, variables)->field.doComputeConstantValue(variables));
}
@Override
@@ -22,6 +22,7 @@ import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
import com.intellij.psi.impl.source.resolve.JavaResolveCache;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.tree.IElementType;
@@ -38,7 +39,8 @@ import java.lang.ref.WeakReference;
import java.util.List;
public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeElement {
@SuppressWarnings("UnusedDeclaration")
/** created implicitly by {@link JavaElementType.JavaCompositeElementType#createCompositeNode()} */
@SuppressWarnings("UnusedDeclaration")
public PsiTypeElementImpl() {
this(JavaElementType.TYPE);
}
@@ -60,7 +62,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
@Override
@NotNull
public PsiType getType() {
return CachedValuesManager.getCachedValue(this, () -> CachedValueProvider.Result.create(calculateType(), PsiModificationTracker.MODIFICATION_COUNT));
return JavaResolveCache.getInstance(getProject()).getTypeElementType(this, element -> element.calculateType());
}
@NotNull
@@ -31,6 +31,7 @@ import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.PsiFieldImpl;
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.impl.source.PsiTypeElementImpl;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.infos.MethodCandidateInfo;
@@ -45,6 +46,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
@@ -53,10 +55,11 @@ public class JavaResolveCache {
private static final NotNullLazyKey<JavaResolveCache, Project> INSTANCE_KEY = ServiceManager.createLazyKey(JavaResolveCache.class);
private final AtomicReference<Map<PsiExpression, PsiType>> myCalculatedTypes = new AtomicReference<>();
private final AtomicReference<Map<PsiExpression, PsiType>> myExpressionTypes = new AtomicReference<>();
private final AtomicReference<Map<PsiTypeElementImpl, Object>> myTypeElementTypes = new AtomicReference<>(); // PsiType or NULL
private final AtomicReference<Map<PsiFieldImpl,Object>> myFieldToConstValueMapPhysical = new AtomicReference<>();
private final AtomicReference<Map<PsiFieldImpl,Object>> myFieldToConstValueMapNonPhysical = new AtomicReference<>();
private final AtomicReference<Map<PsiNewExpression, Object>> myStaticFactories = new AtomicReference<>(); // JavaResolveResult or NULL
private final AtomicReference<ConcurrentMap<PsiNewExpression, Object>> myStaticFactories = new AtomicReference<>(); // JavaResolveResult or NULL
private final AtomicReference<Map<PsiCall, Object>> myTopLevelInferenceSessions = new AtomicReference<>(); // InferenceSession or NULL
private static final Object NULL = Key.create("NULL"); // the object to put into maps to denote resolvers return null
@@ -77,7 +80,8 @@ public class JavaResolveCache {
}
private void clearCaches(boolean isPhysical) {
myCalculatedTypes.set(null);
myExpressionTypes.set(null);
myTypeElementTypes.set(null);
if (isPhysical) {
myFieldToConstValueMapPhysical.set(null);
}
@@ -91,8 +95,8 @@ public class JavaResolveCache {
final boolean isOverloadCheck = MethodCandidateInfo.isOverloadCheck() || LambdaUtil.isLambdaParameterCheck();
final boolean polyExpression = PsiPolyExpressionUtil.isPolyExpression(expr);
Map<PsiExpression, PsiType> map = myCalculatedTypes.get();
if (map == null) map = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, ContainerUtil.createConcurrentWeakKeySoftValueMap());
Map<PsiExpression, PsiType> map = myExpressionTypes.get();
if (map == null) map = ConcurrencyUtil.cacheOrGet(myExpressionTypes, ContainerUtil.createConcurrentWeakKeySoftValueMap());
PsiType type = isOverloadCheck && polyExpression ? null : map.get(expr);
if (type == null) {
@@ -136,9 +140,9 @@ public class JavaResolveCache {
}
@Nullable
public Object computeConstantValueWithCaching(@NotNull PsiFieldImpl variable,
@Nullable Set<PsiVariable> visitedVars,
@NotNull BiFunction<? super PsiFieldImpl, ? super Set<PsiVariable>, Object> computer){
public Object getFieldConstantValue(@NotNull PsiFieldImpl variable,
@Nullable Set<PsiVariable> visitedVars,
@NotNull BiFunction<? super PsiFieldImpl, ? super Set<PsiVariable>, Object> computer){
boolean physical = variable.isPhysical();
AtomicReference<Map<PsiFieldImpl, Object>> ref = physical ? myFieldToConstValueMapPhysical : myFieldToConstValueMapNonPhysical;
@@ -155,22 +159,24 @@ public class JavaResolveCache {
}
@Nullable
public JavaResolveResult getNewExpressionStaticFactory(@NotNull PsiNewExpression newExpression, @NotNull PsiElement context, @NotNull BiFunction<? super PsiNewExpression, ? super PsiElement, ? extends JavaResolveResult> computer) {
AtomicReference<Map<PsiNewExpression, Object>> ref = myStaticFactories;
Map<PsiNewExpression, Object> map = ref.get();
public JavaResolveResult getNewExpressionStaticFactory(@NotNull PsiNewExpression newExpression,
@NotNull Function<? super PsiNewExpression, ? extends JavaResolveResult> computer) {
AtomicReference<ConcurrentMap<PsiNewExpression, Object>> ref = myStaticFactories;
ConcurrentMap<PsiNewExpression, Object> map = ref.get();
if (map == null) map = ConcurrencyUtil.cacheOrGet(ref, ContainerUtil.createConcurrentWeakMap());
Object cached = map.get(newExpression);
if (cached == null) {
JavaResolveResult result = computer.fun(newExpression);
cached = ConcurrencyUtil.cacheOrGet(map, newExpression, result == null ? NULL : result);
}
if (cached == NULL) return null;
if (cached != null) return (JavaResolveResult)cached;
JavaResolveResult result = computer.apply(newExpression, context);
map.put(newExpression, result == null ? NULL : result);
return result;
return (JavaResolveResult)cached;
}
@Nullable
public InferenceSession getTopLevelInferenceSession(@NotNull PsiCall topLevelCall, @NotNull Function<? super PsiCall, ? extends InferenceSession> computer) {
public InferenceSession getTopLevelInferenceSession(@NotNull PsiCall topLevelCall,
@NotNull Function<? super PsiCall, ? extends InferenceSession> computer) {
AtomicReference<Map<PsiCall, Object>> ref = myTopLevelInferenceSessions;
Map<PsiCall, Object> map = ref.get();
if (map == null) map = ConcurrencyUtil.cacheOrGet(ref, ContainerUtil.createConcurrentWeakMap());
@@ -183,4 +189,19 @@ public class JavaResolveCache {
map.put(topLevelCall, result == null ? NULL : result);
return result;
}
public PsiType getTypeElementType(@NotNull PsiTypeElementImpl typeElement,
@NotNull Function<? super PsiTypeElementImpl, ? extends PsiType> computer) {
AtomicReference<Map<PsiTypeElementImpl, Object>> ref = myTypeElementTypes;
Map<PsiTypeElementImpl, Object> map = ref.get();
if (map == null) map = ConcurrencyUtil.cacheOrGet(ref, ContainerUtil.createConcurrentWeakMap());
Object cached = map.get(typeElement);
if (cached == NULL) return null;
if (cached != null) return (PsiType)cached;
PsiType result = computer.fun(typeElement);
map.put(typeElement, result == null ? NULL : result);
return result;
}
}
@@ -76,9 +76,13 @@ public class InferenceSessionContainer {
//But overload resolution can depend on type of lambda parameter. As it can't depend on lambda body,
//traversing down would stop at lambda level and won't take into account overloaded method
!MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argumentList)) {
final PsiCall topLevelCall =
parent instanceof PsiExpression && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression)parent) ? null :
LambdaUtil.treeWalkUp(parent);
final PsiCall topLevelCall = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(parent, false,
() -> {
if (parent instanceof PsiExpression && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression)parent)) {
return null;
}
return LambdaUtil.treeWalkUp(parent);
});
if (topLevelCall != null) {
InferenceSession session;