mark syntax errors in QuickJetPsiCheckerTest

This commit is contained in:
Stepan Koltsov
2011-11-29 01:55:39 +04:00
parent 8498280b0e
commit 4fc41f4ad9
12 changed files with 128 additions and 19 deletions
@@ -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("(<!\\w+(,\\s*\\w+)*!>)|(<!>)");
private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile("\\w+");
public static List<Diagnostic> getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, PsiElement root) {
ArrayList<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
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<Diagnostic> diagnostics = bindingContext.getDiagnostics();
public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, BindingContext bindingContext, List<TextRange> syntaxErrors) {
Collection<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
diagnostics.addAll(bindingContext.getDiagnostics());
for (TextRange syntaxError : syntaxErrors) {
diagnostics.add(new SyntaxErrorDiagnostic(syntaxError));
}
return addDiagnosticMarkersToText(psiFile, diagnostics);
}
public static StringBuffer addDiagnosticMarkersToText(PsiFile psiFile, Collection<Diagnostic> 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<DiagnosticDescriptor> getSortedDiagnosticDescriptors(Collection<Diagnostic> diagnostics) {
List<Diagnostic> list = Lists.newArrayList(diagnostics);
Collections.sort(list, DIAGNOSTIC_COMPARATOR);
@@ -282,6 +361,10 @@ public class CheckerTestUtil {
public List<Diagnostic> getDiagnostics() {
return diagnostics;
}
public TextRange getTextRange() {
return new TextRange(start, end);
}
}
public static class DiagnosedRange {
@@ -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<TextRange> getSyntaxErrorRanges(@NotNull PsiElement root) {
final ArrayList<TextRange> r = new ArrayList<TextRange>();
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()) {
@@ -28,7 +28,7 @@ class WithPC1(a : Int) {
}
class Foo() : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>WithPC0<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST!>this<!>() {
class Foo() : <!SUPERTYPE_NOT_INITIALIZED, FINAL_SUPERTYPE!>WithPC0<!>, <!MANY_CLASSES_IN_SUPERTYPE_LIST, SYNTAX!>this<!>() {
}
@@ -47,4 +47,4 @@ class <!PRIMARY_CONSTRUCTOR_MISSING_STATEFUL_PROPERTY!>NoCPI<!> {
var ab = <!PROPERTY_INITIALIZER_NO_BACKING_FIELD!>1<!>
get() = 1
set(v) {}
}
}
@@ -1,4 +1,4 @@
namespace return
namespace <!SYNTAX!>return<!>
class A {
fun outer() {
@@ -14,4 +14,4 @@ class A {
<!RETURN_NOT_ALLOWED!>return<!UNRESOLVED_REFERENCE!>@inner<!><!>
return@outer
}
}
}
@@ -32,7 +32,7 @@ class A<E>() : C(), T {
super<<!NOT_A_SUPERTYPE!>E<!>>.bar()
super<<!NOT_A_SUPERTYPE!>E<!>>@A.bar()
super<<!NOT_A_SUPERTYPE!>Int<!>>.foo()
super<>.foo()
super<<!SYNTAX!><!>>.foo()
super<<!NOT_A_SUPERTYPE!>fun() : Unit<!>>.foo()
super<<!NOT_A_SUPERTYPE!>()<!>>.foo()
super<T><!UNRESOLVED_REFERENCE!>@B<!>.foo()
@@ -86,4 +86,4 @@ class A1 {
fun test() {
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.equals(null)
}
}
}
@@ -0,0 +1,5 @@
// dummy test of syntax error highlighing in tests
fun get() {
1 + 2 <!SYNTAX!>2 3 4<!>
}
@@ -0,0 +1 @@
fun f() {<!SYNTAX!><!>
@@ -4,5 +4,5 @@ import java.util.List;
fun ff(l: Any) = when(l) {
is <!CANNOT_CHECK_FOR_ERASED!>List<String><!> => 1
else 2
else <!SYNTAX!>2<!>
}
@@ -3,5 +3,4 @@
fun block(f : fun() : Unit) = f()
fun bar() = block{ <!UNRESOLVED_REFERENCE!>foo<!>() // <-- missing closing curly bracket
fun foo() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> }
fun foo() = block{ <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!> }<!SYNTAX!><!>
@@ -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<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
List<Diagnostic> diagnostics = Lists.newArrayList(bindingContext.getDiagnostics());
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile);
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
makeTestData(diagnostics, diagnosedRanges);
@@ -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 {
@@ -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<TextRange> 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() {