diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java index 306bf6e8fb9..bbd920f329e 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetReferenceExpression.java @@ -1,14 +1,19 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; +import com.intellij.psi.*; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import java.util.Collection; + +import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.DESCRIPTOR_TO_DECLARATION; + /** * @author abreslav */ @@ -21,15 +26,41 @@ public abstract class JetReferenceExpression extends JetExpression { JetFile file = (JetFile) getContainingFile(); BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, this); - return psiElement == null - ? file - : psiElement; + if (psiElement != null) { + return psiElement; + } + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, this); + if (declarationDescriptors != null) return null; + return file; + } + + protected ResolveResult[] doMultiResolve() { + JetFile file = (JetFile) getContainingFile(); + BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file); + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, this); + assert declarationDescriptors != null; + ResolveResult[] results = new ResolveResult[declarationDescriptors.size()]; + int i = 0; + for (DeclarationDescriptor descriptor : declarationDescriptors) { + PsiElement element = bindingContext.get(DESCRIPTOR_TO_DECLARATION, descriptor); + if (element != null) { + results[i] = new PsiElementResolveResult(element, true); + i++; + } + } + return results; } @Override public abstract PsiReference getReference(); - protected abstract class JetPsiReference implements PsiReference { + protected abstract class JetPsiReference implements PsiPolyVariantReference { + + @NotNull + @Override + public ResolveResult[] multiResolve(boolean incompleteCode) { + return doMultiResolve(); + } @Override public PsiElement resolve() { @@ -68,4 +99,10 @@ public abstract class JetReferenceExpression extends JetExpression { return false; } } + +// protected abstract class JetPsiMultiReference extends JetPsiReference implements PsiPolyVariantReference { +// @NotNull +// @Override +// public abstract ResolveResult[] multiResolve(boolean incompleteCode); +// } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index d85127b039f..01244223f3e 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -19,7 +19,10 @@ public interface BindingContext { WritableSlice> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE"); WritableSlice TYPE = Slices.createSimpleSlice("TYPE"); WritableSlice EXPRESSION_TYPE = new BasicWritableSlice("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING); + WritableSlice REFERENCE_TARGET = new BasicWritableSlice("REFERENCE_TARGET", RewritePolicy.DO_NOTHING); + WritableSlice> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING); + WritableSlice AUTOCAST = Slices.createSimpleSlice("AUTOCAST"); WritableSlice RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE"); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 090e81903cd..2cc6a9e7689 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -18,6 +18,7 @@ import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE; @@ -217,6 +218,11 @@ public class CallResolver { trace.getErrorHandler().genericError(reference.getNode(), message); } + @Override + public void recordAmbiguity(BindingTrace trace, Collection candidates) { + trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates); + } + }; for (ResolutionTask task : prioritizedTasks) { TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace); @@ -485,6 +491,9 @@ public class CallResolver { tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder); } + + tracing.recordAmbiguity(trace, successfulCandidates.keySet()); + return OverloadResolutionResult.ambiguity(successfulCandidates.keySet()); } } @@ -502,6 +511,7 @@ public class CallResolver { } tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder); + tracing.recordAmbiguity(trace, failedCandidates); return OverloadResolutionResult.manyFailedCandidates(failedCandidates); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java b/idea/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java index 331bd52b239..09fed95601d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/calls/TracingStrategy.java @@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.resolve.BindingTrace; +import java.util.Collection; + /** * @author abreslav */ @@ -19,4 +21,6 @@ import org.jetbrains.jet.lang.resolve.BindingTrace; void reportUnresolvedReference(@NotNull BindingTrace trace); void reportErrorOnReference(BindingTrace trace, String message); + + void recordAmbiguity(BindingTrace trace, Collection candidates); } diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java index cfefc281ee1..f669687dda1 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/DebugInfoAnnotator.java @@ -3,7 +3,6 @@ package org.jetbrains.jet.plugin.annotations; import com.google.common.collect.Sets; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; @@ -15,10 +14,14 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.JetHighlighter; +import java.util.Collection; import java.util.Set; +import static org.jetbrains.jet.lang.resolve.BindingContext.AMBIGUOUS_REFERENCE_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET; import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.jet.lexer.JetTokens.*; @@ -27,8 +30,8 @@ import static org.jetbrains.jet.lexer.JetTokens.*; */ public class DebugInfoAnnotator implements Annotator { - private static volatile boolean debugInfoEnabled = !ApplicationManager.getApplication().isUnitTestMode(); - public static final TokenSet EXCLUDED = TokenSet.create(COLON, AS_KEYWORD, AS_SAFE); + private static volatile boolean debugInfoEnabled = true;//!ApplicationManager.getApplication().isUnitTestMode(); + public static final TokenSet EXCLUDED = TokenSet.create(COLON, AS_KEYWORD, AS_SAFE, IS_KEYWORD, NOT_IS, OROR, ANDAND, EQ, EQEQEQ, EXCLEQEQEQ, ELVIS); public static void setDebugInfoEnabled(boolean value) { debugInfoEnabled = value; @@ -64,15 +67,39 @@ public class DebugInfoAnnotator implements Annotator { if (expression instanceof JetSimpleNameExpression) { JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) expression; IElementType elementType = expression.getNode().getElementType(); - if (elementType == JetNodeTypes.OPERATION_REFERENCE && EXCLUDED.contains(nameExpression.getReferencedNameElementType())) { - return; + if (elementType == JetNodeTypes.OPERATION_REFERENCE) { + IElementType referencedNameElementType = nameExpression.getReferencedNameElementType(); + if (EXCLUDED.contains(referencedNameElementType)) { + return; + } + if (JetTokens.LABELS.contains(referencedNameElementType)) return; } } + + String target = null; DeclarationDescriptor declarationDescriptor = bindingContext.get(REFERENCE_TARGET, expression); - boolean resolved = declarationDescriptor != null; + if (declarationDescriptor != null) { + target = declarationDescriptor.toString(); + } + else { + PsiElement labelTarget = bindingContext.get(LABEL_TARGET, expression); + if (labelTarget != null) { + target = labelTarget.getText(); + } + else { + Collection declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression); + if (declarationDescriptors != null) { + target = "[" + declarationDescriptors.size() + " descriptors]"; + } + } + } + boolean resolved = target != null; boolean unresolved = unresolvedReferences.contains(expression); +// if (ErrorUtils.isError(declarationDescriptor)) { +// holder.createErrorAnnotation() +// } if (resolved && unresolved) { - holder.createErrorAnnotation(expression, "Reference marked as unresolved is actually resolved to " + declarationDescriptor).setTextAttributes(JetHighlighter.JET_DEBUG_INFO); + holder.createErrorAnnotation(expression, "Reference marked as unresolved is actually resolved to " + target).setTextAttributes(JetHighlighter.JET_DEBUG_INFO); } else if (!resolved && !unresolved) { holder.createErrorAnnotation(expression, "Reference is not resolved to anything, but is not marked unresolved").setTextAttributes(JetHighlighter.JET_DEBUG_INFO);