From 08206aacb2e90b55deb594615af7ede78d2d9700 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 23 Oct 2009 17:04:19 +0400 Subject: [PATCH] ambiguous references --- .../daemon/impl/analysis/HighlightUtil.java | 22 ++++++- .../resolve/ClassResolverProcessor.java | 57 +++++++++---------- .../com/intellij/psi/JavaResolveResult.java | 5 +- .../src/messages/JavaErrorMessages.properties | 1 + 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 29637c5ba1c7..1884d46fd5a3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -27,6 +27,7 @@ import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.quickfix.*; +import com.intellij.codeInsight.highlighting.HighlightUsagesDescriptionLocation; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.QuickFixFactory; import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; @@ -507,7 +508,7 @@ public class HighlightUtil { IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, valueType, false); QuickFixAction.registerQuickFixAction(errorResult, fix); } - } + } else { errorResult = checkAssignability(returnType, valueType, returnValue, statement); if (errorResult != null && valueType != null) { @@ -517,7 +518,7 @@ public class HighlightUtil { QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithArrayFix(null){ @Override protected PsiExpression getExpression(final PsiElement element) { - return returnValue != null && returnValue.isValid() ? returnValue : null; + return returnValue.isValid() ? returnValue : null; } }); } @@ -1857,7 +1858,16 @@ public class HighlightUtil { // do not highlight unknown packages - javac does not care about illegal package names if (isInsidePackageStatement(refName)) return null; if (result.isPackagePrefixPackageReference()) return null; - String description = JavaErrorMessages.message("cannot.resolve.symbol", refName.getText()); + JavaResolveResult[] results = ref.multiResolve(true); + String description; + if (results.length > 1) { + String t1 = format(results[0].getElement()); + String t2 = format(results[1].getElement()); + description = JavaErrorMessages.message("ambiguous.reference", refName.getText(), t1, t2); + } + else { + description = JavaErrorMessages.message("cannot.resolve.symbol", refName.getText()); + } HighlightInfoType type = HighlightInfoType.WRONG_REF; if (PsiUtil.isInsideJavadocComment(ref)) return null; @@ -1907,6 +1917,12 @@ public class HighlightUtil { return highlightInfo; } + private static String format(PsiElement element) { + if (element instanceof PsiClass) return formatClass((PsiClass)element); + if (element instanceof PsiMethod) return formatMethod((PsiMethod)element); + return ElementDescriptionUtil.getElementDescription(element, HighlightUsagesDescriptionLocation.INSTANCE); + } + private static boolean isInsidePackageStatement(PsiElement element) { while (element != null) { if (element instanceof PsiPackageStatement) return true; diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java index 88285fd24d78..52494621920a 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java @@ -91,39 +91,38 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi } public boolean execute(PsiElement element, ResolveState state) { - if (element instanceof PsiClass) { - final PsiClass aClass = (PsiClass)element; - final String name = aClass.getName(); - if (myClassName.equals(name)) { - if (myCandidates == null) { - myCandidates = new SmartList(); - } - else { - String fqName = aClass.getQualifiedName(); - if (fqName != null) { - for (ClassCandidateInfo info : myCandidates) { - final PsiClass otherClass = info.getElement(); - assert otherClass != null; - if (fqName.equals(otherClass.getQualifiedName())) { - return true; - } - final PsiClass containingclass1 = aClass.getContainingClass(); - final PsiClass containingclass2 = otherClass.getContainingClass(); - if (containingclass1 != null && containingclass2 != null && containingclass2.isInheritor(containingclass1, true)) { - //shadowing - return true; - } + if (!(element instanceof PsiClass)) return true; + final PsiClass aClass = (PsiClass)element; + final String name = aClass.getName(); + if (myClassName.equals(name)) { + if (myCandidates == null) { + myCandidates = new SmartList(); + } + else { + String fqName = aClass.getQualifiedName(); + if (fqName != null) { + for (ClassCandidateInfo info : myCandidates) { + final PsiClass otherClass = info.getElement(); + assert otherClass != null; + if (fqName.equals(otherClass.getQualifiedName())) { + return true; + } + final PsiClass containingclass1 = aClass.getContainingClass(); + final PsiClass containingclass2 = otherClass.getContainingClass(); + if (containingclass1 != null && containingclass2 != null && containingclass2.isInheritor(containingclass1, true)) { + //shadowing + return true; } } } - - boolean accessible = myPlace == null || checkAccessibility(aClass); - myHasAccessibleCandidate |= accessible; - myHasInaccessibleCandidate |= !accessible; - myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext)); - myResult = null; - return !accessible; } + + boolean accessible = myPlace == null || checkAccessibility(aClass); + myHasAccessibleCandidate |= accessible; + myHasInaccessibleCandidate |= !accessible; + myCandidates.add(new ClassCandidateInfo(aClass, state.get(PsiSubstitutor.KEY), !accessible, myCurrentFileContext)); + myResult = null; + //return !accessible; } return true; } diff --git a/java/openapi/src/com/intellij/psi/JavaResolveResult.java b/java/openapi/src/com/intellij/psi/JavaResolveResult.java index a805e27fb0a1..6a17a7d2dfe3 100644 --- a/java/openapi/src/com/intellij/psi/JavaResolveResult.java +++ b/java/openapi/src/com/intellij/psi/JavaResolveResult.java @@ -28,15 +28,14 @@ public interface JavaResolveResult extends ResolveResult { /** * Substitutor providing values of type parameters occuring * in {@link #getElement()}. - * @return */ PsiSubstitutor getSubstitutor(); boolean isPackagePrefixPackageReference(); /** - * Checks whether {@link #getElement()} is accessible from reference. - * @return + * @return true if {@link #getElement()} is accessible from reference. + * */ boolean isAccessible(); diff --git a/resources-en/src/messages/JavaErrorMessages.properties b/resources-en/src/messages/JavaErrorMessages.properties index 187bcab503f5..998187d6c289 100644 --- a/resources-en/src/messages/JavaErrorMessages.properties +++ b/resources-en/src/messages/JavaErrorMessages.properties @@ -126,6 +126,7 @@ exception.is.never.thrown=Exception ''{0}'' is never thrown in the method wrong.method.arguments=''{0}'' in ''{1}'' cannot be applied to ''{2}'' method.call.expected=Method call expected ambiguous.method.call=Ambiguous method call: both ''{0}'' and ''{1}'' match +ambiguous.reference=Reference to ''{0}'' is ambiguous, both ''{1}'' and ''{2}'' match cannot.resolve.method=Cannot resolve method ''{0}'' missing.method.body=Missing method body, or declare abstract abstract.method.in.non.abstract.class=Abstract method in non-abstract class