PolyVariant references on resolution ambiguities
This commit is contained in:
@@ -1,14 +1,19 @@
|
|||||||
package org.jetbrains.jet.lang.psi;
|
package org.jetbrains.jet.lang.psi;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.PsiReference;
|
|
||||||
import com.intellij.util.IncorrectOperationException;
|
import com.intellij.util.IncorrectOperationException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.AnalyzingUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
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
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
@@ -21,15 +26,41 @@ public abstract class JetReferenceExpression extends JetExpression {
|
|||||||
JetFile file = (JetFile) getContainingFile();
|
JetFile file = (JetFile) getContainingFile();
|
||||||
BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file);
|
BindingContext bindingContext = AnalyzingUtils.analyzeFileWithCache(file);
|
||||||
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, this);
|
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, this);
|
||||||
return psiElement == null
|
if (psiElement != null) {
|
||||||
? file
|
return psiElement;
|
||||||
: psiElement;
|
}
|
||||||
|
Collection<? extends DeclarationDescriptor> 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<? extends DeclarationDescriptor> 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
|
@Override
|
||||||
public abstract PsiReference getReference();
|
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
|
@Override
|
||||||
public PsiElement resolve() {
|
public PsiElement resolve() {
|
||||||
@@ -68,4 +99,10 @@ public abstract class JetReferenceExpression extends JetExpression {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// protected abstract class JetPsiMultiReference extends JetPsiReference implements PsiPolyVariantReference {
|
||||||
|
// @NotNull
|
||||||
|
// @Override
|
||||||
|
// public abstract ResolveResult[] multiResolve(boolean incompleteCode);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE");
|
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice("COMPILE_TIME_VALUE");
|
||||||
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice("TYPE");
|
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice("TYPE");
|
||||||
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
|
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
|
||||||
|
|
||||||
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||||
|
WritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>> AMBIGUOUS_REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, Collection<? extends DeclarationDescriptor>>("AMBIGUOUS_REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||||
|
|
||||||
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST");
|
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST");
|
||||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE");
|
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE");
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.jetbrains.jet.resolve.DescriptorRenderer;
|
|||||||
|
|
||||||
import java.util.*;
|
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.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
@@ -217,6 +218,11 @@ public class CallResolver {
|
|||||||
trace.getErrorHandler().genericError(reference.getNode(), message);
|
trace.getErrorHandler().genericError(reference.getNode(), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates) {
|
||||||
|
trace.record(AMBIGUOUS_REFERENCE_TARGET, reference, candidates);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
for (ResolutionTask<D> task : prioritizedTasks) {
|
for (ResolutionTask<D> task : prioritizedTasks) {
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||||
@@ -485,6 +491,9 @@ public class CallResolver {
|
|||||||
|
|
||||||
tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tracing.recordAmbiguity(trace, successfulCandidates.keySet());
|
||||||
|
|
||||||
return OverloadResolutionResult.ambiguity(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.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder);
|
||||||
|
tracing.recordAmbiguity(trace, failedCandidates);
|
||||||
return OverloadResolutionResult.manyFailedCandidates(failedCandidates);
|
return OverloadResolutionResult.manyFailedCandidates(failedCandidates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
@@ -19,4 +21,6 @@ import org.jetbrains.jet.lang.resolve.BindingTrace;
|
|||||||
void reportUnresolvedReference(@NotNull BindingTrace trace);
|
void reportUnresolvedReference(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
void reportErrorOnReference(BindingTrace trace, String message);
|
void reportErrorOnReference(BindingTrace trace, String message);
|
||||||
|
|
||||||
|
<D extends CallableDescriptor> void recordAmbiguity(BindingTrace trace, Collection<D> candidates);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.jetbrains.jet.plugin.annotations;
|
|||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
import com.intellij.lang.annotation.AnnotationHolder;
|
||||||
import com.intellij.lang.annotation.Annotator;
|
import com.intellij.lang.annotation.Annotator;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
import org.jetbrains.jet.plugin.JetHighlighter;
|
import org.jetbrains.jet.plugin.JetHighlighter;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
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.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
import static org.jetbrains.jet.lexer.JetTokens.*;
|
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||||
|
|
||||||
@@ -27,8 +30,8 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
|
|||||||
*/
|
*/
|
||||||
public class DebugInfoAnnotator implements Annotator {
|
public class DebugInfoAnnotator implements Annotator {
|
||||||
|
|
||||||
private static volatile boolean debugInfoEnabled = !ApplicationManager.getApplication().isUnitTestMode();
|
private static volatile boolean debugInfoEnabled = true;//!ApplicationManager.getApplication().isUnitTestMode();
|
||||||
public static final TokenSet EXCLUDED = TokenSet.create(COLON, AS_KEYWORD, AS_SAFE);
|
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) {
|
public static void setDebugInfoEnabled(boolean value) {
|
||||||
debugInfoEnabled = value;
|
debugInfoEnabled = value;
|
||||||
@@ -64,15 +67,39 @@ public class DebugInfoAnnotator implements Annotator {
|
|||||||
if (expression instanceof JetSimpleNameExpression) {
|
if (expression instanceof JetSimpleNameExpression) {
|
||||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) expression;
|
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) expression;
|
||||||
IElementType elementType = expression.getNode().getElementType();
|
IElementType elementType = expression.getNode().getElementType();
|
||||||
if (elementType == JetNodeTypes.OPERATION_REFERENCE && EXCLUDED.contains(nameExpression.getReferencedNameElementType())) {
|
if (elementType == JetNodeTypes.OPERATION_REFERENCE) {
|
||||||
return;
|
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);
|
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<? extends DeclarationDescriptor> declarationDescriptors = bindingContext.get(AMBIGUOUS_REFERENCE_TARGET, expression);
|
||||||
|
if (declarationDescriptors != null) {
|
||||||
|
target = "[" + declarationDescriptors.size() + " descriptors]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean resolved = target != null;
|
||||||
boolean unresolved = unresolvedReferences.contains(expression);
|
boolean unresolved = unresolvedReferences.contains(expression);
|
||||||
|
// if (ErrorUtils.isError(declarationDescriptor)) {
|
||||||
|
// holder.createErrorAnnotation()
|
||||||
|
// }
|
||||||
if (resolved && unresolved) {
|
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) {
|
else if (!resolved && !unresolved) {
|
||||||
holder.createErrorAnnotation(expression, "Reference is not resolved to anything, but is not marked unresolved").setTextAttributes(JetHighlighter.JET_DEBUG_INFO);
|
holder.createErrorAnnotation(expression, "Reference is not resolved to anything, but is not marked unresolved").setTextAttributes(JetHighlighter.JET_DEBUG_INFO);
|
||||||
|
|||||||
Reference in New Issue
Block a user