289 lines
12 KiB
Java
289 lines
12 KiB
Java
/*
|
|
* Copyright 2010-2015 JetBrains s.r.o.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package org.jetbrains.kotlin.checkers;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
|
import com.intellij.openapi.project.Project;
|
|
import com.intellij.openapi.util.text.StringUtil;
|
|
import com.intellij.psi.PsiElement;
|
|
import com.intellij.psi.PsiElementVisitor;
|
|
import com.intellij.psi.PsiFile;
|
|
import com.intellij.testFramework.LightVirtualFile;
|
|
import com.intellij.util.containers.ContainerUtil;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.kotlin.checkers.CheckerTestUtil.DiagnosedRange;
|
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
|
import org.jetbrains.kotlin.psi.KtFile;
|
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
import org.jetbrains.kotlin.resolve.lazy.JvmResolveUtil;
|
|
import org.jetbrains.kotlin.test.ConfigurationKind;
|
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
|
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment;
|
|
|
|
import java.io.File;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
public class CheckerTestUtilTest extends KotlinTestWithEnvironment {
|
|
@NotNull
|
|
private static String getTestDataPath() {
|
|
return KotlinTestUtils.getTestDataPathBase() + "/diagnostics/checkerTestUtil";
|
|
}
|
|
|
|
@Override
|
|
protected KotlinCoreEnvironment createEnvironment() {
|
|
return createEnvironmentWithMockJdk(ConfigurationKind.ALL);
|
|
}
|
|
|
|
protected void doTest(TheTest theTest) throws Exception {
|
|
String text = KotlinTestUtils.doLoadFile(getTestDataPath(), "test.kt");
|
|
theTest.test(createCheckAndReturnPsiFile("test.kt", text, getProject()));
|
|
}
|
|
|
|
@NotNull
|
|
public static KtFile createCheckAndReturnPsiFile(@NotNull String fileName, @NotNull String text, @NotNull Project project) {
|
|
KtFile myFile = KotlinTestUtils.createFile(fileName, text, project);
|
|
ensureParsed(myFile);
|
|
assertEquals("light virtual file text mismatch", text, ((LightVirtualFile) myFile.getVirtualFile()).getContent().toString());
|
|
assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile()));
|
|
//noinspection ConstantConditions
|
|
assertEquals("doc text mismatch", text, myFile.getViewProvider().getDocument().getText());
|
|
assertEquals("psi text mismatch", text, myFile.getText());
|
|
return myFile;
|
|
}
|
|
|
|
private static void ensureParsed(PsiFile file) {
|
|
file.accept(new PsiElementVisitor() {
|
|
@Override
|
|
public void visitElement(@NotNull PsiElement element) {
|
|
element.acceptChildren(this);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testEquals() throws Exception {
|
|
doTest(new TheTest() {
|
|
@Override
|
|
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testMissing() throws Exception {
|
|
final DiagnosticData typeMismatch1 = diagnostics.get(1);
|
|
doTest(new TheTest(missing(typeMismatch1)) {
|
|
@Override
|
|
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
|
|
diagnostics.remove(typeMismatch1.index);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testUnexpected() throws Exception {
|
|
final DiagnosticData typeMismatch1 = diagnostics.get(1);
|
|
doTest(new TheTest(unexpected(typeMismatch1)) {
|
|
@Override
|
|
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
|
|
diagnosedRanges.remove(typeMismatch1.index);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testBoth() throws Exception {
|
|
final DiagnosticData typeMismatch1 = diagnostics.get(1);
|
|
final DiagnosticData unresolvedReference = diagnostics.get(6);
|
|
doTest(new TheTest(unexpected(typeMismatch1), missing(unresolvedReference)) {
|
|
@Override
|
|
protected void makeTestData(List<Diagnostic> diagnostics, List<DiagnosedRange> diagnosedRanges) {
|
|
diagnosedRanges.remove(typeMismatch1.rangeIndex);
|
|
diagnostics.remove(unresolvedReference.index);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void testMissingInTheMiddle() throws Exception {
|
|
final DiagnosticData noneApplicable = diagnostics.get(4);
|
|
final DiagnosticData typeMismatch3 = diagnostics.get(5);
|
|
doTest(new TheTest(unexpected(noneApplicable), missing(typeMismatch3)) {
|
|
@Override
|
|
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 {
|
|
AbstractDiagnosticsTest test = new AbstractDiagnosticsTest() {
|
|
{setUp();}
|
|
};
|
|
test.doTest(getTestDataPath() + File.separatorChar + "test_with_diagnostic.kt");
|
|
}
|
|
|
|
private static abstract class TheTest {
|
|
private final String[] expected;
|
|
|
|
protected TheTest(String... expectedMessages) {
|
|
this.expected = expectedMessages;
|
|
}
|
|
|
|
public void test(@NotNull PsiFile psiFile) {
|
|
BindingContext bindingContext = JvmResolveUtil.analyzeOneFileWithJavaIntegration(
|
|
(KtFile) psiFile)
|
|
.getBindingContext();
|
|
|
|
String expectedText = CheckerTestUtil.addDiagnosticMarkersToText(psiFile, CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null)).toString();
|
|
|
|
List<DiagnosedRange> diagnosedRanges = Lists.newArrayList();
|
|
CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
|
|
for (DiagnosedRange diagnosedRange : diagnosedRanges) {
|
|
diagnosedRange.setFile(psiFile);
|
|
}
|
|
|
|
List<Diagnostic> diagnostics = CheckerTestUtil.getDiagnosticsIncludingSyntaxErrors(bindingContext, psiFile, false, null);
|
|
Collections.sort(diagnostics, CheckerTestUtil.DIAGNOSTIC_COMPARATOR);
|
|
|
|
makeTestData(diagnostics, diagnosedRanges);
|
|
|
|
List<String> expectedMessages = Lists.newArrayList(expected);
|
|
final List<String> actualMessages = Lists.newArrayList();
|
|
|
|
CheckerTestUtil.diagnosticsDiff(ContainerUtil.<Diagnostic, CheckerTestUtil.TextDiagnostic>newHashMap(),
|
|
diagnosedRanges, diagnostics, new CheckerTestUtil.DiagnosticDiffCallbacks() {
|
|
|
|
@Override
|
|
public void missingDiagnostic(CheckerTestUtil.TextDiagnostic diagnostic, int expectedStart, int expectedEnd) {
|
|
actualMessages.add(missing(diagnostic.getName(), expectedStart, expectedEnd));
|
|
}
|
|
|
|
@Override
|
|
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 static String listToString(List<String> expectedMessages) {
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
for (String expectedMessage : expectedMessages) {
|
|
stringBuilder.append(expectedMessage).append("\n");
|
|
}
|
|
return stringBuilder.toString();
|
|
}
|
|
|
|
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) {
|
|
return "Unexpected " + type + " at " + actualStart + " to " + actualEnd;
|
|
}
|
|
|
|
private static String missing(String type, int expectedStart, int expectedEnd) {
|
|
return "Missing " + type + " at " + expectedStart + " to " + expectedEnd;
|
|
}
|
|
|
|
private static String unexpected(DiagnosticData data) {
|
|
return unexpected(data.name, data.startOffset, data.endOffset);
|
|
}
|
|
|
|
private static String missing(DiagnosticData data) {
|
|
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;
|
|
public String name;
|
|
public int startOffset;
|
|
public int endOffset;
|
|
|
|
private DiagnosticData(int index, int rangeIndex, String name, int startOffset, int endOffset) {
|
|
this.index = index;
|
|
this.rangeIndex = rangeIndex;
|
|
this.name = name;
|
|
this.startOffset = startOffset;
|
|
this.endOffset = endOffset;
|
|
}
|
|
}
|
|
|
|
private final List<DiagnosticData> diagnostics = Lists.newArrayList(
|
|
new DiagnosticData(0, 0, "UNUSED_PARAMETER", 8, 9),
|
|
new DiagnosticData(1, 1, "CONSTANT_EXPECTED_TYPE_MISMATCH", 56, 57),
|
|
new DiagnosticData(2, 2, "UNUSED_VARIABLE", 67, 68),
|
|
new DiagnosticData(3, 3, "TYPE_MISMATCH", 98, 99),
|
|
new DiagnosticData(4, 4, "NONE_APPLICABLE", 120, 121),
|
|
new DiagnosticData(5, 5, "TYPE_MISMATCH", 159, 167),
|
|
new DiagnosticData(6, 6, "UNRESOLVED_REFERENCE", 164, 166),
|
|
new DiagnosticData(7, 6, "TOO_MANY_ARGUMENTS", 164, 166)
|
|
);
|
|
}
|