!RENDER_DIAGNOSTICS_FULL_TEXT directive
Compares diagnostics rendered as text with corresponding .diag.txt file
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.common.messages;
|
package org.jetbrains.kotlin.cli.common.messages;
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.utils.fileUtils.FileUtilsKt;
|
import org.jetbrains.kotlin.utils.fileUtils.FileUtilsKt;
|
||||||
@@ -69,6 +70,23 @@ public interface MessageRenderer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MessageRenderer SYSTEM_INDEPENDENT_RELATIVE_PATHS = new PlainTextMessageRenderer() {
|
||||||
|
private final File cwd = new File(".").getAbsoluteFile();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected String getPath(@NotNull CompilerMessageLocation location) {
|
||||||
|
return FileUtil.toSystemIndependentName(
|
||||||
|
FileUtilsKt.descendantRelativeTo(new File(location.getPath()), cwd).getPath()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SystemIndependentRelativePath";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MessageRenderer GRADLE_STYLE = new GradleStyleMessageRenderer();
|
MessageRenderer GRADLE_STYLE = new GradleStyleMessageRenderer();
|
||||||
|
|
||||||
String renderPreamble();
|
String renderPreamble();
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/inlineCycle.kt:8:5: error: the 'inlineFun2' invocation is a part of inline cycle
|
||||||
|
inlineFun2(p)
|
||||||
|
^
|
||||||
|
/inlineCycle.kt:13:5: error: the 'inlineFun1' invocation is a part of inline cycle
|
||||||
|
inlineFun1(p)
|
||||||
|
^
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// !RENDER_DIAGNOSTICS_FULL_TEXT
|
||||||
|
|
||||||
inline fun inlineFun1(p: () -> Unit) {
|
inline fun inlineFun1(p: () -> Unit) {
|
||||||
p()
|
p()
|
||||||
<!INLINE_CALL_CYCLE, INLINE_CALL_CYCLE!>inlineFun2(p)<!>
|
<!INLINE_CALL_CYCLE, INLINE_CALL_CYCLE!>inlineFun2(p)<!>
|
||||||
|
|||||||
+44
-1
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.TestsCompilerError
|
|||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
|
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.*
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
@@ -61,7 +62,9 @@ import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE
|
|||||||
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE_ALL
|
import org.jetbrains.kotlin.test.util.RecursiveDescriptorComparator.RECURSIVE_ALL
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
import org.jetbrains.kotlin.utils.keysToMap
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.PrintStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.function.Predicate
|
import java.util.function.Predicate
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
@@ -169,6 +172,15 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
// main checks
|
// main checks
|
||||||
var ok = true
|
var ok = true
|
||||||
|
|
||||||
|
val diagnosticsFullTextByteArrayStream = ByteArrayOutputStream()
|
||||||
|
val diagnosticsFullTextPrintStream = PrintStream(diagnosticsFullTextByteArrayStream)
|
||||||
|
var shouldCheckDiagnosticsFullText = false
|
||||||
|
val diagnosticsFullTextCollector =
|
||||||
|
GroupingMessageCollector(
|
||||||
|
PrintingMessageCollector(diagnosticsFullTextPrintStream, MessageRenderer.SYSTEM_INDEPENDENT_RELATIVE_PATHS, true),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
val actualText = StringBuilder()
|
val actualText = StringBuilder()
|
||||||
for (testFile in files) {
|
for (testFile in files) {
|
||||||
val module = testFile.module
|
val module = testFile.module
|
||||||
@@ -183,14 +195,20 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
}
|
}
|
||||||
val moduleDescriptor = modules[module]!!
|
val moduleDescriptor = modules[module]!!
|
||||||
|
|
||||||
|
val moduleBindingContext = moduleBindings[module]!!
|
||||||
ok = ok and testFile.getActualText(
|
ok = ok and testFile.getActualText(
|
||||||
moduleBindings[module]!!,
|
moduleBindingContext,
|
||||||
implementingModulesBindings,
|
implementingModulesBindings,
|
||||||
actualText,
|
actualText,
|
||||||
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule,
|
shouldSkipJvmSignatureDiagnostics(groupedByModule) || isCommonModule,
|
||||||
languageVersionSettingsByModule[module]!!,
|
languageVersionSettingsByModule[module]!!,
|
||||||
moduleDescriptor
|
moduleDescriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (testFile.renderDiagnosticsFullText) {
|
||||||
|
shouldCheckDiagnosticsFullText = true
|
||||||
|
AnalyzerWithCompilerReport.reportDiagnostics(moduleBindingContext.diagnostics, diagnosticsFullTextCollector)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var exceptionFromDynamicCallDescriptorsValidation: Throwable? = null
|
var exceptionFromDynamicCallDescriptorsValidation: Throwable? = null
|
||||||
@@ -201,6 +219,15 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
exceptionFromDynamicCallDescriptorsValidation = e
|
exceptionFromDynamicCallDescriptorsValidation = e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldCheckDiagnosticsFullText) {
|
||||||
|
diagnosticsFullTextCollector.flush()
|
||||||
|
diagnosticsFullTextPrintStream.flush()
|
||||||
|
KotlinTestUtils.assertEqualsToFile(
|
||||||
|
File(FileUtil.getNameWithoutExtension(testDataFile.absolutePath) + ".diag.txt"),
|
||||||
|
String(diagnosticsFullTextByteArrayStream.toByteArray())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
KotlinTestUtils.assertEqualsToFile(getExpectedDiagnosticsFile(testDataFile), actualText.cleanupInferenceDiagnostics()) { s ->
|
KotlinTestUtils.assertEqualsToFile(getExpectedDiagnosticsFile(testDataFile), actualText.cleanupInferenceDiagnostics()) { s ->
|
||||||
s.replace("COROUTINES_PACKAGE", coroutinesPackage)
|
s.replace("COROUTINES_PACKAGE", coroutinesPackage)
|
||||||
}
|
}
|
||||||
@@ -218,6 +245,22 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
checkOriginalAndFirTestdataIdentity(testDataFile)
|
checkOriginalAndFirTestdataIdentity(testDataFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DiagnosticsFullTextMessageCollector : MessageCollector {
|
||||||
|
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasErrors(): Boolean {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkOriginalAndFirTestdataIdentity(testDataFile: File) {
|
private fun checkOriginalAndFirTestdataIdentity(testDataFile: File) {
|
||||||
val firTestDataFile = File(testDataFile.absolutePath.replace(".kt", ".fir.kt"))
|
val firTestDataFile = File(testDataFile.absolutePath.replace(".kt", ".fir.kt"))
|
||||||
if (!firTestDataFile.exists()) return
|
if (!firTestDataFile.exists()) return
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
val withNewInferenceDirective: Boolean
|
val withNewInferenceDirective: Boolean
|
||||||
val newInferenceEnabled: Boolean
|
val newInferenceEnabled: Boolean
|
||||||
val renderDiagnosticMessages: Boolean
|
val renderDiagnosticMessages: Boolean
|
||||||
|
val renderDiagnosticsFullText: Boolean
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives, declareCheckType)
|
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives, declareCheckType)
|
||||||
@@ -166,8 +167,8 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
this.declareFlexibleType = EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE in directives
|
this.declareFlexibleType = EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE in directives
|
||||||
this.markDynamicCalls = MARK_DYNAMIC_CALLS_DIRECTIVE in directives
|
this.markDynamicCalls = MARK_DYNAMIC_CALLS_DIRECTIVE in directives
|
||||||
this.withNewInferenceDirective = WITH_NEW_INFERENCE_DIRECTIVE in directives
|
this.withNewInferenceDirective = WITH_NEW_INFERENCE_DIRECTIVE in directives
|
||||||
this.newInferenceEnabled = customLanguageVersionSettings?.supportsFeature(LanguageFeature.NewInference) ?:
|
this.newInferenceEnabled =
|
||||||
shouldUseNewInferenceForTests()
|
customLanguageVersionSettings?.supportsFeature(LanguageFeature.NewInference) ?: shouldUseNewInferenceForTests()
|
||||||
if (fileName.endsWith(".java")) {
|
if (fileName.endsWith(".java")) {
|
||||||
// TODO: check there are no syntax errors in .java sources
|
// TODO: check there are no syntax errors in .java sources
|
||||||
this.createKtFile = lazyOf(null)
|
this.createKtFile = lazyOf(null)
|
||||||
@@ -175,10 +176,12 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
this.expectedText = this.clearText
|
this.expectedText = this.clearText
|
||||||
} else {
|
} else {
|
||||||
this.expectedText = textWithMarkers
|
this.expectedText = textWithMarkers
|
||||||
this.clearText = CheckerTestUtil.parseDiagnosedRanges(addExtras(expectedText), diagnosedRanges, diagnosedRangesToDiagnosticNames)
|
this.clearText =
|
||||||
|
CheckerTestUtil.parseDiagnosedRanges(addExtras(expectedText), diagnosedRanges, diagnosedRangesToDiagnosticNames)
|
||||||
this.createKtFile = lazy { TestCheckerUtil.createCheckAndReturnPsiFile(fileName, clearText, project) }
|
this.createKtFile = lazy { TestCheckerUtil.createCheckAndReturnPsiFile(fileName, clearText, project) }
|
||||||
}
|
}
|
||||||
this.renderDiagnosticMessages = RENDER_DIAGNOSTICS_MESSAGES in directives
|
this.renderDiagnosticMessages = RENDER_DIAGNOSTICS_MESSAGES in directives
|
||||||
|
this.renderDiagnosticsFullText = RENDER_DIAGNOSTICS_FULL_TEXT in directives
|
||||||
}
|
}
|
||||||
|
|
||||||
val ktFile: KtFile? by createKtFile
|
val ktFile: KtFile? by createKtFile
|
||||||
@@ -210,14 +213,14 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
|
|
||||||
private fun addImports(text: String, imports: String): String {
|
private fun addImports(text: String, imports: String): String {
|
||||||
var result = text
|
var result = text
|
||||||
val pattern = Pattern.compile("^package [\\.\\w\\d]*\n", Pattern.MULTILINE)
|
val pattern = Pattern.compile("^package [.\\w\\d]*\n", Pattern.MULTILINE)
|
||||||
val matcher = pattern.matcher(result)
|
val matcher = pattern.matcher(result)
|
||||||
if (matcher.find()) {
|
result = if (matcher.find()) {
|
||||||
// add imports after the package directive
|
// add imports after the package directive
|
||||||
result = result.substring(0, matcher.end()) + imports + result.substring(matcher.end())
|
result.substring(0, matcher.end()) + imports + result.substring(matcher.end())
|
||||||
} else {
|
} else {
|
||||||
// add imports at the beginning
|
// add imports at the beginning
|
||||||
result = imports + result
|
imports + result
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -264,10 +267,9 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
moduleDescriptor,
|
moduleDescriptor,
|
||||||
this.diagnosedRangesToDiagnosticNames
|
this.diagnosedRangesToDiagnosticNames
|
||||||
)
|
)
|
||||||
val filteredDiagnostics = ContainerUtil.filter(
|
val filteredDiagnostics = ContainerUtil.filter(diagnostics + jvmSignatureDiagnostics) {
|
||||||
diagnostics + jvmSignatureDiagnostics,
|
whatDiagnosticsToConsider.value(it.diagnostic)
|
||||||
{ whatDiagnosticsToConsider.value(it.diagnostic) }
|
}
|
||||||
)
|
|
||||||
|
|
||||||
actualDiagnostics.addAll(filteredDiagnostics)
|
actualDiagnostics.addAll(filteredDiagnostics)
|
||||||
|
|
||||||
@@ -320,11 +322,9 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
|
|
||||||
fun updateUncheckedDiagnostics(diagnostic: TextDiagnostic, start: Int, end: Int) {
|
fun updateUncheckedDiagnostics(diagnostic: TextDiagnostic, start: Int, end: Int) {
|
||||||
diagnostic.enhanceInferenceCompatibility(invertedInferenceCompatibilityOfTest)
|
diagnostic.enhanceInferenceCompatibility(invertedInferenceCompatibilityOfTest)
|
||||||
uncheckedDiagnostics.add(PositionalTextDiagnostic(diagnostic, start, end
|
uncheckedDiagnostics.add(PositionalTextDiagnostic(diagnostic, start, end))
|
||||||
)
|
}
|
||||||
)
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
actualText.append(
|
actualText.append(
|
||||||
CheckerTestUtil.addDiagnosticMarkersToText(
|
CheckerTestUtil.addDiagnosticMarkersToText(
|
||||||
@@ -370,7 +370,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
companion object {
|
companion object {
|
||||||
private const val HELPERS_PATH = "./compiler/testData/diagnostics/helpers"
|
private const val HELPERS_PATH = "./compiler/testData/diagnostics/helpers"
|
||||||
val DIAGNOSTICS_DIRECTIVE = "DIAGNOSTICS"
|
val DIAGNOSTICS_DIRECTIVE = "DIAGNOSTICS"
|
||||||
val DIAGNOSTICS_PATTERN: Pattern = Pattern.compile("([\\+\\-!])(\\w+)\\s*")
|
val DIAGNOSTICS_PATTERN: Pattern = Pattern.compile("([+\\-!])(\\w+)\\s*")
|
||||||
val DIAGNOSTICS_TO_INCLUDE_ANYWAY: Set<DiagnosticFactory<*>> = setOf(
|
val DIAGNOSTICS_TO_INCLUDE_ANYWAY: Set<DiagnosticFactory<*>> = setOf(
|
||||||
Errors.UNRESOLVED_REFERENCE,
|
Errors.UNRESOLVED_REFERENCE,
|
||||||
Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER,
|
||||||
@@ -406,6 +406,8 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
|
|
||||||
val RENDER_DIAGNOSTICS_MESSAGES = "RENDER_DIAGNOSTICS_MESSAGES"
|
val RENDER_DIAGNOSTICS_MESSAGES = "RENDER_DIAGNOSTICS_MESSAGES"
|
||||||
|
|
||||||
|
val RENDER_DIAGNOSTICS_FULL_TEXT = "RENDER_DIAGNOSTICS_FULL_TEXT"
|
||||||
|
|
||||||
val DIAGNOSTIC_IN_TESTDATA_PATTERN = Regex("<!>|<!(.*?(\\(\".*?\"\\)|\\(\\))??)+(?<!<)!>")
|
val DIAGNOSTIC_IN_TESTDATA_PATTERN = Regex("<!>|<!(.*?(\\(\".*?\"\\)|\\(\\))??)+(?<!<)!>")
|
||||||
|
|
||||||
fun parseDiagnosticFilterDirective(
|
fun parseDiagnosticFilterDirective(
|
||||||
@@ -435,12 +437,12 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
Assert.fail(
|
Assert.fail(
|
||||||
"Wrong syntax in the '// !$DIAGNOSTICS_DIRECTIVE: ...' directive:\n" +
|
"Wrong syntax in the '// !$DIAGNOSTICS_DIRECTIVE: ...' directive:\n" +
|
||||||
"found: '$directives'\n" +
|
"found: '$directives'\n" +
|
||||||
"Must be '([+-!]DIAGNOSTIC_FACTORY_NAME|ERROR|WARNING|INFO)+'\n" +
|
"Must be '([+-!]DIAGNOSTIC_FACTORY_NAME|ERROR|WARNING|INFO)+'\n" +
|
||||||
"where '+' means 'include'\n" +
|
"where '+' means 'include'\n" +
|
||||||
" '-' means 'exclude'\n" +
|
" '-' means 'exclude'\n" +
|
||||||
" '!' means 'exclude everything but this'\n" +
|
" '!' means 'exclude everything but this'\n" +
|
||||||
"directives are applied in the order of appearance, i.e. !FOO +BAR means include only FOO and BAR"
|
"directives are applied in the order of appearance, i.e. !FOO +BAR means include only FOO and BAR"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,7 +463,7 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava<TestModule, Tes
|
|||||||
if (!first) {
|
if (!first) {
|
||||||
Assert.fail(
|
Assert.fail(
|
||||||
"'$operation$name' appears in a position rather than the first one, " +
|
"'$operation$name' appears in a position rather than the first one, " +
|
||||||
"which effectively cancels all the previous filters in this directive"
|
"which effectively cancels all the previous filters in this directive"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
condition = newCondition
|
condition = newCondition
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import org.jetbrains.kotlin.types.AbstractTypeBindingTest
|
|||||||
import org.jetbrains.kotlin.visualizer.fir.AbstractFirVisualizer
|
import org.jetbrains.kotlin.visualizer.fir.AbstractFirVisualizer
|
||||||
import org.jetbrains.kotlin.visualizer.psi.AbstractPsiVisualizer
|
import org.jetbrains.kotlin.visualizer.psi.AbstractPsiVisualizer
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main() {
|
||||||
System.setProperty("java.awt.headless", "true")
|
System.setProperty("java.awt.headless", "true")
|
||||||
|
|
||||||
val excludedFirTestdataPattern = "^(.+)\\.fir\\.kts?\$"
|
val excludedFirTestdataPattern = "^(.+)\\.fir\\.kts?\$"
|
||||||
@@ -127,11 +127,11 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractDiagnosticsTestWithOldJvmBackend> {
|
testClass<AbstractDiagnosticsTestWithOldJvmBackend> {
|
||||||
model("diagnostics/testsWithJvmBackend")
|
model("diagnostics/testsWithJvmBackend", targetBackend = TargetBackend.JVM)
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractDiagnosticsTestWithJvmIrBackend> {
|
testClass<AbstractDiagnosticsTestWithJvmIrBackend> {
|
||||||
model("diagnostics/testsWithJvmBackend")
|
model("diagnostics/testsWithJvmBackend", targetBackend = TargetBackend.JVM_IR)
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractMultiPlatformIntegrationTest> {
|
testClass<AbstractMultiPlatformIntegrationTest> {
|
||||||
|
|||||||
Reference in New Issue
Block a user