diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index b7d156c1825..d76a32de86a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -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_COMPARATOR = new Comparator() { @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 ranges1 = getTextRanges(o1); + List 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("()|()"); @@ -132,8 +141,10 @@ public class CheckerTestUtil { private static void unexpectedDiagnostics(List 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 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 getTextRanges(@NotNull Diagnostic diagnostic) { + return Collections.singletonList(((SyntaxErrorDiagnostic) diagnostic).textRange); } @NotNull @@ -337,7 +348,7 @@ public class CheckerTestUtil { List 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 getTextRanges(Diagnostic currentDiagnostic) { + return currentDiagnostic.getFactory().getTextRanges(currentDiagnostic); } private static class DiagnosticDescriptor { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java index 5b6e97783a1..7b33078d130 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/AbstractDiagnosticFactory.java @@ -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 getTextRanges(@NotNull Diagnostic diagnostic) { + return Collections.singletonList(((DiagnosticWithTextRange) diagnostic).getTextRange()); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java index 42621e20bfc..877d05bdad5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticFactory.java @@ -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 getTextRanges(@NotNull Diagnostic diagnostic); @NotNull PsiFile getPsiFile(@NotNull Diagnostic diagnostic); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java index fbbbc1ea72f..82dfc9dee67 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/DiagnosticHolder.java @@ -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 textRanges = diagnostic.getFactory().getTextRanges(diagnostic); + throw new IllegalStateException(diagnostic.getMessage() + DiagnosticUtils.atLocation(psiFile, textRanges.get(0))); } } }; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 8be2c6dffff..99cdb406f14 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -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 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 RETURN_TYPE_MISMATCH_ON_OVERRIDE = new ParameterizedDiagnosticFactory2(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 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) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java index 6801ec1b9b7..1ef1ce29695 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/RedeclarationDiagnosticFactory.java @@ -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 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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java index a3350a690ab..e06edd22af7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/UnresolvedReferenceDiagnosticFactory.java @@ -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 { @@ -19,4 +23,16 @@ public class UnresolvedReferenceDiagnosticFactory extends AbstractDiagnosticFact public UnresolvedReferenceDiagnostic on(@NotNull JetReferenceExpression reference) { return new UnresolvedReferenceDiagnostic(reference, message); } + + @NotNull + @Override + public List 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); + } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java index ec971f4796c..ab1aea96953 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java @@ -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 getBracketRanges() { + TextRange lBracket = getIndicesNode().findChildByType(JetTokens.LBRACKET).getTextRange(); + TextRange rBracket = getIndicesNode().findChildByType(JetTokens.RBRACKET).getTextRange(); + return Lists.newArrayList(lBracket, rBracket); + } } diff --git a/compiler/testData/diagnostics/tests/LValueAssignment.jet b/compiler/testData/diagnostics/tests/LValueAssignment.jet index 7752029c1db..b4402994c0e 100644 --- a/compiler/testData/diagnostics/tests/LValueAssignment.jet +++ b/compiler/testData/diagnostics/tests/LValueAssignment.jet @@ -128,7 +128,7 @@ class Test() { (a : Array)[4]++ (ab.getArray() : Array)[54] += 43 - this[54] = 34 + this[54] = 34 } } diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index 06fd0e7c2ce..54eec072198 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -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 redeclarations, @NotNull final AnnotationHolder holder ) { + List 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 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)); }