CheckerTestUtil: introduce ActualDiagnostic to encapsulate Diagnostic

This commit is contained in:
Alexander Udalov
2016-12-20 15:43:35 +03:00
parent 6cfc42666c
commit 7d3628b9be
4 changed files with 142 additions and 109 deletions
@@ -30,6 +30,8 @@ import com.intellij.util.Function;
import com.intellij.util.SmartList; import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack; import com.intellij.util.containers.Stack;
import kotlin.Pair;
import kotlin.TuplesKt;
import kotlin.collections.CollectionsKt; import kotlin.collections.CollectionsKt;
import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -44,20 +46,20 @@ import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtElement;
import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtExpression;
import org.jetbrains.kotlin.psi.KtReferenceExpression; import org.jetbrains.kotlin.psi.KtReferenceExpression;
import org.jetbrains.kotlin.psi.KtWhenExpression;
import org.jetbrains.kotlin.resolve.AnalyzingUtils; import org.jetbrains.kotlin.resolve.AnalyzingUtils;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class CheckerTestUtil { public class CheckerTestUtil {
public static final Comparator<Diagnostic> DIAGNOSTIC_COMPARATOR = new Comparator<Diagnostic>() { public static final Comparator<ActualDiagnostic> DIAGNOSTIC_COMPARATOR = new Comparator<ActualDiagnostic>() {
@Override @Override
public int compare(@NotNull Diagnostic o1, @NotNull Diagnostic o2) { public int compare(@NotNull ActualDiagnostic o1, @NotNull ActualDiagnostic o2) {
List<TextRange> ranges1 = o1.getTextRanges(); List<TextRange> ranges1 = o1.diagnostic.getTextRanges();
List<TextRange> ranges2 = o2.getTextRanges(); List<TextRange> ranges2 = o2.diagnostic.getTextRanges();
int minNumberOfRanges = ranges1.size() < ranges2.size() ? ranges1.size() : ranges2.size(); int minNumberOfRanges = ranges1.size() < ranges2.size() ? ranges1.size() : ranges2.size();
for (int i = 0; i < minNumberOfRanges; i++) { for (int i = 0; i < minNumberOfRanges; i++) {
TextRange range1 = ranges1.get(i); TextRange range1 = ranges1.get(i);
@@ -90,37 +92,38 @@ public class CheckerTestUtil {
private static final Pattern INDIVIDUAL_PARAMETER_PATTERN = Pattern.compile(DIAGNOSTIC_PARAMETER); private static final Pattern INDIVIDUAL_PARAMETER_PATTERN = Pattern.compile(DIAGNOSTIC_PARAMETER);
@NotNull @NotNull
public static List<Diagnostic> getDiagnosticsIncludingSyntaxErrors( public static List<ActualDiagnostic> getDiagnosticsIncludingSyntaxErrors(
@NotNull BindingContext bindingContext, @NotNull BindingContext bindingContext,
@NotNull final PsiElement root, @NotNull PsiElement root,
boolean markDynamicCalls, boolean markDynamicCalls,
@Nullable List<DeclarationDescriptor> dynamicCallDescriptors @Nullable List<DeclarationDescriptor> dynamicCallDescriptors
) { ) {
List<Diagnostic> diagnostics = new ArrayList<Diagnostic>(); List<ActualDiagnostic> diagnostics = new ArrayList<ActualDiagnostic>();
diagnostics.addAll(Collections2.filter(bindingContext.getDiagnostics().all(), for (Diagnostic diagnostic : bindingContext.getDiagnostics().all()) {
new Predicate<Diagnostic>() { if (PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false)) {
@Override diagnostics.add(new ActualDiagnostic(diagnostic));
public boolean apply(Diagnostic diagnostic) { }
return PsiTreeUtil.isAncestor(root, diagnostic.getPsiElement(), false);
}
}));
for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
diagnostics.add(new SyntaxErrorDiagnostic(errorElement));
} }
List<Diagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors);
for (PsiErrorElement errorElement : AnalyzingUtils.getSyntaxErrorRanges(root)) {
diagnostics.add(new ActualDiagnostic(new SyntaxErrorDiagnostic(errorElement)));
}
List<ActualDiagnostic> debugAnnotations = getDebugInfoDiagnostics(root, bindingContext, markDynamicCalls, dynamicCallDescriptors);
diagnostics.addAll(debugAnnotations); diagnostics.addAll(debugAnnotations);
return diagnostics; return diagnostics;
} }
@SuppressWarnings("TestOnlyProblems") @SuppressWarnings("TestOnlyProblems")
@NotNull @NotNull
private static List<Diagnostic> getDebugInfoDiagnostics( private static List<ActualDiagnostic> getDebugInfoDiagnostics(
@NotNull PsiElement root, @NotNull PsiElement root,
@NotNull BindingContext bindingContext, @NotNull BindingContext bindingContext,
final boolean markDynamicCalls, final boolean markDynamicCalls,
@Nullable final List<DeclarationDescriptor> dynamicCallDescriptors @Nullable final List<DeclarationDescriptor> dynamicCallDescriptors
) { ) {
final List<Diagnostic> debugAnnotations = Lists.newArrayList(); final List<ActualDiagnostic> debugAnnotations = new ArrayList<ActualDiagnostic>();
DebugInfoUtil.markDebugAnnotations(root, bindingContext, new DebugInfoUtil.DebugInfoReporter() { DebugInfoUtil.markDebugAnnotations(root, bindingContext, new DebugInfoUtil.DebugInfoReporter() {
@Override @Override
public void reportElementWithErrorType(@NotNull KtReferenceExpression expression) { public void reportElementWithErrorType(@NotNull KtReferenceExpression expression) {
@@ -149,35 +152,26 @@ public class CheckerTestUtil {
} }
private void newDiagnostic(KtElement element, DebugInfoDiagnosticFactory factory) { private void newDiagnostic(KtElement element, DebugInfoDiagnosticFactory factory) {
debugAnnotations.add(new DebugInfoDiagnostic(element, factory)); debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(element, factory)));
} }
}); });
// this code is used in tests and in internal action 'copy current file as diagnostic test' // this code is used in tests and in internal action 'copy current file as diagnostic test'
for (KtExpression expression : bindingContext.getSliceContents(BindingContext.SMARTCAST).keySet()) { //noinspection unchecked
if (PsiTreeUtil.isAncestor(root, expression, false)) { for (Pair<? extends WritableSlice<? extends KtExpression, ?>, DebugInfoDiagnosticFactory> factory : Arrays.asList(
debugAnnotations.add(new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.SMARTCAST)); TuplesKt.to(BindingContext.SMARTCAST, DebugInfoDiagnosticFactory.SMARTCAST),
} TuplesKt.to(BindingContext.IMPLICIT_RECEIVER_SMARTCAST, DebugInfoDiagnosticFactory.IMPLICIT_RECEIVER_SMARTCAST),
} TuplesKt.to(BindingContext.SMARTCAST_NULL, DebugInfoDiagnosticFactory.CONSTANT),
for (KtExpression expression : bindingContext.getSliceContents(BindingContext.IMPLICIT_RECEIVER_SMARTCAST).keySet()) { TuplesKt.to(BindingContext.LEAKING_THIS, DebugInfoDiagnosticFactory.LEAKING_THIS),
if (PsiTreeUtil.isAncestor(root, expression, false)) { TuplesKt.to(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, DebugInfoDiagnosticFactory.IMPLICIT_EXHAUSTIVE)
debugAnnotations.add(new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.IMPLICIT_RECEIVER_SMARTCAST)); )) {
} for (KtExpression expression : bindingContext.getSliceContents(factory.getFirst()).keySet()) {
} if (PsiTreeUtil.isAncestor(root, expression, false)) {
for (KtExpression expression : bindingContext.getSliceContents(BindingContext.SMARTCAST_NULL).keySet()) { debugAnnotations.add(new ActualDiagnostic(new DebugInfoDiagnostic(expression, factory.getSecond())));
if (PsiTreeUtil.isAncestor(root, expression, false)) { }
debugAnnotations.add(new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.CONSTANT));
}
}
for (KtExpression expression : bindingContext.getSliceContents(BindingContext.LEAKING_THIS).keySet()) {
if (PsiTreeUtil.isAncestor(root, expression, false)) {
debugAnnotations.add(new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.LEAKING_THIS));
}
}
for (KtWhenExpression expression : bindingContext.getSliceContents(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN).keySet()) {
if (PsiTreeUtil.isAncestor(root, expression, false)) {
debugAnnotations.add(new DebugInfoDiagnostic(expression, DebugInfoDiagnosticFactory.IMPLICIT_EXHAUSTIVE));
} }
} }
return debugAnnotations; return debugAnnotations;
} }
@@ -189,12 +183,12 @@ public class CheckerTestUtil {
void unexpectedDiagnostic(TextDiagnostic diagnostic, int actualStart, int actualEnd); void unexpectedDiagnostic(TextDiagnostic diagnostic, int actualStart, int actualEnd);
} }
public static Map<Diagnostic, TextDiagnostic> diagnosticsDiff( public static Map<ActualDiagnostic, TextDiagnostic> diagnosticsDiff(
List<DiagnosedRange> expected, List<DiagnosedRange> expected,
Collection<Diagnostic> actual, Collection<ActualDiagnostic> actual,
DiagnosticDiffCallbacks callbacks DiagnosticDiffCallbacks callbacks
) { ) {
Map<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic = new HashMap<Diagnostic, TextDiagnostic>(); Map<ActualDiagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic = new HashMap<ActualDiagnostic, TextDiagnostic>();
assertSameFile(actual); assertSameFile(actual);
@@ -256,7 +250,7 @@ public class CheckerTestUtil {
@NotNull DiagnosticDiffCallbacks callbacks, @NotNull DiagnosticDiffCallbacks callbacks,
@NotNull DiagnosedRange currentExpected, @NotNull DiagnosedRange currentExpected,
@NotNull DiagnosticDescriptor currentActual, @NotNull DiagnosticDescriptor currentActual,
@NotNull Map<Diagnostic, TextDiagnostic> diagnosticToInput @NotNull Map<ActualDiagnostic, TextDiagnostic> diagnosticToInput
) { ) {
int expectedStart = currentExpected.getStart(); int expectedStart = currentExpected.getStart();
int expectedEnd = currentExpected.getEnd(); int expectedEnd = currentExpected.getEnd();
@@ -265,21 +259,21 @@ public class CheckerTestUtil {
int actualEnd = currentActual.getEnd(); int actualEnd = currentActual.getEnd();
assert expectedStart == actualStart && expectedEnd == actualEnd; assert expectedStart == actualStart && expectedEnd == actualEnd;
Map<Diagnostic, TextDiagnostic> actualDiagnostics = currentActual.getTextDiagnosticsMap(); Map<ActualDiagnostic, TextDiagnostic> actualDiagnostics = currentActual.getTextDiagnosticsMap();
List<TextDiagnostic> expectedDiagnostics = currentExpected.getDiagnostics(); List<TextDiagnostic> expectedDiagnostics = currentExpected.getDiagnostics();
for (final TextDiagnostic expectedDiagnostic : expectedDiagnostics) { for (final TextDiagnostic expectedDiagnostic : expectedDiagnostics) {
Map.Entry<Diagnostic, TextDiagnostic> actualDiagnosticEntry = CollectionsKt.firstOrNull( Map.Entry<ActualDiagnostic, TextDiagnostic> actualDiagnosticEntry = CollectionsKt.firstOrNull(
actualDiagnostics.entrySet(), new Function1<Map.Entry<Diagnostic, TextDiagnostic>, Boolean>() { actualDiagnostics.entrySet(), new Function1<Map.Entry<ActualDiagnostic, TextDiagnostic>, Boolean>() {
@Override @Override
public Boolean invoke(Map.Entry<Diagnostic, TextDiagnostic> entry) { public Boolean invoke(Map.Entry<ActualDiagnostic, TextDiagnostic> entry) {
return expectedDiagnostic.getName().equals(entry.getValue().getName()); return expectedDiagnostic.getName().equals(entry.getValue().getName());
} }
} }
); );
if (actualDiagnosticEntry != null) { if (actualDiagnosticEntry != null) {
Diagnostic actualDiagnostic = actualDiagnosticEntry.getKey(); ActualDiagnostic actualDiagnostic = actualDiagnosticEntry.getKey();
TextDiagnostic actualTextDiagnostic = actualDiagnosticEntry.getValue(); TextDiagnostic actualTextDiagnostic = actualDiagnosticEntry.getValue();
if (!compareTextDiagnostic(expectedDiagnostic, actualTextDiagnostic)) { if (!compareTextDiagnostic(expectedDiagnostic, actualTextDiagnostic)) {
@@ -315,17 +309,17 @@ public class CheckerTestUtil {
return true; return true;
} }
private static void assertSameFile(Collection<Diagnostic> actual) { private static void assertSameFile(Collection<ActualDiagnostic> actual) {
if (actual.isEmpty()) return; if (actual.isEmpty()) return;
PsiFile file = actual.iterator().next().getPsiElement().getContainingFile(); PsiFile file = CollectionsKt.first(actual).getFile();
for (Diagnostic diagnostic : actual) { for (ActualDiagnostic actualDiagnostic : actual) {
assert diagnostic.getPsiFile().equals(file) assert actualDiagnostic.getFile().equals(file)
: "All diagnostics should come from the same file: " + diagnostic.getPsiFile() + ", " + file; : "All diagnostics should come from the same file: " + actualDiagnostic.getFile() + ", " + file;
} }
} }
private static void unexpectedDiagnostics(DiagnosticDescriptor descriptor, DiagnosticDiffCallbacks callbacks) { private static void unexpectedDiagnostics(DiagnosticDescriptor descriptor, DiagnosticDiffCallbacks callbacks) {
for (Diagnostic diagnostic : descriptor.diagnostics) { for (ActualDiagnostic diagnostic : descriptor.diagnostics) {
callbacks.unexpectedDiagnostic(TextDiagnostic.asTextDiagnostic(diagnostic), descriptor.start, descriptor.end); callbacks.unexpectedDiagnostic(TextDiagnostic.asTextDiagnostic(diagnostic), descriptor.start, descriptor.end);
} }
} }
@@ -371,28 +365,30 @@ public class CheckerTestUtil {
return matcher.replaceAll(""); return matcher.replaceAll("");
} }
public static StringBuffer addDiagnosticMarkersToText(@NotNull PsiFile psiFile, @NotNull Collection<Diagnostic> diagnostics) { public static StringBuffer addDiagnosticMarkersToText(@NotNull PsiFile psiFile, @NotNull Collection<ActualDiagnostic> diagnostics) {
return addDiagnosticMarkersToText(psiFile, diagnostics, Collections.<Diagnostic, TextDiagnostic>emptyMap(), return addDiagnosticMarkersToText(
new Function<PsiFile, String>() { psiFile, diagnostics, Collections.<ActualDiagnostic, TextDiagnostic>emptyMap(),
@Override new Function<PsiFile, String>() {
public String fun(PsiFile file) { @Override
return file.getText(); public String fun(PsiFile file) {
} return file.getText();
}); }
}
);
} }
public static StringBuffer addDiagnosticMarkersToText( public static StringBuffer addDiagnosticMarkersToText(
@NotNull final PsiFile psiFile, @NotNull final PsiFile psiFile,
@NotNull Collection<Diagnostic> diagnostics, @NotNull Collection<ActualDiagnostic> diagnostics,
@NotNull Map<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic, @NotNull Map<ActualDiagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic,
@NotNull Function<PsiFile, String> getFileText @NotNull Function<PsiFile, String> getFileText
) { ) {
String text = getFileText.fun(psiFile); String text = getFileText.fun(psiFile);
StringBuffer result = new StringBuffer(); StringBuffer result = new StringBuffer();
diagnostics = Collections2.filter(diagnostics, new Predicate<Diagnostic>() { diagnostics = Collections2.filter(diagnostics, new Predicate<ActualDiagnostic>() {
@Override @Override
public boolean apply(Diagnostic diagnostic) { public boolean apply(ActualDiagnostic actualDiagnostic) {
return psiFile.equals(diagnostic.getPsiFile()); return psiFile.equals(actualDiagnostic.getFile());
} }
}); });
if (!diagnostics.isEmpty()) { if (!diagnostics.isEmpty()) {
@@ -449,11 +445,11 @@ public class CheckerTestUtil {
private static void openDiagnosticsString( private static void openDiagnosticsString(
StringBuffer result, StringBuffer result,
DiagnosticDescriptor currentDescriptor, DiagnosticDescriptor currentDescriptor,
Map<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic Map<ActualDiagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic
) { ) {
result.append("<!"); result.append("<!");
for (Iterator<Diagnostic> iterator = currentDescriptor.diagnostics.iterator(); iterator.hasNext(); ) { for (Iterator<ActualDiagnostic> iterator = currentDescriptor.diagnostics.iterator(); iterator.hasNext(); ) {
Diagnostic diagnostic = iterator.next(); ActualDiagnostic diagnostic = iterator.next();
TextDiagnostic expectedDiagnostic = diagnosticToExpectedDiagnostic.get(diagnostic); TextDiagnostic expectedDiagnostic = diagnosticToExpectedDiagnostic.get(diagnostic);
if (expectedDiagnostic != null) { if (expectedDiagnostic != null) {
TextDiagnostic actualTextDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic); TextDiagnostic actualTextDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic);
@@ -465,7 +461,7 @@ public class CheckerTestUtil {
} }
} }
else { else {
result.append(diagnostic.getFactory().getName()); result.append(diagnostic.getName());
} }
if (iterator.hasNext()) { if (iterator.hasNext()) {
result.append(", "); result.append(", ");
@@ -579,12 +575,13 @@ public class CheckerTestUtil {
} }
@NotNull @NotNull
private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(@NotNull Collection<Diagnostic> diagnostics) { private static List<DiagnosticDescriptor> getSortedDiagnosticDescriptors(@NotNull Collection<ActualDiagnostic> diagnostics) {
LinkedListMultimap<TextRange, Diagnostic> diagnosticsGroupedByRanges = LinkedListMultimap.create(); LinkedListMultimap<TextRange, ActualDiagnostic> diagnosticsGroupedByRanges = LinkedListMultimap.create();
for (Diagnostic diagnostic : diagnostics) { for (ActualDiagnostic actualDiagnostic : diagnostics) {
Diagnostic diagnostic = actualDiagnostic.diagnostic;
if (!diagnostic.isValid()) continue; if (!diagnostic.isValid()) continue;
for (TextRange textRange : diagnostic.getTextRanges()) { for (TextRange textRange : diagnostic.getTextRanges()) {
diagnosticsGroupedByRanges.put(textRange, diagnostic); diagnosticsGroupedByRanges.put(textRange, actualDiagnostic);
} }
} }
List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList(); List<DiagnosticDescriptor> diagnosticDescriptors = Lists.newArrayList();
@@ -605,17 +602,17 @@ public class CheckerTestUtil {
private static class DiagnosticDescriptor { private static class DiagnosticDescriptor {
private final int start; private final int start;
private final int end; private final int end;
private final List<Diagnostic> diagnostics; private final List<ActualDiagnostic> diagnostics;
DiagnosticDescriptor(int start, int end, List<Diagnostic> diagnostics) { DiagnosticDescriptor(int start, int end, List<ActualDiagnostic> diagnostics) {
this.start = start; this.start = start;
this.end = end; this.end = end;
this.diagnostics = diagnostics; this.diagnostics = diagnostics;
} }
public Map<Diagnostic, TextDiagnostic> getTextDiagnosticsMap() { public Map<ActualDiagnostic, TextDiagnostic> getTextDiagnosticsMap() {
Map<Diagnostic, TextDiagnostic> diagnosticMap = new IdentityHashMap<Diagnostic, TextDiagnostic>(); Map<ActualDiagnostic, TextDiagnostic> diagnosticMap = new HashMap<ActualDiagnostic, TextDiagnostic>();
for (Diagnostic diagnostic : diagnostics) { for (ActualDiagnostic diagnostic : diagnostics) {
diagnosticMap.put(diagnostic, TextDiagnostic.asTextDiagnostic(diagnostic)); diagnosticMap.put(diagnostic, TextDiagnostic.asTextDiagnostic(diagnostic));
} }
return diagnosticMap; return diagnosticMap;
@@ -634,6 +631,40 @@ public class CheckerTestUtil {
} }
} }
public static class ActualDiagnostic {
public final Diagnostic diagnostic;
ActualDiagnostic(@NotNull Diagnostic diagnostic) {
this.diagnostic = diagnostic;
}
@NotNull
public String getName() {
return diagnostic.getFactory().getName();
}
@NotNull
public PsiFile getFile() {
return diagnostic.getPsiFile();
}
@Override
public boolean equals(Object obj) {
// '==' on diagnostics is intentional here
return obj instanceof ActualDiagnostic && ((ActualDiagnostic) obj).diagnostic == diagnostic;
}
@Override
public int hashCode() {
return System.identityHashCode(diagnostic);
}
@Override
public String toString() {
return diagnostic.toString();
}
}
public static class TextDiagnostic { public static class TextDiagnostic {
@NotNull @NotNull
private static TextDiagnostic parseDiagnostic(String text) { private static TextDiagnostic parseDiagnostic(String text) {
@@ -663,9 +694,11 @@ public class CheckerTestUtil {
} }
@NotNull @NotNull
public static TextDiagnostic asTextDiagnostic(@NotNull Diagnostic diagnostic) { public static TextDiagnostic asTextDiagnostic(@NotNull ActualDiagnostic actualDiagnostic) {
Diagnostic diagnostic = actualDiagnostic.diagnostic;
//noinspection TestOnlyProblems
DiagnosticRenderer renderer = DefaultErrorMessages.getRendererForDiagnostic(diagnostic); DiagnosticRenderer renderer = DefaultErrorMessages.getRendererForDiagnostic(diagnostic);
String diagnosticName = diagnostic.getFactory().getName(); String diagnosticName = actualDiagnostic.getName();
if (renderer instanceof AbstractDiagnosticWithParametersRenderer) { if (renderer instanceof AbstractDiagnosticWithParametersRenderer) {
//noinspection unchecked //noinspection unchecked
Object[] renderParameters = ((AbstractDiagnosticWithParametersRenderer) renderer).renderParameters(diagnostic); Object[] renderParameters = ((AbstractDiagnosticWithParametersRenderer) renderer).renderParameters(diagnostic);
@@ -27,6 +27,7 @@ import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.asJava.getJvmSignatureDiagnostics import org.jetbrains.kotlin.asJava.getJvmSignatureDiagnostics
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestFile
import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestModule import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest.TestModule
import org.jetbrains.kotlin.checkers.CheckerTestUtil.ActualDiagnostic
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.diagnostics.*
@@ -201,7 +202,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
} }
val jvmSignatureDiagnostics = if (skipJvmSignatureDiagnostics) val jvmSignatureDiagnostics = if (skipJvmSignatureDiagnostics)
emptySet<Diagnostic>() emptySet<ActualDiagnostic>()
else else
computeJvmSignatureDiagnostics(bindingContext) computeJvmSignatureDiagnostics(bindingContext)
@@ -210,7 +211,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors( CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(
bindingContext, ktFile, markDynamicCalls, dynamicCallDescriptors bindingContext, ktFile, markDynamicCalls, dynamicCallDescriptors
) + jvmSignatureDiagnostics, ) + jvmSignatureDiagnostics,
whatDiagnosticsToConsider { whatDiagnosticsToConsider.value(it.diagnostic) }
) )
val diagnosticToExpectedDiagnostic = CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks { val diagnosticToExpectedDiagnostic = CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, object : CheckerTestUtil.DiagnosticDiffCallbacks {
@@ -249,13 +250,13 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
return ok[0] return ok[0]
} }
private fun computeJvmSignatureDiagnostics(bindingContext: BindingContext): Set<Diagnostic> { private fun computeJvmSignatureDiagnostics(bindingContext: BindingContext): Set<ActualDiagnostic> {
val jvmSignatureDiagnostics = HashSet<Diagnostic>() val jvmSignatureDiagnostics = HashSet<ActualDiagnostic>()
val declarations = PsiTreeUtil.findChildrenOfType(ktFile, KtDeclaration::class.java) val declarations = PsiTreeUtil.findChildrenOfType(ktFile, KtDeclaration::class.java)
for (declaration in declarations) { for (declaration in declarations) {
val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics, val diagnostics = getJvmSignatureDiagnostics(declaration, bindingContext.diagnostics,
GlobalSearchScope.allScope(project)) ?: continue GlobalSearchScope.allScope(project)) ?: continue
jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration)) jvmSignatureDiagnostics.addAll(diagnostics.forElement(declaration).map { ActualDiagnostic(it) })
} }
return jvmSignatureDiagnostics return jvmSignatureDiagnostics
} }
@@ -20,9 +20,9 @@ import com.google.common.collect.Lists;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.checkers.CheckerTestUtil.ActualDiagnostic;
import org.jetbrains.kotlin.checkers.CheckerTestUtil.DiagnosedRange; import org.jetbrains.kotlin.checkers.CheckerTestUtil.DiagnosedRange;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil; import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
@@ -53,7 +53,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
public void testEquals() throws Exception { public void testEquals() throws Exception {
doTest(new TheTest() { doTest(new TheTest() {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
} }
}); });
} }
@@ -62,7 +62,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosticData typeMismatch1 = diagnostics.get(1); final DiagnosticData typeMismatch1 = diagnostics.get(1);
doTest(new TheTest(missing(typeMismatch1)) { doTest(new TheTest(missing(typeMismatch1)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnostics.remove(typeMismatch1.index); diagnostics.remove(typeMismatch1.index);
} }
}); });
@@ -72,7 +72,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosticData typeMismatch1 = diagnostics.get(1); final DiagnosticData typeMismatch1 = diagnostics.get(1);
doTest(new TheTest(unexpected(typeMismatch1)) { doTest(new TheTest(unexpected(typeMismatch1)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(typeMismatch1.index); diagnosedRanges.remove(typeMismatch1.index);
} }
}); });
@@ -83,7 +83,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosticData unresolvedReference = diagnostics.get(6); final DiagnosticData unresolvedReference = diagnostics.get(6);
doTest(new TheTest(unexpected(typeMismatch1), missing(unresolvedReference)) { doTest(new TheTest(unexpected(typeMismatch1), missing(unresolvedReference)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(typeMismatch1.rangeIndex); diagnosedRanges.remove(typeMismatch1.rangeIndex);
diagnostics.remove(unresolvedReference.index); diagnostics.remove(unresolvedReference.index);
} }
@@ -95,7 +95,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosticData typeMismatch3 = diagnostics.get(5); final DiagnosticData typeMismatch3 = diagnostics.get(5);
doTest(new TheTest(unexpected(noneApplicable), missing(typeMismatch3)) { doTest(new TheTest(unexpected(noneApplicable), missing(typeMismatch3)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnosedRanges.remove(noneApplicable.rangeIndex); diagnosedRanges.remove(noneApplicable.rangeIndex);
diagnostics.remove(typeMismatch3.index); diagnostics.remove(typeMismatch3.index);
} }
@@ -108,7 +108,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosedRange range = asDiagnosticRange(unused, unusedDiagnostic); final DiagnosedRange range = asDiagnosticRange(unused, unusedDiagnostic);
doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNUSED_VARIABLE(a)", unused.startOffset, unused.endOffset)) { doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNUSED_VARIABLE(a)", unused.startOffset, unused.endOffset)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnosedRanges.set(unused.rangeIndex, range); diagnosedRanges.set(unused.rangeIndex, range);
} }
}); });
@@ -121,7 +121,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
final DiagnosedRange range = asDiagnosticRange(unresolvedReference, unusedDiagnostic, toManyArguments); final DiagnosedRange range = asDiagnosticRange(unresolvedReference, unusedDiagnostic, toManyArguments);
doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNRESOLVED_REFERENCE(xx)", unresolvedReference.startOffset, unresolvedReference.endOffset)) { doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNRESOLVED_REFERENCE(xx)", unresolvedReference.startOffset, unresolvedReference.endOffset)) {
@Override @Override
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) { protected void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
diagnosedRanges.set(unresolvedReference.rangeIndex, range); diagnosedRanges.set(unresolvedReference.rangeIndex, range);
} }
}); });
@@ -153,15 +153,16 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
List<DiagnosedRange> diagnosedRanges = Lists.newArrayList(); List<DiagnosedRange> diagnosedRanges = Lists.newArrayList();
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null); List<ActualDiagnostic> actualDiagnostics =
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR); CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null);
Collections.sort(actualDiagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
makeTestData(diagnostics, diagnosedRanges); makeTestData(actualDiagnostics, diagnosedRanges);
List<String> expectedMessages = Lists.newArrayList(expected); List<String> expectedMessages = Lists.newArrayList(expected);
final List<String> actualMessages = Lists.newArrayList(); final List<String> actualMessages = Lists.newArrayList();
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { CheckerTestUtil.diagnosticsDiff(diagnosedRanges, actualDiagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override @Override
public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) { public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) {
actualMessages.add(missing(diagnostic.getName(), expectedStart, expectedEnd)); actualMessages.add(missing(diagnostic.getName(), expectedStart, expectedEnd));
@@ -194,7 +195,7 @@ public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
return stringBuilder.toString(); return stringBuilder.toString();
} }
protected abstract void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges); protected abstract void makeTestData(List<ActualDiagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges);
} }
private static String wrongParameters(String expected, String actual, int start, int end) { private static String wrongParameters(String expected, String actual, int start, int end) {
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.kotlin.checkers.CheckerTestUtil; import org.jetbrains.kotlin.checkers.CheckerTestUtil;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
@@ -44,7 +43,8 @@ public class CopyAsDiagnosticTestAction extends AnAction {
BindingContext bindingContext = ResolutionUtils.analyzeFully((KtFile) psiFile); BindingContext bindingContext = ResolutionUtils.analyzeFully((KtFile) psiFile);
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null); List<CheckerTestUtil.ActualDiagnostic> diagnostics =
CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null);
String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, diagnostics).toString(); String result = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, diagnostics).toString();
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
@@ -54,7 +54,6 @@ public class CopyAsDiagnosticTestAction extends AnAction {
}); });
} }
@Override @Override
public void update(AnActionEvent e) { public void update(AnActionEvent e) {
e.getPresentation().setVisible(ApplicationManager.getApplication().isInternal()); e.getPresentation().setVisible(ApplicationManager.getApplication().isInternal());
@@ -63,5 +62,4 @@ public class CopyAsDiagnosticTestAction extends AnAction {
PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE); PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
e.getPresentation().setEnabled(editor != null && psiFile instanceof KtFile); e.getPresentation().setEnabled(editor != null && psiFile instanceof KtFile);
} }
} }