diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index 9360fb27083..d002d67284d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -2,8 +2,13 @@ package org.jetbrains.jet.checkers; import com.google.common.collect.*; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory; +import org.jetbrains.jet.lang.diagnostics.Severity; +import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; import java.util.*; @@ -32,6 +37,15 @@ public class CheckerTestUtil { private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()"); private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile("\\w+"); + public static List getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, PsiElement root) { + ArrayList diagnostics = new ArrayList(); + diagnostics.addAll(bindingContext.getDiagnostics()); + for (TextRange textRange : AnalyzingUtils.getSyntaxErrorRanges(root)) { + diagnostics.add(new SyntaxErrorDiagnostic(textRange)); + } + return diagnostics; + } + public interface DiagnosticDiffCallbacks { void missingDiagnostic(String type, int expectedStart, int expectedEnd); void unexpectedDiagnostic(String type, int actualStart, int actualEnd); @@ -144,7 +158,7 @@ public class CheckerTestUtil { Matcher diagnosticTypeMatcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(matchedText); DiagnosedRange range = new DiagnosedRange(effectiveOffset); while (diagnosticTypeMatcher.find()) { - range.addDiagnostic(diagnosticTypeMatcher.group()); + range.addDiagnostic(diagnosticTypeMatcher.group()); } opened.push(range); result.add(range); @@ -158,9 +172,17 @@ public class CheckerTestUtil { return matcher.replaceAll(""); } - public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext) { - Collection diagnostics = bindingContext.getDiagnostics(); + public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext, List syntaxErrors) { + Collection diagnostics = new ArrayList(); + diagnostics.addAll(bindingContext.getDiagnostics()); + for (TextRange syntaxError : syntaxErrors) { + diagnostics.add(new SyntaxErrorDiagnostic(syntaxError)); + } + return addDiagnosticMarkersToText(psiFile, diagnostics); + } + + public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, Collection diagnostics) { StringBuffer result = new StringBuffer(); String text = psiFile.getText(); if (!diagnostics.isEmpty()) { @@ -193,6 +215,14 @@ public class CheckerTestUtil { } result.append(c); } + + if (currentDescriptor != null) { + assert currentDescriptor.start == text.length(); + assert currentDescriptor.end == text.length(); + openDiagnosticsString(result, currentDescriptor); + opened.push(currentDescriptor); + } + while (!opened.isEmpty() && text.length() == opened.peek().end) { closeDiagnosticString(result); opened.pop(); @@ -223,6 +253,55 @@ public class CheckerTestUtil { result.append(""); } + private static class SyntaxErrorDiagnosticFactory implements DiagnosticFactory { + private static final SyntaxErrorDiagnosticFactory instance = new SyntaxErrorDiagnosticFactory(); + + @NotNull + @Override + public TextRange getTextRange(@NotNull Diagnostic diagnostic) { + return ((SyntaxErrorDiagnostic) diagnostic).textRange; + } + + @NotNull + @Override + public PsiFile getPsiFile(@NotNull Diagnostic diagnostic) { + throw new IllegalStateException(); + } + + @NotNull + @Override + public String getName() { + return "SYNTAX"; + } + } + + public static class SyntaxErrorDiagnostic implements Diagnostic { + + private final TextRange textRange; + + public SyntaxErrorDiagnostic(TextRange textRange) { + this.textRange = textRange; + } + + @NotNull + @Override + public DiagnosticFactory getFactory() { + return SyntaxErrorDiagnosticFactory.instance; + } + + @NotNull + @Override + public String getMessage() { + throw new IllegalStateException(); + } + + @NotNull + @Override + public Severity getSeverity() { + throw new IllegalStateException(); + } + } + private static List getSortedDiagnosticDescriptors(Collection diagnostics) { List list = Lists.newArrayList(diagnostics); Collections.sort(list, DIAGNOSTIC_COMPARATOR); @@ -282,6 +361,10 @@ public class CheckerTestUtil { public List getDiagnostics() { return diagnostics; } + + public TextRange getTextRange() { + return new TextRange(start, end); + } } public static class DiagnosedRange { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java index 483a5673739..da5cb3020b5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/AnalyzingUtils.java @@ -4,6 +4,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Maps; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiErrorElement; @@ -45,6 +46,22 @@ public class AnalyzingUtils { } }); } + + public static List getSyntaxErrorRanges(@NotNull PsiElement root) { + final ArrayList r = new ArrayList(); + root.acceptChildren(new PsiElementVisitor() { + @Override + public void visitElement(PsiElement element) { + element.acceptChildren(this); + } + + @Override + public void visitErrorElement(PsiErrorElement element) { + r.add(element.getTextRange()); + } + }); + return r; + } public static void throwExceptionOnErrors(BindingContext bindingContext) { for (Diagnostic diagnostic : bindingContext.getDiagnostics()) { diff --git a/compiler/testData/checkerWithErrorTypes/quick/Constructors.jet b/compiler/testData/checkerWithErrorTypes/quick/Constructors.jet index 85a218569ac..e6ce2e54a41 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/Constructors.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/Constructors.jet @@ -28,7 +28,7 @@ class WithPC1(a : Int) { } -class Foo() : WithPC0, this() { +class Foo() : WithPC0, this() { } @@ -47,4 +47,4 @@ class NoCPI { var ab = 1 get() = 1 set(v) {} -} \ No newline at end of file +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/Return.jet b/compiler/testData/checkerWithErrorTypes/quick/Return.jet index 905a88ed092..2426ecb933c 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/Return.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/Return.jet @@ -1,4 +1,4 @@ -namespace return +namespace return class A { fun outer() { @@ -14,4 +14,4 @@ class A { return@inner return@outer } -} \ No newline at end of file +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/Super.jet b/compiler/testData/checkerWithErrorTypes/quick/Super.jet index 7a3095d820f..c7fc54a8b58 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/Super.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/Super.jet @@ -32,7 +32,7 @@ class A() : C(), T { super<E>.bar() super<E>@A.bar() super<Int>.foo() - super<>.foo() + super<>.foo() super<fun() : Unit>.foo() super<()>.foo() super@B.foo() @@ -86,4 +86,4 @@ class A1 { fun test() { super.equals(null) } -} \ No newline at end of file +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlighting.jet b/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlighting.jet new file mode 100644 index 00000000000..373cfbceda4 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlighting.jet @@ -0,0 +1,5 @@ +// dummy test of syntax error highlighing in tests + +fun get() { + 1 + 2 2 3 4 +} diff --git a/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlightingEof.jet b/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlightingEof.jet new file mode 100644 index 00000000000..7114933f970 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/SyntaxErrorInTestHighlightingEof.jet @@ -0,0 +1 @@ +fun f() { diff --git a/compiler/testData/checkerWithErrorTypes/quick/cast/WhenErasedDisallowFromAny.jet b/compiler/testData/checkerWithErrorTypes/quick/cast/WhenErasedDisallowFromAny.jet index af0653dd699..2f424e3b9ad 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/cast/WhenErasedDisallowFromAny.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/cast/WhenErasedDisallowFromAny.jet @@ -4,5 +4,5 @@ import java.util.List; fun ff(l: Any) = when(l) { is List => 1 - else 2 + else 2 } diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet index 35a66da2884..5e562547174 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt328DuplicatedByKt329.jet @@ -3,5 +3,4 @@ fun block(f : fun() : Unit) = f() fun bar() = block{ foo() // <-- missing closing curly bracket -fun foo() = block{ bar() } - +fun foo() = block{ bar() } diff --git a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java index cdf385d3158..72d7364ca5e 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -1,6 +1,7 @@ package org.jetbrains.jet.checkers; import com.google.common.collect.Lists; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -82,12 +83,12 @@ public class CheckerTestUtilTest extends JetLiteFixture { public void test(PsiFile psiFile) { BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(ImportingStrategy.NONE), (JetFile) psiFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER); - String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString(); + String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString(); List diagnosedRanges = Lists.newArrayList(); CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); - List diagnostics = Lists.newArrayList(bindingContext.getDiagnostics()); + List diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile); Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR); makeTestData(diagnostics, diagnosedRanges); diff --git a/compiler/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java b/compiler/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java index d7ae428139f..fc1609e2865 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/QuickJetPsiCheckerTest.java @@ -47,7 +47,7 @@ public class QuickJetPsiCheckerTest extends JetLiteFixture { BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(AnalyzingUtils.getInstance(importingStrategy), jetFile, AnalyzerFacade.SINGLE_DECLARATION_PROVIDER); - CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() { + CheckerTestUtil.diagnosticsDiff(diagnosedRanges, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, jetFile), new CheckerTestUtil.DiagnosticDiffCallbacks() { @Override public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { String message = "Missing " + type + DiagnosticUtils.atLocation(myFile, new TextRange(expectedStart, expectedEnd)); @@ -61,14 +61,14 @@ public class QuickJetPsiCheckerTest extends JetLiteFixture { } }); - String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString(); + String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext, AnalyzingUtils.getSyntaxErrorRanges(jetFile)).toString(); assertEquals(expectedText, actualText); // convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath)); } -// private void convert(File src, File dest) throws IOException { + // private void convert(File src, File dest) throws IOException { // File[] files = src.listFiles(); // for (File file : files) { // try { diff --git a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java index 7e3844b4c4d..a7de5694715 100644 --- a/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java +++ b/idea/src/org/jetbrains/jet/plugin/actions/CopyAsDiagnosticTestAction.java @@ -6,11 +6,12 @@ import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import org.jetbrains.jet.checkers.CheckerTestUtil; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import java.awt.*; @@ -18,6 +19,7 @@ import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; +import java.util.List; /** * @author abreslav @@ -30,8 +32,9 @@ public class CopyAsDiagnosticTestAction extends AnAction { assert editor != null && psiFile != null; BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile); + List syntaxError = AnalyzingUtils.getSyntaxErrorRanges(psiFile); - String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext).toString(); + String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, bindingContext, syntaxError).toString(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(new StringSelection(result), new ClipboardOwner() {