ambiguity conflict resolution for class/package (IDEA-151859;IDEA-184289)

This commit is contained in:
Anna.Kozlova
2017-12-28 17:53:58 +01:00
parent a1239e3f1f
commit c522bdfb38
16 changed files with 136 additions and 12 deletions

View File

@@ -383,11 +383,8 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
if (result.length == 0 && (kind == CLASS_OR_PACKAGE_NAME_KIND || kind == CLASS_NAME_KIND)) {
String qualifiedName = referenceElement.getClassNameText();
PsiClass aClass = qualifiedName != null && !StringUtil.isEmptyOrSpaces(StringUtil.getPackageName(qualifiedName))
? JavaPsiFacade.getInstance(referenceElement.getProject()).findClass(qualifiedName, referenceElement.getResolveScope())
: null;
if (aClass != null) {
result = new JavaResolveResult[] {new CandidateInfo(aClass, PsiSubstitutor.EMPTY, referenceElement, false)};
if (qualifiedName != null) {
result = tryClassResult(qualifiedName, referenceElement, result);
}
}
@@ -397,6 +394,23 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
}
}
public static JavaResolveResult[] tryClassResult(String qualifiedName, PsiElement referenceElement, JavaResolveResult[] result) {
String packageName = StringUtil.getPackageName(qualifiedName);
Project project = referenceElement.getProject();
if (!StringUtil.isEmptyOrSpaces(packageName)) {
PsiClass referencedClass = PsiResolveHelper.SERVICE.getInstance(project).resolveReferencedClass(packageName, referenceElement);
//class is always preferred to package => when such a class exists, the qualified name can point to inner class only and that check must already have been failed
if (referencedClass != null) {
return result;
}
PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(qualifiedName, referenceElement.getResolveScope());
if (aClass != null) {
result = new JavaResolveResult[] {new CandidateInfo(aClass, PsiSubstitutor.EMPTY, referenceElement, false)};
}
}
return result;
}
@Override
@NotNull
public JavaResolveResult advancedResolve(final boolean incompleteCode) {
@@ -614,6 +628,11 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
else if (facade.findClass(qName, getResolveScope()) == null && !preserveQualification) {
return this;
}
else if (facade.getResolveHelper().resolveReferencedClass(qName, this) == null &&
facade.getResolveHelper().resolveReferencedClass(StringUtil.getPackageName(qName), this) != null) {
qName = aClass.getName();
assert qName != null : aClass;
}
String text = qName;
PsiReferenceParameterList parameterList = getParameterList();

View File

@@ -283,11 +283,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
if (result.length == 0 && variable == null) {
String qualifiedName = getQualifiedName();
PsiClass aClass = qualifiedName != null && !StringUtil.isEmptyOrSpaces(StringUtil.getPackageName(qualifiedName))
? JavaPsiFacade.getInstance(getProject()).findClass(qualifiedName, getResolveScope())
: null;
if (aClass != null) {
result = new JavaResolveResult[] {new CandidateInfo(aClass, PsiSubstitutor.EMPTY, this, false)};
if (qualifiedName != null) {
result = PsiJavaCodeReferenceElementImpl.tryClassResult(qualifiedName, this, result);
}
}
@@ -675,7 +672,8 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
if (isReferenceTo(element)) return this;
final PsiManager manager = getManager();
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
final PsiJavaParserFacade parserFacade = facade.getParserFacade();
if (element instanceof PsiClass) {
final boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(getProject()).useFQClassNames() && isFullyQualified(this);
String qName = ((PsiClass)element).getQualifiedName();
@@ -685,6 +683,11 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
else if (JavaPsiFacade.getInstance(manager.getProject()).findClass(qName, getResolveScope()) == null && !preserveQualification) {
return this;
}
else if (facade.getResolveHelper().resolveReferencedClass(qName, this) == null &&
facade.getResolveHelper().resolveReferencedClass(StringUtil.getPackageName(qName), this) != null) {
qName = ((PsiClass)element).getName();
assert qName != null : element;
}
PsiExpression ref = parserFacade.createExpressionFromText(qName, this);
getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode());
final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(manager.getProject());

View File

@@ -0,0 +1,4 @@
package c;
class Test {
a.<error descr="Cannot resolve symbol 'b'">b</error> myB;
}

View File

@@ -0,0 +1,6 @@
package c;
import c.d.*;
class Test {
a.<error descr="Cannot resolve symbol 'b'">b</error> myB;
}

View File

@@ -0,0 +1,9 @@
package a;
public class a extends B {
public static void main(String[] args) {
a f = B.create();
}
}

View File

@@ -0,0 +1,6 @@
package a;
public class B {
public static a create() {
return new a();
}
}

View File

@@ -0,0 +1,12 @@
package a;
public class a extends B {
public static a create() {
return new a();
}
public static void main(String[] args) {
a f = a.create();
}
}

View File

@@ -0,0 +1,3 @@
package a;
public class B {
}

View File

@@ -0,0 +1,11 @@
package Fabric;
public class Fabric extends MetaFabric {
public static Fabric create() {
return new Fabric();
}
public static void main(String[] args) {
Fabric f = Fabric.create();
}
}

View File

@@ -0,0 +1,2 @@
package Fabric;
public class MetaFabric { }

View File

@@ -0,0 +1,2 @@
package Fabric;
public class AFabric { }

View File

@@ -0,0 +1,11 @@
package Fabric;
public class Fabric extends AFabric {
public static Fabric create() {
return new Fabric();
}
public static void main(String[] args) {
Fabric f = Fabric.create();
}
}

View File

@@ -41,7 +41,7 @@ class ClassInDefaultPackageHighlightingTest : LightCodeInsightFixtureTestCase()
doTest("""
class Test {{
new conflict();
new conflict.C();
new conflict.<error descr="Cannot resolve symbol 'C'">C</error>();
}}""".trimIndent())
}

View File

@@ -140,6 +140,20 @@ public class LightAdvHighlightingFixtureTest extends LightCodeInsightFixtureTest
myFixture.checkHighlighting();
}
public void testClassPackageConflict() {
myFixture.addClass("package a; public class b {}");
myFixture.addClass("package c; public class a {}");
myFixture.configureByFile(getTestName(false) + ".java");
myFixture.checkHighlighting();
}
public void testClassPackageConflict1() {
myFixture.addClass("package a; public class b {}");
myFixture.addClass("package c.d; public class a {}");
myFixture.configureByFile(getTestName(false) + ".java");
myFixture.checkHighlighting();
}
@Override
protected String getBasePath() {
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/advFixture";

View File

@@ -100,4 +100,22 @@ public class PullUpMultifileTest extends MultiFileTestCase {
public void testReuseSuperSuperMethod() {
doTest();
}
public void testClassPackageConflict() {
doTest((rootDir, rootAfter) -> {
final PsiClass srcClass = myJavaFacade.findClass("a.a", GlobalSearchScope.allScope(myProject));
assertTrue("Source class not found", srcClass != null);
final PsiClass targetClass = myJavaFacade.findClass("a.B", GlobalSearchScope.allScope(myProject));
assertTrue("Target class not found", targetClass != null);
final PsiMethod[] methods = srcClass.getMethods();
assertTrue("No methods found", methods.length > 0);
final MemberInfo[] membersToMove = new MemberInfo[1];
final MemberInfo memberInfo = new MemberInfo(methods[0]);
memberInfo.setChecked(true);
membersToMove[0] = memberInfo;
new PullUpProcessor(srcClass, targetClass, membersToMove, new DocCommentPolicy(DocCommentPolicy.ASIS)).run();
});
}
}

View File

@@ -43,6 +43,10 @@ public class RenameClassTest extends MultiFileTestCase {
doTest("pack1.MyList", "List");
}
public void testPackageClassConflict() {
doTest("Fabric.AFabric", "MetaFabric");
}
public void testInnerClass() {
doTest("pack1.OuterClass.InnerClass", "NewInnerClass");
}