java resolve: ensure cached all qualifiers do not lead to cached types based on ThreadLocalTypes values

fixes failed check for different types returned on different threads (see JavaResolveCache#reportUnstableType)

GitOrigin-RevId: a5efd5e5a9657ad55c74e413185959c517e341e8
This commit is contained in:
Anna Kozlova
2019-09-01 17:03:16 +00:00
committed by intellij-monorepo-bot
parent e9944a9b8a
commit 55426d88a9
3 changed files with 36 additions and 2 deletions
@@ -6,6 +6,8 @@ import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
@@ -242,8 +244,11 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
protected void elementFinished(@NotNull PsiElement element) {
if (!(element instanceof PsiReferenceExpressionImpl)) return;
PsiReferenceExpressionImpl chainedQualifier = (PsiReferenceExpressionImpl)element;
ourQualifierCache.get()
.put(chainedQualifier, resolveCache.resolveWithCaching(chainedQualifier, INSTANCE, false, false, containingFile));
RecursionGuard.StackStamp stamp = RecursionManager.markStack();
ResolveResult[] res = resolveCache.resolveWithCaching(chainedQualifier, INSTANCE, false, false, containingFile);
if (stamp.mayCacheNow()) {
ourQualifierCache.get().put(chainedQualifier, res);
}
}
// walk only qualifiers, not their argument and other associated stuff
@@ -0,0 +1,10 @@
import java.util.*;
import java.util.stream.*;
class MyTest {
void m(Map<String, BladeInjectionInfo> directiveInfos){
Map<String, BladeInjectionInfo> lowerCaseDirectiveInfos = directiveInfos.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.get<caret>Key().toLowerCase(Locale.ENGLISH),
entry -> entry.getValue(), (a, b) -> b));
}
}
@@ -38,6 +38,25 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
doTestAllMethodCallExpressions();
}
public void testForbidCachingForAllQualifiersWhenDependOnThreadLocalTypes() {
configure();
PsiMethodCallExpression getKeyCall =
PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiMethodCallExpression.class);
PsiLambdaExpression l1 = PsiTreeUtil.getParentOfType(getKeyCall, PsiLambdaExpression.class);
PsiLambdaExpression l2 = (PsiLambdaExpression)PsiTreeUtil.skipWhitespacesForward(l1.getNextSibling());
//ensure chained method calls inside lambda are resolved
//including entry.getKey()
//these calls depend on ThreadLocalTypes and should not be cached
//note that their types should not be cached as well
l2.getFunctionalInterfaceType();
//check that getKey was not cached in the line above
PsiType type = getKeyCall.getType();
assertEquals(CommonClassNames.JAVA_LANG_STRING, type.getCanonicalText());
}
public void testLambdaParameterTypeDetection() {
configure();
PsiReferenceExpression referenceExpression =