[FIR] Add old FE-like diagnostic tests
This commit is contained in:
-5
@@ -1,5 +0,0 @@
|
||||
<INAPPLICABLE_INFIX_MODIFIER>: infix fun Int.foo(x: Int, y: Int) {}
|
||||
|
||||
<INAPPLICABLE_INFIX_MODIFIER>: infix fun Int.bar() {}
|
||||
|
||||
<INAPPLICABLE_INFIX_MODIFIER>: infix fun baz(x: Int, y: Int) {}
|
||||
@@ -1,10 +1,10 @@
|
||||
infix fun Int.good(x: Int) {}
|
||||
|
||||
infix fun Int.foo(x: Int, y: Int) {}
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun Int.foo(x: Int, y: Int) {}<!>
|
||||
|
||||
infix fun Int.bar() {}
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun Int.bar() {}<!>
|
||||
|
||||
infix fun baz(x: Int, y: Int) {}
|
||||
<!INAPPLICABLE_INFIX_MODIFIER!>infix fun baz(x: Int, y: Int) {}<!>
|
||||
|
||||
infix class A
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@ abstract class AbstractFirResolveTestCase : AbstractFirResolveWithSessionTestCas
|
||||
return createEnvironmentWithMockJdk(configurationKind)
|
||||
}
|
||||
|
||||
private fun doCreateAndProcessFir(ktFiles: List<KtFile>): List<FirFile> {
|
||||
|
||||
protected fun doCreateAndProcessFir(ktFiles: List<KtFile>): List<FirFile> {
|
||||
val scope = GlobalSearchScope.filesScope(project, ktFiles.mapNotNull { it.virtualFile })
|
||||
.uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(project))
|
||||
val session = createSession(environment, scope)
|
||||
@@ -48,26 +47,25 @@ abstract class AbstractFirResolveTestCase : AbstractFirResolveWithSessionTestCas
|
||||
}
|
||||
}
|
||||
|
||||
protected fun processInputFile(path: String): List<FirFile> {
|
||||
protected fun generateKtFiles(path: String): List<KtFile> {
|
||||
val file = File(path)
|
||||
|
||||
val allFiles = listOf(file) + file.parentFile.listFiles { sibling ->
|
||||
sibling.name.removePrefix(file.nameWithoutExtension).removeSuffix(file.extension).matches("\\.[0-9]+\\.".toRegex())
|
||||
}
|
||||
|
||||
val ktFiles =
|
||||
allFiles.map {
|
||||
val text = KotlinTestUtils.doLoadFile(it)
|
||||
it.name to text
|
||||
}
|
||||
.sortedBy { (_, text) ->
|
||||
KotlinTestUtils.parseDirectives(text)["analyzePriority"]?.toInt()
|
||||
}
|
||||
.map { (name, text) ->
|
||||
KotlinTestUtils.createFile(name, text, project)
|
||||
}
|
||||
return allFiles.map {
|
||||
val text = KotlinTestUtils.doLoadFile(it)
|
||||
it.name to text
|
||||
}.sortedBy { (_, text) ->
|
||||
KotlinTestUtils.parseDirectives(text)["analyzePriority"]?.toInt()
|
||||
}.map { (name, text) ->
|
||||
KotlinTestUtils.createFile(name, text, project)
|
||||
}
|
||||
}
|
||||
|
||||
return doCreateAndProcessFir(ktFiles)
|
||||
protected fun processInputFile(path: String): List<FirFile> {
|
||||
return doCreateAndProcessFir(generateKtFiles(path))
|
||||
}
|
||||
|
||||
open fun doTest(path: String) {
|
||||
|
||||
+161
-17
@@ -5,40 +5,184 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.checkers.DiagnosedRange
|
||||
import org.jetbrains.kotlin.checkers.DiagnosticDiffCallbacks
|
||||
import org.jetbrains.kotlin.checkers.TestCheckerUtil
|
||||
import org.jetbrains.kotlin.checkers.diagnostics.ActualDiagnostic
|
||||
import org.jetbrains.kotlin.checkers.diagnostics.PositionalTextDiagnostic
|
||||
import org.jetbrains.kotlin.checkers.diagnostics.TextDiagnostic
|
||||
import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil
|
||||
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.ParallelDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.SimpleDiagnosticsCollector
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.collectors.components.DeclarationCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestFiles
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirResolveWithDiagnosticsTestCase : AbstractFirResolveTestCase() {
|
||||
override fun doTest(path: String) {
|
||||
val firFiles = processInputFile(path)
|
||||
val file = File(path)
|
||||
val expectedText = KotlinTestUtils.doLoadFile(file)
|
||||
val testFiles = createTestFiles(file, expectedText)
|
||||
val firFiles = doCreateAndProcessFir(testFiles.mapNotNull { it.ktFile })
|
||||
checkFir(path, firFiles)
|
||||
checkDiagnostics(path, firFiles)
|
||||
checkDiagnostics(file, testFiles, firFiles)
|
||||
}
|
||||
|
||||
private fun checkDiagnostics(path: String, firFiles: List<FirFile>) {
|
||||
private fun createCollector(): AbstractDiagnosticCollector {
|
||||
// val collector = SimpleDiagnosticsCollector()
|
||||
val collector = ParallelDiagnosticsCollector(4)
|
||||
collector.initializeComponents(DeclarationCheckersDiagnosticComponent(collector))
|
||||
val diagnostics = mutableListOf<ConeDiagnostic>()
|
||||
for (file in firFiles) {
|
||||
diagnostics += collector.collectDiagnostics(file)
|
||||
return collector
|
||||
}
|
||||
|
||||
private fun checkDiagnostics(file: File, testFiles: List<TestFile>, firFiles: List<FirFile>) {
|
||||
val collector = createCollector()
|
||||
val actualText = StringBuilder()
|
||||
for ((testFile, firFile) in testFiles zip firFiles) {
|
||||
val coneDiagnostics = collector.collectDiagnostics(firFile)
|
||||
testFile.getActualText(coneDiagnostics, actualText)
|
||||
}
|
||||
val expectedPath = path.replace(".kt", ".diagnostics.txt")
|
||||
val expectedFile = File(expectedPath)
|
||||
if (diagnostics.isEmpty()) {
|
||||
assertFalse("There is no diagnostics but expected file exists", expectedFile.exists())
|
||||
return
|
||||
KotlinTestUtils.assertEqualsToFile(file, actualText.toString())
|
||||
}
|
||||
|
||||
private fun createTestFiles(file: File, expectedText: String?): List<TestFile> {
|
||||
return TestFiles.createTestFiles(file.name, expectedText, object : TestFiles.TestFileFactory<Nothing?, TestFile> {
|
||||
override fun createFile(module: Nothing?, fileName: String, text: String, directives: MutableMap<String, String>): TestFile {
|
||||
return TestFile(fileName, text, directives)
|
||||
}
|
||||
|
||||
override fun createModule(name: String, dependencies: MutableList<String>, friends: MutableList<String>): Nothing? {
|
||||
return null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private inner class TestFile(
|
||||
fileName: String,
|
||||
textWithMarkers: String,
|
||||
val directives: Map<String, String>
|
||||
) {
|
||||
private val diagnosedRanges: MutableList<DiagnosedRange> = mutableListOf()
|
||||
private val diagnosedRangesToDiagnosticNames: MutableMap<IntRange, MutableSet<String>> = mutableMapOf()
|
||||
val ktFile: KtFile? by lazy {
|
||||
if (fileName.endsWith(".java")) {
|
||||
null
|
||||
} else {
|
||||
TestCheckerUtil.createCheckAndReturnPsiFile(fileName, clearText, project)
|
||||
}
|
||||
}
|
||||
val actualDiagnostics: MutableList<ActualDiagnostic> = mutableListOf()
|
||||
val clearText: String
|
||||
val expectedText: String
|
||||
|
||||
init {
|
||||
if (fileName.endsWith(".java")) {
|
||||
clearText = textWithMarkers
|
||||
expectedText = clearText
|
||||
} else {
|
||||
expectedText = textWithMarkers
|
||||
clearText = CheckerTestUtil.parseDiagnosedRanges(addExtracts(expectedText), diagnosedRanges, diagnosedRangesToDiagnosticNames)
|
||||
}
|
||||
}
|
||||
|
||||
val actual = diagnostics.joinToString("\n\n") {
|
||||
val text = (it.source as FirPsiSourceElement).psi.text
|
||||
"<${it.diagnostic.factory.name}>: $text"
|
||||
fun addExtracts(text: String): String {
|
||||
// TODO
|
||||
return text
|
||||
}
|
||||
KotlinTestUtils.assertEqualsToFile(expectedFile, actual)
|
||||
|
||||
fun getActualText(
|
||||
coneDiagnostics: Iterable<ConeDiagnostic>,
|
||||
actualText: StringBuilder
|
||||
): Boolean {
|
||||
val ktFile = this.ktFile
|
||||
if (ktFile == null) {
|
||||
// TODO: check java files too
|
||||
actualText.append(this.clearText)
|
||||
return true
|
||||
}
|
||||
|
||||
if (ktFile.name.endsWith("CoroutineUtil.kt") && ktFile.packageFqName == FqName("helpers")) return true
|
||||
|
||||
// TODO: report JVM signature diagnostics also for implementing modules
|
||||
|
||||
val ok = booleanArrayOf(true)
|
||||
val diagnostics = coneDiagnostics.toActualDiagnostic()
|
||||
val filteredDiagnostics = diagnostics // TODO
|
||||
|
||||
actualDiagnostics.addAll(filteredDiagnostics)
|
||||
|
||||
val uncheckedDiagnostics = mutableListOf<PositionalTextDiagnostic>()
|
||||
|
||||
val diagnosticToExpectedDiagnostic =
|
||||
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, filteredDiagnostics, object : DiagnosticDiffCallbacks {
|
||||
override fun missingDiagnostic(diagnostic: TextDiagnostic, expectedStart: Int, expectedEnd: Int) {
|
||||
val message = "Missing " + diagnostic.description + PsiDiagnosticUtils.atLocation(
|
||||
ktFile,
|
||||
TextRange(expectedStart, expectedEnd)
|
||||
)
|
||||
System.err.println(message)
|
||||
ok[0] = false
|
||||
}
|
||||
|
||||
override fun wrongParametersDiagnostic(
|
||||
expectedDiagnostic: TextDiagnostic,
|
||||
actualDiagnostic: TextDiagnostic,
|
||||
start: Int,
|
||||
end: Int
|
||||
) {
|
||||
val message = "Parameters of diagnostic not equal at position " +
|
||||
PsiDiagnosticUtils.atLocation(ktFile, TextRange(start, end)) +
|
||||
". Expected: ${expectedDiagnostic.asString()}, actual: $actualDiagnostic"
|
||||
System.err.println(message)
|
||||
ok[0] = false
|
||||
}
|
||||
|
||||
override fun unexpectedDiagnostic(diagnostic: TextDiagnostic, actualStart: Int, actualEnd: Int) {
|
||||
val message = "Unexpected ${diagnostic.description}${PsiDiagnosticUtils.atLocation(
|
||||
ktFile,
|
||||
TextRange(actualStart, actualEnd)
|
||||
)}"
|
||||
System.err.println(message)
|
||||
ok[0] = false
|
||||
}
|
||||
|
||||
fun updateUncheckedDiagnostics(diagnostic: TextDiagnostic, start: Int, end: Int) {
|
||||
uncheckedDiagnostics.add(PositionalTextDiagnostic(diagnostic, start, end))
|
||||
}
|
||||
})
|
||||
|
||||
actualText.append(
|
||||
CheckerTestUtil.addDiagnosticMarkersToText(
|
||||
ktFile,
|
||||
filteredDiagnostics,
|
||||
diagnosticToExpectedDiagnostic,
|
||||
{ file -> file.text },
|
||||
uncheckedDiagnostics,
|
||||
false,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
stripExtras(actualText)
|
||||
|
||||
return ok[0]
|
||||
}
|
||||
|
||||
private fun stripExtras(text: StringBuilder): StringBuilder {
|
||||
// TODO
|
||||
return text
|
||||
}
|
||||
}
|
||||
|
||||
private fun Iterable<ConeDiagnostic>.toActualDiagnostic(): Collection<ActualDiagnostic> {
|
||||
return map { ActualDiagnostic(it.diagnostic, null, true) }
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ object CheckerTestUtil {
|
||||
languageVersionSettings: LanguageVersionSettings?,
|
||||
dataFlowValueFactory: DataFlowValueFactory?,
|
||||
moduleDescriptor: ModuleDescriptorImpl?,
|
||||
diagnosedRanges: MutableMap<IntRange, MutableSet<String>>?
|
||||
diagnosedRanges: Map<IntRange, MutableSet<String>>?
|
||||
): List<ActualDiagnostic> {
|
||||
val debugAnnotations = mutableListOf<ActualDiagnostic>()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user