Mark only brackets when array access expression is unresolved

This commit is contained in:
svtk
2012-01-31 16:40:52 +04:00
parent 948ccc5205
commit 1cb4c89c5c
10 changed files with 103 additions and 45 deletions
@@ -11,7 +11,6 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -26,16 +25,26 @@ public class CheckerTestUtil {
public static final Comparator<Diagnostic> DIAGNOSTIC_COMPARATOR = new Comparator<Diagnostic>() {
@Override
public int compare(Diagnostic o1, Diagnostic o2) {
TextRange range1 = getTextRange(o1);
TextRange range2 = getTextRange(o2);
int startOffset1 = range1.getStartOffset();
int startOffset2 = range2.getStartOffset();
if (startOffset1 != startOffset2) {
// Start early -- go first
return startOffset1 - range2.getStartOffset();
List<TextRange> ranges1 = getTextRanges(o1);
List<TextRange> ranges2 = getTextRanges(o2);
if (ranges1.size() != ranges2.size()) return ranges1.size() - ranges2.size();
for (int i = 0; i < ranges1.size(); i++) {
TextRange range1 = ranges1.get(i);
TextRange range2 = ranges2.get(i);
int startOffset1 = range1.getStartOffset();
int startOffset2 = range2.getStartOffset();
if (startOffset1 != startOffset2) {
// Start early -- go first
return startOffset1 - range2.getStartOffset();
}
int endOffset1 = range1.getEndOffset();
int endOffset2 = range2.getEndOffset();
if (endOffset1 != endOffset2) {
// start at the same offset, the one who end later is the outer, i.e. goes first
return endOffset2 - endOffset1;
}
}
// start at the same offset, the one who end later is the outer, i.e. goes first
return range2.getEndOffset() - range1.getEndOffset();
return 0;
}
};
private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("(<!\\w+(,\\s*\\w+)*!>)|(<!>)");
@@ -132,8 +141,10 @@ public class CheckerTestUtil {
private static void unexpectedDiagnostics(List<Diagnostic> actual, DiagnosticDiffCallbacks callbacks) {
for (Diagnostic diagnostic : actual) {
if (!diagnostic.getFactory().getPsiFile(diagnostic).equals(callbacks.getFile())) continue;
TextRange textRange = getTextRange(diagnostic);
callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset());
List<TextRange> textRanges = getTextRanges(diagnostic);
for (TextRange textRange : textRanges) {
callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset());
}
}
}
@@ -272,8 +283,8 @@ public class CheckerTestUtil {
@NotNull
@Override
public TextRange getTextRange(@NotNull Diagnostic diagnostic) {
return ((SyntaxErrorDiagnostic) diagnostic).textRange;
public List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic) {
return Collections.singletonList(((SyntaxErrorDiagnostic) diagnostic).textRange);
}
@NotNull
@@ -337,7 +348,7 @@ public class CheckerTestUtil {
List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
DiagnosticDescriptor currentDiagnosticDescriptor = null;
for (Diagnostic diagnostic : list) {
TextRange textRange = getTextRange(diagnostic);
TextRange textRange = getTextRanges(diagnostic).get(0);
if (currentDiagnosticDescriptor != null && currentDiagnosticDescriptor.equalRange(textRange)) {
currentDiagnosticDescriptor.diagnostics.add(diagnostic);
}
@@ -349,8 +360,8 @@ public class CheckerTestUtil {
return diagnosticDescriptors;
}
private static TextRange getTextRange(Diagnostic currentDiagnostic) {
return currentDiagnostic.getFactory().getTextRange(currentDiagnostic);
private static List<TextRange> getTextRanges(Diagnostic currentDiagnostic) {
return currentDiagnostic.getFactory().getTextRanges(currentDiagnostic);
}
private static class DiagnosticDescriptor {
@@ -4,6 +4,9 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
@@ -22,8 +25,8 @@ public class AbstractDiagnosticFactory implements DiagnosticFactory {
@NotNull
@Override
public TextRange getTextRange(@NotNull Diagnostic diagnostic) {
return ((DiagnosticWithTextRange) diagnostic).getTextRange();
public List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic) {
return Collections.singletonList(((DiagnosticWithTextRange) diagnostic).getTextRange());
}
@NotNull
@@ -4,12 +4,14 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author abreslav
*/
public interface DiagnosticFactory {
@NotNull
TextRange getTextRange(@NotNull Diagnostic diagnostic);
List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic);
@NotNull
PsiFile getPsiFile(@NotNull Diagnostic diagnostic);
@@ -4,6 +4,8 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author abreslav
*/
@@ -18,8 +20,8 @@ public interface DiagnosticHolder {
public void report(@NotNull Diagnostic diagnostic) {
if (diagnostic.getSeverity() == Severity.ERROR) {
PsiFile psiFile = diagnostic.getFactory().getPsiFile(diagnostic);
TextRange textRange = diagnostic.getFactory().getTextRange(diagnostic);
throw new IllegalStateException(diagnostic.getMessage() + DiagnosticUtils.atLocation(psiFile, textRange));
List<TextRange> textRanges = diagnostic.getFactory().getTextRanges(diagnostic);
throw new IllegalStateException(diagnostic.getMessage() + DiagnosticUtils.atLocation(psiFile, textRanges.get(0)));
}
}
};
@@ -15,7 +15,9 @@ import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import static org.jetbrains.jet.lang.diagnostics.Severity.ERROR;
import static org.jetbrains.jet.lang.diagnostics.Severity.WARNING;
@@ -193,6 +195,9 @@ public interface Errors {
SimpleDiagnosticFactory LOCAL_VARIABLE_WITH_GETTER = SimpleDiagnosticFactory.create(ERROR, "Local variables are not allowed to have getters");
SimpleDiagnosticFactory LOCAL_VARIABLE_WITH_SETTER = SimpleDiagnosticFactory.create(ERROR, "Local variables are not allowed to have setters");
SimplePsiElementOnlyDiagnosticFactory<JetProperty> VAL_WITH_SETTER = SimplePsiElementOnlyDiagnosticFactory.create(ERROR, "A 'val'-property cannot have a setter");
SimpleDiagnosticFactory NO_GET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No get method providing array access");
SimpleDiagnosticFactory NO_SET_METHOD = SimpleDiagnosticFactory.create(ERROR, "No set method providing array access");
SimpleDiagnosticFactory EQUALS_MISSING = SimpleDiagnosticFactory.create(ERROR, "No method 'equals(Any?) : Boolean' available");
SimpleDiagnosticFactory ASSIGNMENT_IN_EXPRESSION_CONTEXT = SimpleDiagnosticFactory.create(ERROR, "Assignments are not expressions, and only expressions are allowed in this context");
@@ -362,7 +367,7 @@ public interface Errors {
ParameterizedDiagnosticFactory2<CallableMemberDescriptor, CallableMemberDescriptor> RETURN_TYPE_MISMATCH_ON_OVERRIDE = new ParameterizedDiagnosticFactory2<CallableMemberDescriptor, CallableMemberDescriptor>(ERROR, "Return type of {0} is not a subtype of the return type overridden member {1}") {
@NotNull
@Override
public TextRange getTextRange(@NotNull Diagnostic diagnostic) {
public List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic) {
PsiElement psiElement = ((DiagnosticWithPsiElement) diagnostic).getPsiElement();
JetTypeReference returnTypeRef = null;
ASTNode nameNode = null;
@@ -381,9 +386,9 @@ public interface Errors {
returnTypeRef = accessor.getReturnTypeReference();
nameNode = accessor.getNamePlaceholder().getNode();
}
if (returnTypeRef != null) return returnTypeRef.getTextRange();
if (nameNode != null) return nameNode.getTextRange();
return super.getTextRange(diagnostic);
if (returnTypeRef != null) return Collections.singletonList(returnTypeRef.getTextRange());
if (nameNode != null) return Collections.singletonList(nameNode.getTextRange());
return super.getTextRanges(diagnostic);
}
private ASTNode getNameNode(JetNamedDeclaration function) {
@@ -8,6 +8,9 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.Collections;
import java.util.List;
/**
* @author abreslav
*/
@@ -38,22 +41,22 @@ public class RedeclarationDiagnosticFactory extends AbstractDiagnosticFactory {
@NotNull
@Override
public TextRange getTextRange(@NotNull Diagnostic diagnostic) {
public List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic) {
PsiElement redeclaration = ((RedeclarationDiagnostic) diagnostic).getPsiElement();
if (redeclaration instanceof JetNamedDeclaration) {
PsiElement nameIdentifier = ((JetNamedDeclaration) redeclaration).getNameIdentifier();
if (nameIdentifier != null) {
return nameIdentifier.getTextRange();
return Collections.singletonList(nameIdentifier.getTextRange());
}
}
else if (redeclaration instanceof JetFile) {
JetFile file = (JetFile) redeclaration;
PsiElement nameIdentifier = file.getNamespaceHeader().getNameIdentifier();
if (nameIdentifier != null) {
return nameIdentifier.getTextRange();
return Collections.singletonList(nameIdentifier.getTextRange());
}
}
return redeclaration.getTextRange();
return Collections.singletonList(redeclaration.getTextRange());
}
@NotNull
@@ -1,12 +1,16 @@
package org.jetbrains.jet.lang.diagnostics;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import java.util.List;
/**
* @author abreslav
*/
* @author abreslav
*/
public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFactory
implements PsiElementOnlyDiagnosticFactory<JetSimpleNameExpression> {
@@ -19,4 +23,16 @@ public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFact
public UnresolvedReferenceDiagnostic on(@NotNull JetReferenceExpression reference) {
return new UnresolvedReferenceDiagnostic(reference, message);
}
@NotNull
@Override
public List<TextRange> getTextRanges(@NotNull Diagnostic diagnostic) {
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
JetReferenceExpression element = ((UnresolvedReferenceDiagnostic) diagnostic).getPsiElement();
if (element instanceof JetArrayAccessExpression) {
return ((JetArrayAccessExpression)element).getBracketRanges();
}
}
return super.getTextRanges(diagnostic);
}
}
@@ -1,6 +1,8 @@
package org.jetbrains.jet.lang.psi;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceService;
@@ -8,6 +10,7 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collections;
import java.util.List;
@@ -50,7 +53,14 @@ public class JetArrayAccessExpression extends JetReferenceExpression {
return PsiTreeUtil.getChildrenOfTypeAsList(container, JetExpression.class);
}
@NotNull
public JetContainerNode getIndicesNode() {
return (JetContainerNode) findChildByType(JetNodeTypes.INDICES);
}
public List<TextRange> getBracketRanges() {
TextRange lBracket = getIndicesNode().findChildByType(JetTokens.LBRACKET).getTextRange();
TextRange rBracket = getIndicesNode().findChildByType(JetTokens.RBRACKET).getTextRange();
return Lists.newArrayList(lBracket, rBracket);
}
}
@@ -128,7 +128,7 @@ class Test() {
(a : Array<Int>)[4]++
(<!VARIABLE_EXPECTED!>ab.getArray()<!> : Array<Int>)[54] += 43
<!UNRESOLVED_REFERENCE!>this[54]<!> = 34
this<!NO_SET_METHOD!><!UNRESOLVED_REFERENCE!>[<!>54]<!> = 34
}
}
@@ -29,6 +29,7 @@ import org.jetbrains.jet.plugin.quickfix.JetIntentionActionFactory;
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
@@ -141,6 +142,7 @@ public class JetPsiChecker implements Annotator {
@NotNull Set<PsiElement> redeclarations,
@NotNull final AnnotationHolder holder
) {
List<TextRange> textRanges = diagnostic.getFactory().getTextRanges(diagnostic);
if (diagnostic.getSeverity() == Severity.ERROR) {
if (diagnostic instanceof UnresolvedReferenceDiagnostic) {
UnresolvedReferenceDiagnostic unresolvedReferenceDiagnostic = (UnresolvedReferenceDiagnostic) diagnostic;
@@ -159,9 +161,11 @@ public class JetPsiChecker implements Annotator {
}
}
else {
Annotation annotation = holder.createErrorAnnotation(referenceExpression, diagnostic.getMessage());
registerQuickFix(annotation, diagnostic);
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
for (TextRange textRange : textRanges) {
Annotation annotation = holder.createErrorAnnotation(textRange, diagnostic.getMessage());
registerQuickFix(annotation, diagnostic);
annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
return;
@@ -174,17 +178,19 @@ public class JetPsiChecker implements Annotator {
}
// Generic annotation
Annotation errorAnnotation = holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic));
registerQuickFix(
errorAnnotation,
diagnostic);
for (TextRange textRange : textRanges) {
Annotation errorAnnotation = holder.createErrorAnnotation(textRange, getMessage(diagnostic));
registerQuickFix(errorAnnotation, diagnostic);
}
}
else if (diagnostic.getSeverity() == Severity.WARNING) {
Annotation annotation = holder.createWarningAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic));
registerQuickFix(annotation, diagnostic);
for (TextRange textRange : textRanges) {
Annotation annotation = holder.createWarningAnnotation(textRange, getMessage(diagnostic));
registerQuickFix(annotation, diagnostic);
if (diagnostic.getFactory() instanceof UnusedElementDiagnosticFactory) {
annotation.setHighlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL);
if (diagnostic.getFactory() instanceof UnusedElementDiagnosticFactory) {
annotation.setHighlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL);
}
}
}
}
@@ -234,7 +240,7 @@ public class JetPsiChecker implements Annotator {
@Nullable
private Annotation markRedeclaration(@NotNull Set<PsiElement> redeclarations, @NotNull RedeclarationDiagnostic diagnostic, @NotNull AnnotationHolder holder) {
if (!redeclarations.add(diagnostic.getPsiElement())) return null;
return holder.createErrorAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic));
return holder.createErrorAnnotation(diagnostic.getFactory().getTextRanges(diagnostic).get(0), getMessage(diagnostic));
}