From caf44969a4552f3224bf17c3a17f469113b6d439 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Tue, 9 Sep 2014 15:54:32 +0400 Subject: [PATCH] Add support for check diagnostic parameters in test. --- .../jet/checkers/CheckerTestUtil.java | 248 ++++++++++++--- .../checkerTestUtil/test_with_diagnostic.kt | 15 + .../test_with_diagnostic.lazy.log | 295 ++++++++++++++++++ .../checkerTestUtil/test_with_diagnostic.txt | 13 + .../jet/checkers/BaseDiagnosticsTest.java | 28 +- .../jet/checkers/CheckerTestUtilTest.java | 91 +++++- 6 files changed, 630 insertions(+), 60 deletions(-) create mode 100644 compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.kt create mode 100644 compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.lazy.log create mode 100644 compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.txt diff --git a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java index 45b10f8a690..fd2adc9a681 100644 --- a/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/checkers/CheckerTestUtil.java @@ -19,16 +19,24 @@ package org.jetbrains.jet.checkers; import com.google.common.base.Predicate; import com.google.common.collect.*; import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Function; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; 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.diagnostics.rendering.AbstractDiagnosticWithParametersRenderer; +import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages; +import org.jetbrains.jet.lang.diagnostics.rendering.DiagnosticFactoryToRendererMap; +import org.jetbrains.jet.lang.diagnostics.rendering.DiagnosticRenderer; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetReferenceExpression; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; @@ -64,11 +72,18 @@ public class CheckerTestUtil { return ranges1.size() - ranges2.size(); } }; - private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()"); - private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile("\\w+"); + + private static final String IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE"; + private static final String DIAGNOSTIC_PARAMETER = "[^\\)\\(\\s;]+"; + private static final String INDIVIDUAL_DIAGNOSTIC = "(\\w+)(\\(" + DIAGNOSTIC_PARAMETER + "(;\\s*" + DIAGNOSTIC_PARAMETER + ")*\\))?"; + private static final Pattern RANGE_START_OR_END_PATTERN = Pattern.compile("()|()"); + private static final Pattern INDIVIDUAL_DIAGNOSTIC_PATTERN = Pattern.compile(INDIVIDUAL_DIAGNOSTIC); + private static final Pattern INDIVIDUAL_PARAMETER_PATTERN = Pattern.compile(DIAGNOSTIC_PARAMETER); public static List getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, final PsiElement root) { - ArrayList diagnostics = new ArrayList(); + List diagnostics = new ArrayList(); diagnostics.addAll(Collections2.filter(bindingContext.getDiagnostics().all(), new Predicate() { @Override @@ -117,11 +132,13 @@ public class CheckerTestUtil { } public interface DiagnosticDiffCallbacks { - void missingDiagnostic(String type, int expectedStart, int expectedEnd); - void unexpectedDiagnostic(String type, int actualStart, int actualEnd); + void missingDiagnostic(TextDiagnostic diagnostic, int expectedStart, int expectedEnd); + void wrongParametersDiagnostic(TextDiagnostic expectedDiagnostic, TextDiagnostic actualDiagnostic, int start, int end); + void unexpectedDiagnostic(TextDiagnostic diagnostic, int actualStart, int actualEnd); } public static void diagnosticsDiff( + Map diagnosticToExpectedDiagnostic, List expected, Collection actual, DiagnosticDiffCallbacks callbacks @@ -164,23 +181,7 @@ public class CheckerTestUtil { currentActual = safeAdvance(actualDiagnostics); } else { - assert expectedStart == actualStart && expectedEnd == actualEnd; - Multiset actualDiagnosticTypes = currentActual.getDiagnosticTypeStrings(); - Multiset expectedDiagnosticTypes = currentExpected.getDiagnostics(); - if (!actualDiagnosticTypes.equals(expectedDiagnosticTypes)) { - Multiset notInActualTypes = HashMultiset.create(expectedDiagnosticTypes); - Multisets.removeOccurrences(notInActualTypes, actualDiagnosticTypes); - - Multiset notInExpectedTypes = HashMultiset.create(actualDiagnosticTypes); - Multisets.removeOccurrences(notInExpectedTypes, expectedDiagnosticTypes); - - for (String type : notInActualTypes) { - callbacks.missingDiagnostic(type, expectedStart, expectedEnd); - } - for (String type : notInExpectedTypes) { - callbacks.unexpectedDiagnostic(type, actualStart, actualEnd); - } - } + compareDiagnostics(callbacks, currentExpected, currentActual, diagnosticToExpectedDiagnostic); currentExpected = safeAdvance(expectedDiagnostics); currentActual = safeAdvance(actualDiagnostics); } @@ -196,6 +197,61 @@ public class CheckerTestUtil { } } + private static void compareDiagnostics( + @NotNull DiagnosticDiffCallbacks callbacks, + @NotNull DiagnosedRange currentExpected, + @NotNull DiagnosticDescriptor currentActual, + @NotNull Map diagnosticToInput + ) { + int expectedStart = currentExpected.getStart(); + int expectedEnd = currentExpected.getEnd(); + + int actualStart = currentActual.getStart(); + int actualEnd = currentActual.getEnd(); + assert expectedStart == actualStart && expectedEnd == actualEnd; + + Map actualDiagnostics = currentActual.getTextDiagnosticsMap(); + List expectedDiagnostics = currentExpected.getDiagnostics(); + + for (TextDiagnostic expectedDiagnostic : expectedDiagnostics) { + boolean diagnosticFound = false; + for (Diagnostic actualDiagnostic : actualDiagnostics.keySet()) { + TextDiagnostic actualTextDiagnostic = actualDiagnostics.get(actualDiagnostic); + if (expectedDiagnostic.getName().equals(actualTextDiagnostic.getName())) { + if (!compareTextDiagnostic(expectedDiagnostic, actualTextDiagnostic)) { + callbacks.wrongParametersDiagnostic(expectedDiagnostic, actualTextDiagnostic, expectedStart, expectedEnd); + } + + actualDiagnostics.remove(actualDiagnostic); + diagnosticToInput.put(actualDiagnostic, expectedDiagnostic); + diagnosticFound = true; + break; + } + } + if (!diagnosticFound) callbacks.missingDiagnostic(expectedDiagnostic, expectedStart, expectedEnd); + } + + for (TextDiagnostic unexpectedDiagnostic : actualDiagnostics.values()) { + callbacks.unexpectedDiagnostic(unexpectedDiagnostic, actualStart, actualEnd); + } + } + + private static boolean compareTextDiagnostic(@NotNull TextDiagnostic expected, @NotNull TextDiagnostic actual) { + if (!expected.getName().equals(actual.getName())) return false; + + if (expected.getParameters() == null) return true; + if (actual.getParameters() == null || expected.getParameters().size() != actual.getParameters().size()) return false; + + for (int index = 0; index < expected.getParameters().size(); index++) { + String expectedParameter = expected.getParameters().get(index); + String actualParameter = actual.getParameters().get(index); + if (!expectedParameter.equals(IGNORE_DIAGNOSTIC_PARAMETER) && !expectedParameter.equals(actualParameter)) { + return false; + } + } + return true; + } + private static void assertSameFile(Collection actual) { if (actual.isEmpty()) return; PsiFile file = actual.iterator().next().getPsiElement().getContainingFile(); @@ -209,14 +265,14 @@ public class CheckerTestUtil { for (Diagnostic diagnostic : actual) { List textRanges = diagnostic.getTextRanges(); for (TextRange textRange : textRanges) { - callbacks.unexpectedDiagnostic(diagnostic.getFactory().getName(), textRange.getStartOffset(), textRange.getEndOffset()); + callbacks.unexpectedDiagnostic(TextDiagnostic.asTextDiagnostic(diagnostic), textRange.getStartOffset(), textRange.getEndOffset()); } } } private static void missingDiagnostics(DiagnosticDiffCallbacks callbacks, DiagnosedRange currentExpected) { - for (String type : currentExpected.getDiagnostics()) { - callbacks.missingDiagnostic(type, currentExpected.getStart(), currentExpected.getEnd()); + for (TextDiagnostic diagnostic : currentExpected.getDiagnostics()) { + callbacks.missingDiagnostic(diagnostic, currentExpected.getStart(), currentExpected.getEnd()); } } @@ -255,8 +311,8 @@ public class CheckerTestUtil { return matcher.replaceAll(""); } - public static StringBuffer addDiagnosticMarkersToText(@NotNull final PsiFile psiFile, @NotNull Collection diagnostics) { - return addDiagnosticMarkersToText(psiFile, diagnostics, new Function() { + public static StringBuffer addDiagnosticMarkersToText(@NotNull PsiFile psiFile, @NotNull Collection diagnostics) { + return addDiagnosticMarkersToText(psiFile, diagnostics, Collections.emptyMap(), new Function() { @Override public String fun(PsiFile file) { return file.getText(); @@ -267,6 +323,7 @@ public class CheckerTestUtil { public static StringBuffer addDiagnosticMarkersToText( @NotNull final PsiFile psiFile, @NotNull Collection diagnostics, + @NotNull Map diagnosticToExpectedDiagnostic, @NotNull Function getFileText ) { String text = getFileText.fun(psiFile); @@ -291,7 +348,7 @@ public class CheckerTestUtil { opened.pop(); } while (currentDescriptor != null && i == currentDescriptor.start) { - openDiagnosticsString(result, currentDescriptor); + openDiagnosticsString(result, currentDescriptor, diagnosticToExpectedDiagnostic); if (currentDescriptor.getEnd() == i) { closeDiagnosticString(result); } @@ -311,7 +368,7 @@ public class CheckerTestUtil { if (currentDescriptor != null) { assert currentDescriptor.start == text.length(); assert currentDescriptor.end == text.length(); - openDiagnosticsString(result, currentDescriptor); + openDiagnosticsString(result, currentDescriptor, diagnosticToExpectedDiagnostic); opened.push(currentDescriptor); } @@ -329,11 +386,25 @@ public class CheckerTestUtil { return result; } - private static void openDiagnosticsString(StringBuffer result, DiagnosticDescriptor currentDescriptor) { + private static void openDiagnosticsString( + StringBuffer result, + DiagnosticDescriptor currentDescriptor, + Map diagnosticToExpectedDiagnostic + ) { result.append(" iterator = currentDescriptor.diagnostics.iterator(); iterator.hasNext(); ) { Diagnostic diagnostic = iterator.next(); - result.append(diagnostic.getFactory().getName()); + if (diagnosticToExpectedDiagnostic.containsKey(diagnostic)) { + TextDiagnostic expectedDiagnostic = diagnosticToExpectedDiagnostic.get(diagnostic); + TextDiagnostic actualTextDiagnostic = TextDiagnostic.asTextDiagnostic(diagnostic); + if (compareTextDiagnostic(expectedDiagnostic, actualTextDiagnostic)) { + result.append(expectedDiagnostic.asString()); + } else { + result.append(actualTextDiagnostic.asString()); + } + } else { + result.append(diagnostic.getFactory().getName()); + } if (iterator.hasNext()) { result.append(", "); } @@ -455,7 +526,7 @@ public class CheckerTestUtil { } Collections.sort(diagnosticDescriptors, new Comparator() { @Override - public int compare(DiagnosticDescriptor d1, DiagnosticDescriptor d2) { + public int compare(@NotNull DiagnosticDescriptor d1, @NotNull DiagnosticDescriptor d2) { // Start early -- go first; start at the same offset, the one who end later is the outer, i.e. goes first return (d1.start != d2.start) ? d1.start - d2.start : d2.end - d1.end; } @@ -474,12 +545,12 @@ public class CheckerTestUtil { this.diagnostics = diagnostics; } - public Multiset getDiagnosticTypeStrings() { - Multiset actualDiagnosticTypes = HashMultiset.create(); + public Map getTextDiagnosticsMap() { + Map diagnosticMap = new IdentityHashMap(); for (Diagnostic diagnostic : diagnostics) { - actualDiagnosticTypes.add(diagnostic.getFactory().getName()); + diagnosticMap.put(diagnostic, TextDiagnostic.asTextDiagnostic(diagnostic)); } - return actualDiagnosticTypes; + return diagnosticMap; } public int getStart() { @@ -499,13 +570,110 @@ public class CheckerTestUtil { } } + public static class TextDiagnostic { + @NotNull + private static TextDiagnostic parseDiagnostic(String text) { + Matcher matcher = INDIVIDUAL_DIAGNOSTIC_PATTERN.matcher(text); + if (!matcher.find()) + throw new IllegalArgumentException("Could not parse diagnostic: " + text); + String name = matcher.group(1); + + String parameters = matcher.group(2); + if (parameters == null) { + return new TextDiagnostic(name, null); + } + + List parsedParameters = new SmartList(); + Matcher parametersMatcher = INDIVIDUAL_PARAMETER_PATTERN.matcher(parameters); + while (parametersMatcher.find()) + parsedParameters.add(parametersMatcher.group()); + return new TextDiagnostic(name, parsedParameters); + } + + @NotNull + public static TextDiagnostic asTextDiagnostic(@NotNull Diagnostic diagnostic) { + DiagnosticRenderer renderer = getRenderer(diagnostic); + String diagnosticName = diagnostic.getFactory().getName(); + if (renderer instanceof AbstractDiagnosticWithParametersRenderer) { + //noinspection unchecked + Object[] renderParameters = ((AbstractDiagnosticWithParametersRenderer) renderer).renderParameters(diagnostic); + List parameters = ContainerUtil.map(renderParameters, new Function() { + @Override + public String fun(Object o) { + return o != null ? o.toString() : "null"; + } + }); + return new TextDiagnostic(diagnosticName, parameters); + } + return new TextDiagnostic(diagnosticName, null); + } + + @Nullable + private static DiagnosticRenderer getRenderer(@NotNull Diagnostic diagnostic) { + for (DiagnosticFactoryToRendererMap map : DefaultErrorMessages.MAPS) { + DiagnosticRenderer renderer = map.get(diagnostic.getFactory()); + if (renderer != null) + return renderer; + } + return null; + } + + + @NotNull + private final String name; + @Nullable + private final List parameters; + + public TextDiagnostic(@NotNull String name, @Nullable List parameters) { + this.name = name; + this.parameters = parameters; + } + + @NotNull + public String getName() { + return name; + } + + @Nullable + public List getParameters() { + return parameters; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TextDiagnostic that = (TextDiagnostic) o; + + if (!name.equals(that.name)) return false; + if (parameters != null ? !parameters.equals(that.parameters) : that.parameters != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + (parameters != null ? parameters.hashCode() : 0); + return result; + } + + @NotNull + public String asString() { + if (parameters == null) + return name; + return name + '(' + StringUtil.join(parameters, "; ") + ')'; + } + } + public static class DiagnosedRange { private final int start; private int end; - private final Multiset diagnostics = HashMultiset.create(); + private final List diagnostics = ContainerUtil.newSmartList(); private PsiFile file; - private DiagnosedRange(int start) { + protected DiagnosedRange(int start) { this.start = start; } @@ -517,7 +685,7 @@ public class CheckerTestUtil { return end; } - public Multiset getDiagnostics() { + public List getDiagnostics() { return diagnostics; } @@ -526,7 +694,7 @@ public class CheckerTestUtil { } public void addDiagnostic(String diagnostic) { - diagnostics.add(diagnostic); + diagnostics.add(TextDiagnostic.parseDiagnostic(diagnostic)); } public void setFile(@NotNull PsiFile file) { diff --git a/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.kt b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.kt new file mode 100644 index 00000000000..b58374ab28e --- /dev/null +++ b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.kt @@ -0,0 +1,15 @@ +fun foo(u : Unit) : Int = 1 + +fun test() : Int { + foo(1) + val a : () -> Unit = { + foo(1) +} +return 1 - "1" +} + +class A() { + val x : Int = foo1(xx) +} + +fun foo1() {} \ No newline at end of file diff --git a/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.lazy.log b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.lazy.log new file mode 100644 index 00000000000..016dc8d1998 --- /dev/null +++ b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.lazy.log @@ -0,0 +1,295 @@ +DescriptorResolver@0 { + = null +} + +LazyJavaPackageFragmentProvider@1 { + packageFragments('': FqName@2) = LazyJavaPackageFragment@3[''] + packageFragments('A': FqName@4) = null + packageFragments('Int': FqName@5) = null + packageFragments('Unit': FqName@6) = null + packageFragments('java': FqName@7) = LazyJavaPackageFragment@8['java'] + packageFragments('java.lang': FqName@9) = LazyJavaPackageFragment@10['lang'] + packageFragments('java.lang.Int': FqName@11) = null + packageFragments('java.lang.Unit': FqName@12) = null + packageFragments('java.lang.xx': FqName@13) = null + packageFragments('kotlin': FqName@14) = null + packageFragments('kotlin.Int': FqName@15) = null + packageFragments('kotlin.Unit': FqName@16) = null + packageFragments('kotlin.io': FqName@17) = null + packageFragments('kotlin.jvm': FqName@18) = null + packageFragments('kotlin.xx': FqName@19) = null + packageFragments('xx': FqName@20) = null +} + +LazyJavaPackageFragment@3[''] { + classes('Int': Name@21) = null // through LazyPackageFragmentScopeForJavaPackage@22 + classes('Unit': Name@23) = null // through LazyPackageFragmentScopeForJavaPackage@22 + classes('foo': Name@24) = null // through LazyPackageFragmentScopeForJavaPackage@22 + classes('foo1': Name@25) = null // through LazyPackageFragmentScopeForJavaPackage@22 + classes('minus': Name@26) = null // through LazyPackageFragmentScopeForJavaPackage@22 + classes('xx': Name@27) = null // through LazyPackageFragmentScopeForJavaPackage@22 + deserializedPackageScope = Empty@28 // through LazyPackageFragmentScopeForJavaPackage@22 + functions('foo': Name@24) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@22 + functions('foo1': Name@25) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@22 + functions('minus': Name@26) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@22 + functions('xx': Name@30) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@22 + memberIndex = computeMemberIndex$1@31 // through LazyPackageFragmentScopeForJavaPackage@22 +} + +LazyJavaPackageFragment@8['java'] { + classes('lang': Name@32) = null // through LazyPackageFragmentScopeForJavaPackage@33 + deserializedPackageScope = Empty@28 // through LazyPackageFragmentScopeForJavaPackage@33 + functions('lang': Name@34) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@33 + memberIndex = computeMemberIndex$1@35 // through LazyPackageFragmentScopeForJavaPackage@33 +} + +LazyJavaPackageFragment@10['lang'] { + classes('foo': Name@24) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('foo1': Name@25) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('minus': Name@26) = null // through LazyPackageFragmentScopeForJavaPackage@36 + classes('xx': Name@27) = null // through LazyPackageFragmentScopeForJavaPackage@36 + deserializedPackageScope = Empty@28 // through LazyPackageFragmentScopeForJavaPackage@36 + functions('foo': Name@24) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('foo1': Name@25) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('minus': Name@26) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + functions('xx': Name@30) = EmptyList@29[empty] // through LazyPackageFragmentScopeForJavaPackage@36 + memberIndex = computeMemberIndex$1@37 // through LazyPackageFragmentScopeForJavaPackage@36 +} + +ResolutionTaskHolder@38 { + = ArrayList@39[1] { ResolutionCandidate@40 } + = ArrayList@41[1] { ResolutionCandidate@40 } + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} + +ResolutionTaskHolder@42 { + = ArrayList@43[1] { ResolutionCandidate@44 } + = ArrayList@45[1] { ResolutionCandidate@44 } + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} + +ResolutionTaskHolder@46 { + = ArrayList@47[1] { ResolutionCandidate@48 } + = ArrayList@49[1] { ResolutionCandidate@48 } + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} + +ResolutionTaskHolder@50 { + = ArrayList@51[8] { ResolutionCandidate@52, ResolutionCandidate@53, ResolutionCandidate@54, ... } + = ArrayList@55[8] { ResolutionCandidate@52, ResolutionCandidate@53, ResolutionCandidate@54, ... } + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} + +ResolutionTaskHolder@56 { + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} + +ResolutionTaskHolder@57 { + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] + = EmptyList@29[empty] +} diff --git a/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.txt b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.txt new file mode 100644 index 00000000000..356134fb893 --- /dev/null +++ b/compiler/testData/diagnostics/checkerTestUtil/test_with_diagnostic.txt @@ -0,0 +1,13 @@ +package + +internal fun foo(/*0*/ u: kotlin.Unit): kotlin.Int +internal fun foo1(): kotlin.Unit +internal fun test(): kotlin.Int + +internal final class A { + public constructor A() + internal final val x: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java b/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java index b9509bff054..c35f976ce73 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/BaseDiagnosticsTest.java @@ -334,24 +334,40 @@ public abstract class BaseDiagnosticsTest extends jvmSignatureDiagnostics), whatDiagnosticsToConsider ); - CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { + + Map diagnosticToExpectedDiagnostic = ContainerUtil.newHashMap(); + CheckerTestUtil.diagnosticsDiff(diagnosticToExpectedDiagnostic, diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { @Override - public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { - String message = "Missing " + type + DiagnosticUtils.atLocation(jetFile, new TextRange(expectedStart, expectedEnd)); + public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) { + String message = "Missing " + diagnostic.getName() + DiagnosticUtils.atLocation(jetFile, new TextRange(expectedStart, expectedEnd)); System.err.println(message); ok[0] = false; } @Override - public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) { - String message = "Unexpected " + type + DiagnosticUtils.atLocation(jetFile, new TextRange(actualStart, actualEnd)); + public void wrongParametersDiagnostic( + CheckerTestUtil.TextDiagnostic expectedDiagnostic, + CheckerTestUtil.TextDiagnostic actualDiagnostic, + int start, + int end + ) { + String message = "Parameters of diagnostic not equal at position " + + DiagnosticUtils.atLocation(jetFile, new TextRange(start, end)) + + ". Expected: " + expectedDiagnostic.asString() + ", actual: " + actualDiagnostic.asString(); + System.err.println(message); + ok[0] = false; + } + + @Override + public void unexpectedDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int actualStart, int actualEnd) { + String message = "Unexpected " + diagnostic.getName() + DiagnosticUtils.atLocation(jetFile, new TextRange(actualStart, actualEnd)); System.err.println(message); ok[0] = false; } }); - actualText.append(CheckerTestUtil.addDiagnosticMarkersToText(jetFile, diagnostics, new Function() { + actualText.append(CheckerTestUtil.addDiagnosticMarkersToText(jetFile, diagnostics, diagnosticToExpectedDiagnostic, new Function() { @Override public String fun(PsiFile file) { return file.getText(); diff --git a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java index fda075a7844..c3cccc0c20f 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java +++ b/compiler/tests/org/jetbrains/jet/checkers/CheckerTestUtilTest.java @@ -17,16 +17,20 @@ package org.jetbrains.jet.checkers; import com.google.common.collect.Lists; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.JetLiteFixture; +import org.jetbrains.jet.checkers.CheckerTestUtil.DiagnosedRange; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.lazy.JvmResolveUtil; +import java.io.File; import java.util.Collections; import java.util.List; @@ -50,7 +54,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { public void testEquals() throws Exception { doTest(new TheTest() { @Override - protected void makeTestData(List diagnostics, List diagnosedRanges) { + protected void makeTestData(List diagnostics, List diagnosedRanges) { } }); } @@ -59,7 +63,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { final DiagnosticData typeMismatch1 = diagnostics.get(1); doTest(new TheTest(missing(typeMismatch1)) { @Override - protected void makeTestData(List diagnostics, List diagnosedRanges) { + protected void makeTestData(List diagnostics, List diagnosedRanges) { diagnostics.remove(typeMismatch1.index); } }); @@ -69,7 +73,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { final DiagnosticData typeMismatch1 = diagnostics.get(1); doTest(new TheTest(unexpected(typeMismatch1)) { @Override - protected void makeTestData(List diagnostics, List diagnosedRanges) { + protected void makeTestData(List diagnostics, List diagnosedRanges) { diagnosedRanges.remove(typeMismatch1.index); } }); @@ -80,7 +84,7 @@ public class CheckerTestUtilTest extends JetLiteFixture { final DiagnosticData unresolvedReference = diagnostics.get(6); doTest(new TheTest(unexpected(typeMismatch1), missing(unresolvedReference)) { @Override - protected void makeTestData(List diagnostics, List diagnosedRanges) { + protected void makeTestData(List diagnostics, List diagnosedRanges) { diagnosedRanges.remove(typeMismatch1.rangeIndex); diagnostics.remove(unresolvedReference.index); } @@ -92,13 +96,45 @@ public class CheckerTestUtilTest extends JetLiteFixture { final DiagnosticData typeMismatch3 = diagnostics.get(5); doTest(new TheTest(unexpected(noneApplicable), missing(typeMismatch3)) { @Override - protected void makeTestData(List diagnostics, List diagnosedRanges) { + protected void makeTestData(List diagnostics, List diagnosedRanges) { diagnosedRanges.remove(noneApplicable.rangeIndex); diagnostics.remove(typeMismatch3.index); } }); } + public void testWrongParameters() throws Exception { + final DiagnosticData unused = diagnostics.get(2); + String unusedDiagnostic = asTextDiagnostic(unused, "i"); + final DiagnosedRange range = asDiagnosticRange(unused, unusedDiagnostic); + doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNUSED_VARIABLE(a)", unused.startOffset, unused.endOffset)) { + @Override + protected void makeTestData(List diagnostics, List diagnosedRanges) { + diagnosedRanges.set(unused.rangeIndex, range); + } + }); + } + + public void testWrongParameterInMultiRange() throws Exception { + final DiagnosticData unresolvedReference = diagnostics.get(6); + String unusedDiagnostic = asTextDiagnostic(unresolvedReference, "i"); + String toManyArguments = asTextDiagnostic(diagnostics.get(7)); + final DiagnosedRange range = asDiagnosticRange(unresolvedReference, unusedDiagnostic, toManyArguments); + doTest(new TheTest(wrongParameters(unusedDiagnostic, "UNRESOLVED_REFERENCE(xx)", unresolvedReference.startOffset, unresolvedReference.endOffset)) { + @Override + protected void makeTestData(List diagnostics, List diagnosedRanges) { + diagnosedRanges.set(unresolvedReference.rangeIndex, range); + } + }); + } + + public void testAbstractJetDiagnosticsTest() throws Exception { + AbstractJetDiagnosticsTest test = new AbstractJetDiagnosticsTest() { + {setUp();} + }; + test.doTest(myFullDataPath + File.separatorChar + "test_with_diagnostic.kt"); + } + private static abstract class TheTest { private final String[] expected; @@ -113,9 +149,9 @@ public class CheckerTestUtilTest extends JetLiteFixture { String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile)).toString(); - List diagnosedRanges = Lists.newArrayList(); + List diagnosedRanges = Lists.newArrayList(); CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); - for (CheckerTestUtil.DiagnosedRange diagnosedRange : diagnosedRanges) { + for (DiagnosedRange diagnosedRange : diagnosedRanges) { diagnosedRange.setFile(psiFile); } @@ -127,23 +163,34 @@ public class CheckerTestUtilTest extends JetLiteFixture { List expectedMessages = Lists.newArrayList(expected); final List actualMessages = Lists.newArrayList(); - CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { + CheckerTestUtil.diagnosticsDiff(ContainerUtil.newHashMap(), + diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() { @Override - public void missingDiagnostic(String type, int expectedStart, int expectedEnd) { - actualMessages.add(missing(type, expectedStart, expectedEnd)); + public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) { + actualMessages.add(missing(diagnostic.getName(), expectedStart, expectedEnd)); } @Override - public void unexpectedDiagnostic(String type, int actualStart, int actualEnd) { - actualMessages.add(unexpected(type, actualStart, actualEnd)); + public void wrongParametersDiagnostic( + CheckerTestUtil.TextDiagnostic expectedDiagnostic, + CheckerTestUtil.TextDiagnostic actualDiagnostic, + int start, + int end + ) { + actualMessages.add(wrongParameters(expectedDiagnostic.asString(), actualDiagnostic.asString(), start, end)); + } + + @Override + public void unexpectedDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int actualStart, int actualEnd) { + actualMessages.add(unexpected(diagnostic.getName(), actualStart, actualEnd)); } }); assertEquals(listToString(expectedMessages), listToString(actualMessages)); } - private String listToString(List expectedMessages) { + private static String listToString(List expectedMessages) { StringBuilder stringBuilder = new StringBuilder(); for (String expectedMessage : expectedMessages) { stringBuilder.append(expectedMessage).append("\n"); @@ -151,7 +198,11 @@ public class CheckerTestUtilTest extends JetLiteFixture { return stringBuilder.toString(); } - protected abstract void makeTestData(List diagnostics, List diagnosedRanges); + protected abstract void makeTestData(List diagnostics, List diagnosedRanges); + } + + private static String wrongParameters(String expected, String actual, int start, int end) { + return "Wrong parameters " + expected + " != " + actual +" at " + start + " to " + end; } private static String unexpected(String type, int actualStart, int actualEnd) { @@ -170,6 +221,18 @@ public class CheckerTestUtilTest extends JetLiteFixture { return missing(data.name, data.startOffset, data.endOffset); } + private static String asTextDiagnostic(DiagnosticData diagnosticData, String... params) { + return diagnosticData.name + "(" + StringUtil.join(params, "; ") + ")"; + } + + private static DiagnosedRange asDiagnosticRange(DiagnosticData diagnosticData, String... textDiagnostics) { + DiagnosedRange range = new DiagnosedRange(diagnosticData.startOffset); + range.setEnd(diagnosticData.endOffset); + for (String textDiagnostic : textDiagnostics) + range.addDiagnostic(textDiagnostic); + return range; + } + private static class DiagnosticData { public int index; public int rangeIndex;