From 24e17b7bc2eef00cde7ff502158213b5ad7872a3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 30 Jan 2013 16:59:54 +0400 Subject: [PATCH] Resolve to packages obscured by inaccessible class --- .../PsiJavaCodeReferenceElementImpl.java | 34 +++--- .../impl/source/resolve/JavaResolveUtil.java | 14 +++ .../tree/java/PsiReferenceExpressionImpl.java | 106 +++++++++--------- .../packageObscuring/main/Main.java | 12 ++ .../packageObscuring/pkg/sub.java | 9 ++ .../packageObscuring/pkg/sub/Test.java | 7 ++ .../daemon/AdvHighlightingTest.java | 4 + 7 files changed, 111 insertions(+), 75 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/main/Main.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub/Test.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 4ce16d62ffce..f449956ed035 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -31,6 +31,7 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.resolve.ClassResolverProcessor; +import com.intellij.psi.impl.source.resolve.JavaResolveUtil; import com.intellij.psi.impl.source.resolve.ResolveCache; import com.intellij.psi.impl.source.resolve.VariableResolverProcessor; import com.intellij.psi.impl.source.tree.*; @@ -345,16 +346,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } - if (result.length > 0 && result[0].getElement() instanceof PsiClass) { - PsiType[] parameters = ((PsiJavaCodeReferenceElement)ref).getTypeParameters(); - for (int i = 0; i < result.length; i++) { - CandidateInfo resolveResult = (CandidateInfo)result[i]; - PsiElement resultElement = resolveResult.getElement(); - if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) { - result[i] = new CandidateInfo(resolveResult, resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters)); - } - } - } + JavaResolveUtil.substituteResults((PsiJavaCodeReferenceElement)ref, result); return result; } @@ -449,7 +441,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme final PsiElement classNameElement = getReferenceNameElement(); if (!(classNameElement instanceof PsiIdentifier)) return JavaResolveResult.EMPTY_ARRAY; final String className = classNameElement.getText(); - final ClassResolverProcessor processor = new ClassResolverProcessor(className, this); PsiScopesUtil.resolveAndWalk(processor, this, null); return processor.getResult(); @@ -464,18 +455,21 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } return new JavaResolveResult[]{new CandidateInfo(aPackage, PsiSubstitutor.EMPTY)}; } - case CLASS_FQ_OR_PACKAGE_NAME_KIND: { - JavaResolveResult[] result = resolve(CLASS_FQ_NAME_KIND); - if (result.length == 0) { - result = resolve(PACKAGE_NAME_KIND); - } - return result; - } + case CLASS_FQ_OR_PACKAGE_NAME_KIND: case CLASS_OR_PACKAGE_NAME_KIND: { - JavaResolveResult[] result = resolve(CLASS_NAME_KIND); - if (result.length == 0) { + int classKind = kind == CLASS_OR_PACKAGE_NAME_KIND ? CLASS_NAME_KIND : CLASS_FQ_NAME_KIND; + JavaResolveResult[] result = resolve(classKind); + + if (result.length == 1 && !result[0].isAccessible()) { + JavaResolveResult[] packageResult = resolve(PACKAGE_NAME_KIND); + if (packageResult.length != 0) { + result = packageResult; + } + } + else if (result.length == 0) { result = resolve(PACKAGE_NAME_KIND); } + return result; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index ff66bde31c9a..b60524d331ee 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -23,6 +23,7 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; +import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.InheritanceUtil; @@ -216,4 +217,17 @@ public class JavaResolveUtil { return true; } + + public static void substituteResults(@NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) { + if (result.length > 0 && result[0].getElement() instanceof PsiClass) { + PsiType[] parameters = ref.getTypeParameters(); + for (int i = 0; i < result.length; i++) { + CandidateInfo resolveResult = (CandidateInfo)result[i]; + PsiElement resultElement = resolveResult.getElement(); + if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) { + result[i] = new CandidateInfo(resolveResult, resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters)); + } + } + } + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java index 7375daa7f057..fdb1609faef4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -34,10 +34,7 @@ import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.source.SourceJavaCodeReference; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; -import com.intellij.psi.impl.source.resolve.ClassResolverProcessor; -import com.intellij.psi.impl.source.resolve.JavaResolveCache; -import com.intellij.psi.impl.source.resolve.ResolveCache; -import com.intellij.psi.impl.source.resolve.VariableResolverProcessor; +import com.intellij.psi.impl.source.resolve.*; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.scope.ElementClassFilter; @@ -187,59 +184,46 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple private static final class OurGenericsResolver implements ResolveCache.PolyVariantResolver { private static final OurGenericsResolver INSTANCE = new OurGenericsResolver(); - @NotNull - private static JavaResolveResult[] _resolve(boolean incompleteCode, PsiReferenceExpressionImpl expression) { - CompositeElement treeParent = expression.getTreeParent(); - IElementType parentType = treeParent == null ? null : treeParent.getElementType(); - expression.resolveAllQualifiers(); - final JavaResolveResult[] result = expression.resolve(parentType); - - if (incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION && result.length == 0) { - return expression.resolve(JavaElementType.REFERENCE_EXPRESSION); - } - - return result; - } - @Override @NotNull public JavaResolveResult[] resolve(@NotNull PsiJavaReference ref, boolean incompleteCode) { - final JavaResolveResult[] result = _resolve(incompleteCode, (PsiReferenceExpressionImpl)ref); - if (result.length > 0 && result[0].getElement() instanceof PsiClass) { - final PsiType[] parameters = ((PsiJavaCodeReferenceElement)ref).getTypeParameters(); - final JavaResolveResult[] newResult = new JavaResolveResult[result.length]; - for (int i = 0; i < result.length; i++) { - final CandidateInfo resolveResult = (CandidateInfo)result[i]; - newResult[i] = new CandidateInfo(resolveResult, resolveResult.getSubstitutor().putAll( - (PsiClass)resolveResult.getElement(), parameters)); - } - return newResult; + PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)ref; + CompositeElement treeParent = expression.getTreeParent(); + IElementType parentType = treeParent == null ? null : treeParent.getElementType(); + resolveAllQualifiers(expression); + JavaResolveResult[] result = expression.resolve(parentType); + + if (result.length == 0 && incompleteCode && parentType != JavaElementType.REFERENCE_EXPRESSION) { + result = expression.resolve(JavaElementType.REFERENCE_EXPRESSION); } + + JavaResolveUtil.substituteResults(expression, result); + return result; } - } - private void resolveAllQualifiers() { - // to avoid SOE, resolve all qualifiers starting from the innermost - PsiElement qualifier = getQualifier(); - if (qualifier == null) return; - final ResolveCache resolveCache = ResolveCache.getInstance(getProject()); - qualifier.accept(new JavaRecursiveElementWalkingVisitor() { - @Override - public void visitReferenceExpression(PsiReferenceExpression expression) { - if (!(expression instanceof PsiReferenceExpressionImpl) || resolveCache.isCached(expression, true, false, true)) { - return; + private static void resolveAllQualifiers(PsiReferenceExpressionImpl expression) { + // to avoid SOE, resolve all qualifiers starting from the innermost + PsiElement qualifier = expression.getQualifier(); + if (qualifier == null) return; + final ResolveCache resolveCache = ResolveCache.getInstance(expression.getProject()); + qualifier.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceExpression(PsiReferenceExpression expression) { + if (!(expression instanceof PsiReferenceExpressionImpl) || resolveCache.isCached(expression, true, false, true)) { + return; + } + visitElement(expression); } - visitElement(expression); - } - @Override - protected void elementFinished(PsiElement element) { - if (!(element instanceof PsiReferenceExpressionImpl)) return; - PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element; - resolveCache.resolveWithCaching(expression, OurGenericsResolver.INSTANCE, false, false); - } - }); + @Override + protected void elementFinished(PsiElement element) { + if (!(element instanceof PsiReferenceExpressionImpl)) return; + PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element; + resolveCache.resolveWithCaching(expression, INSTANCE, false, false); + } + }); + } } @NotNull @@ -250,21 +234,33 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple return result; } - final PsiElement classNameElement = getReferenceNameElement(); - if (!(classNameElement instanceof PsiIdentifier)) return JavaResolveResult.EMPTY_ARRAY; - result = resolveToClass(classNameElement); - if (result.length > 0) { - return result; + PsiElement classNameElement = getReferenceNameElement(); + if (!(classNameElement instanceof PsiIdentifier)) { + return JavaResolveResult.EMPTY_ARRAY; } - return resolveToPackage(); + result = resolveToClass(classNameElement); + if (result.length == 1 && !result[0].isAccessible()) { + JavaResolveResult[] packageResult = resolveToPackage(); + if (packageResult.length != 0) { + result = packageResult; + } + } + else if (result.length == 0) { + result = resolveToPackage(); + } + + return result; } + if (parentType == JavaElementType.METHOD_CALL_EXPRESSION) { return resolveToMethod(); } + if (parentType == JavaElementType.METHOD_REF_EXPRESSION) { return resolve(JavaElementType.REFERENCE_EXPRESSION); } + return resolveToVariable(); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/main/Main.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/main/Main.java new file mode 100644 index 000000000000..ec7d7e6611ae --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/main/Main.java @@ -0,0 +1,12 @@ +package main; + +public class Main { + public static void main(String[] args) { + pkg.sub.Test obj = new pkg.sub.Test(); + obj.m1(); + obj.m2(); + + pkg.sub.Test.s1(); + pkg.sub.Test.s2(); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub.java new file mode 100644 index 000000000000..21764febddbc --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub.java @@ -0,0 +1,9 @@ +package pkg; + +class sub { + public static class Test { + public void m2() { } + + public static void s2() { } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub/Test.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub/Test.java new file mode 100644 index 000000000000..90c5d6ebfb13 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageObscuring/pkg/sub/Test.java @@ -0,0 +1,7 @@ +package pkg.sub; + +public class Test { + public void m1() { } + + public static void s1() { } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java index fef44cf872f4..b513b4732b3c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java @@ -297,4 +297,8 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase { public void testPackageAndClassConflict3() throws Exception { doTest(BASE_PATH + "/packageClassClash/java/lang.java", false, false); } + + public void testPackageObscuring() throws Exception { + doTest(BASE_PATH + "/packageObscuring/main/Main.java", BASE_PATH + "/packageObscuring", false, false); + } }