Add support for check diagnostic parameters in test.

This commit is contained in:
Stanislav Erokhin
2014-09-09 15:54:32 +04:00
parent 5a192f58ea
commit caf44969a4
6 changed files with 630 additions and 60 deletions
@@ -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("(<!\\w+(,\\s*\\w+)*!>)|(<!>)");
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("(<!"+
INDIVIDUAL_DIAGNOSTIC +"(,\\s*"+
INDIVIDUAL_DIAGNOSTIC +")*!>)|(<!>)");
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<Diagnostic> getDiagnosticsIncludingSyntaxErrors(BindingContext bindingContext, final PsiElement root) {
ArrayList<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
List<Diagnostic> diagnostics = new ArrayList<Diagnostic>();
diagnostics.addAll(Collections2.filter(bindingContext.getDiagnostics().all(),
new Predicate<Diagnostic>() {
@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<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic,
List<DiagnosedRange> expected,
Collection<Diagnostic> actual,
DiagnosticDiffCallbacks callbacks
@@ -164,23 +181,7 @@ public class CheckerTestUtil {
currentActual = safeAdvance(actualDiagnostics);
}
else {
assert expectedStart == actualStart && expectedEnd == actualEnd;
Multiset<String> actualDiagnosticTypes = currentActual.getDiagnosticTypeStrings();
Multiset<String> expectedDiagnosticTypes = currentExpected.getDiagnostics();
if (!actualDiagnosticTypes.equals(expectedDiagnosticTypes)) {
Multiset<String> notInActualTypes = HashMultiset.create(expectedDiagnosticTypes);
Multisets.removeOccurrences(notInActualTypes, actualDiagnosticTypes);
Multiset<String> 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<Diagnostic, TextDiagnostic> diagnosticToInput
) {
int expectedStart = currentExpected.getStart();
int expectedEnd = currentExpected.getEnd();
int actualStart = currentActual.getStart();
int actualEnd = currentActual.getEnd();
assert expectedStart == actualStart && expectedEnd == actualEnd;
Map<Diagnostic, TextDiagnostic> actualDiagnostics = currentActual.getTextDiagnosticsMap();
List<TextDiagnostic> 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<Diagnostic> actual) {
if (actual.isEmpty()) return;
PsiFile file = actual.iterator().next().getPsiElement().getContainingFile();
@@ -209,14 +265,14 @@ public class CheckerTestUtil {
for (Diagnostic diagnostic : actual) {
List<TextRange> 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<Diagnostic> diagnostics) {
return addDiagnosticMarkersToText(psiFile, diagnostics, new Function<PsiFile, String>() {
public static StringBuffer addDiagnosticMarkersToText(@NotNull PsiFile psiFile, @NotNull Collection<Diagnostic> diagnostics) {
return addDiagnosticMarkersToText(psiFile, diagnostics, Collections.<Diagnostic, TextDiagnostic>emptyMap(), new Function<PsiFile, String>() {
@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<Diagnostic> diagnostics,
@NotNull Map<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic,
@NotNull Function<PsiFile, String> 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<Diagnostic, TextDiagnostic> diagnosticToExpectedDiagnostic
) {
result.append("<!");
for (Iterator<Diagnostic> 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<DiagnosticDescriptor>() {
@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<String> getDiagnosticTypeStrings() {
Multiset<String> actualDiagnosticTypes = HashMultiset.create();
public Map<Diagnostic, TextDiagnostic> getTextDiagnosticsMap() {
Map<Diagnostic, TextDiagnostic> diagnosticMap = new IdentityHashMap<Diagnostic, TextDiagnostic>();
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<String> parsedParameters = new SmartList<String>();
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<String> parameters = ContainerUtil.map(renderParameters, new Function<Object, String>() {
@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<String> parameters;
public TextDiagnostic(@NotNull String name, @Nullable List<String> parameters) {
this.name = name;
this.parameters = parameters;
}
@NotNull
public String getName() {
return name;
}
@Nullable
public List<String> 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<String> diagnostics = HashMultiset.create();
private final List<TextDiagnostic> 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<String> getDiagnostics() {
public List<TextDiagnostic> 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) {
@@ -0,0 +1,15 @@
fun foo(<!UNUSED_PARAMETER(IGNORE)!>u<!> : Unit) : Int = 1
fun test() : Int {
foo(<!CONSTANT_EXPECTED_TYPE_MISMATCH(IGNORE; kotlin.Unit)!>1<!>)
val <!UNUSED_VARIABLE!>a<!> : () -> Unit = {
foo(<!CONSTANT_EXPECTED_TYPE_MISMATCH(integer; IGNORE)!>1<!>)
}
return 1 <!NONE_APPLICABLE!>-<!> "1"
}
class A() {
val x : Int = <!TYPE_MISMATCH!>foo1(<!UNRESOLVED_REFERENCE, TOO_MANY_ARGUMENTS!>xx<!>)<!>
}
fun foo1() {}
@@ -0,0 +1,295 @@
DescriptorResolver@0 {
<name not found> = null
}
LazyJavaPackageFragmentProvider@1 {
packageFragments('<root>': FqName@2) = LazyJavaPackageFragment@3['<root>']
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['<root>'] {
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 {
<name not found> = ArrayList@39[1] { ResolutionCandidate@40 }
<name not found> = ArrayList@41[1] { ResolutionCandidate@40 }
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
ResolutionTaskHolder@42 {
<name not found> = ArrayList@43[1] { ResolutionCandidate@44 }
<name not found> = ArrayList@45[1] { ResolutionCandidate@44 }
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
ResolutionTaskHolder@46 {
<name not found> = ArrayList@47[1] { ResolutionCandidate@48 }
<name not found> = ArrayList@49[1] { ResolutionCandidate@48 }
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
ResolutionTaskHolder@50 {
<name not found> = ArrayList@51[8] { ResolutionCandidate@52, ResolutionCandidate@53, ResolutionCandidate@54, ... }
<name not found> = ArrayList@55[8] { ResolutionCandidate@52, ResolutionCandidate@53, ResolutionCandidate@54, ... }
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
ResolutionTaskHolder@56 {
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
ResolutionTaskHolder@57 {
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
<name not found> = EmptyList@29[empty]
}
@@ -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
}
@@ -334,24 +334,40 @@ public abstract class BaseDiagnosticsTest extends
jvmSignatureDiagnostics),
whatDiagnosticsToConsider
);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
Map<Diagnostic, CheckerTestUtil.TextDiagnostic> 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<PsiFile, String>() {
actualText.append(CheckerTestUtil.addDiagnosticMarkersToText(jetFile, diagnostics, diagnosticToExpectedDiagnostic, new Function<PsiFile, String>() {
@Override
public String fun(PsiFile file) {
return file.getText();
@@ -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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges) {
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<DiagnosedRange> 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<Diagnostic> diagnostics, List<DiagnosedRange> 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<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
List<DiagnosedRange> 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<String> expectedMessages = Lists.newArrayList(expected);
final List<String> actualMessages = Lists.newArrayList();
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
CheckerTestUtil.diagnosticsDiff(ContainerUtil.<Diagnostic, CheckerTestUtil.TextDiagnostic>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<String> expectedMessages) {
private static String listToString(List<String> 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<Diagnostic> diagnostics, List<CheckerTestUtil.DiagnosedRange> diagnosedRanges);
protected abstract void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> 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;