[FIR] update reversed testData

^KT-56543
This commit is contained in:
Dmitrii Gridin
2023-04-04 23:10:31 +02:00
committed by Space Team
parent 1c5aa6c45b
commit 6170d83301
33 changed files with 140 additions and 96 deletions
@@ -1,19 +1,15 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.frontend.fir.handlers.AbstractFirIdenticalChecker
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.services.sourceFileProvider
import org.jetbrains.kotlin.test.utils.isLLFirTestData
import java.io.File
import kotlin.test.assertEquals
/**
* `.ll.kt` test data should not be identical to its base `.fir.kt`/`.kt` test data. If a base `.fir.kt` file does not exist, the base file
@@ -39,47 +35,11 @@ class LLFirIdenticalChecker(testServices: TestServices) : AbstractFirIdenticalCh
"`${testDataFile.name}` and `${baseFile.name}` are identical. Remove `$testDataFile`."
}
} else {
assertPreprocessedTestDataAreEqual(baseFile, baseContent, testDataFile, llContent) {
assertPreprocessedTestDataAreEqual(testServices, baseFile, baseContent, testDataFile, llContent) {
"When ignoring diagnostics, the contents of `${baseFile.name}` (expected) and `${testDataFile.name}` (actual) are not" +
" identical. `.ll.kt` test data may only differ from its base `.fir.kt` or `.kt` test data in the reported" +
" diagnostics and the `LL_FIR_DIVERGENCE` directive. Update one of these test data files."
}
}
}
/**
* Asserts that [baseFile] and [llFile] have the same content after preprocessing (which removes diagnostics and other meta info). This
* prevents situations where one test data changes, but changes to the other test data are forgotten.
*
* [llContent] should have its `LL_FIR_DIVERGENCE` directive already removed.
*/
private fun assertPreprocessedTestDataAreEqual(
baseFile: File,
baseContent: String,
llFile: File,
llContent: String,
message: () -> String,
) {
val processedBaseContent = testServices.sourceFileProvider.getContentOfSourceFile(
TestFile(
baseFile.path,
baseContent,
baseFile,
startLineNumberInOriginalFile = 0,
isAdditional = false,
RegisteredDirectives.Empty,
)
)
val processedLlContent = testServices.sourceFileProvider.getContentOfSourceFile(
TestFile(
llFile.path,
llContent,
llFile,
startLineNumberInOriginalFile = 0,
isAdditional = false,
RegisteredDirectives.Empty,
)
)
assertEquals(processedBaseContent, processedLlContent, message())
}
}
@@ -18,5 +18,7 @@ abstract class AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataSpecTes
)
baseFirSpecDiagnosticTestConfigurationForIde()
useAfterAnalysisCheckers(::FirReversedSuppressor)
useMetaTestConfigurators(::ReversedDiagnosticsConfigurator)
useAfterAnalysisCheckers(::ReversedFirIdenticalChecker)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based
import java.io.File
import org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based.AbstractCompilerBasedTestForFir
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostic.compiler.based.facades.LLFirAnalyzerFacadeFactoryWithPreresolveInReversedOrder
import org.jetbrains.kotlin.test.bind
@@ -14,8 +15,13 @@ import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.WrappedException
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
import org.jetbrains.kotlin.test.frontend.fir.handlers.AbstractFirIdenticalChecker
import org.jetbrains.kotlin.test.model.AfterAnalysisChecker
import org.jetbrains.kotlin.test.services.MetaTestConfigurator
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.test.utils.firTestDataFile
import org.jetbrains.kotlin.test.utils.llFirTestDataFile
abstract class AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataTest : AbstractCompilerBasedTestForFir() {
override fun TestConfigurationBuilder.configureTest() {
@@ -24,6 +30,15 @@ abstract class AbstractLLFirPreresolvedReversedDiagnosticCompilerTestDataTest :
)
useAfterAnalysisCheckers(::FirReversedSuppressor)
useMetaTestConfigurators(::ReversedDiagnosticsConfigurator)
useAfterAnalysisCheckers(::ReversedFirIdenticalChecker)
}
}
internal class ReversedDiagnosticsConfigurator(testServices: TestServices) : MetaTestConfigurator(testServices) {
override fun transformTestDataPath(testDataFileName: String): String {
val reversedTestDataFileName = testDataFileName.replaceFirst(".", ".reversed.")
return if (File(reversedTestDataFileName).exists()) reversedTestDataFileName else testDataFileName
}
}
@@ -52,3 +67,28 @@ internal class FirReversedSuppressor(testServices: TestServices) : AfterAnalysis
val IGNORE_REVERSED_RESOLVE by directive("Temporary disables reversed resolve checks until the issue is fixed")
}
}
class ReversedFirIdenticalChecker(testServices: TestServices) : AbstractFirIdenticalChecker(testServices) {
override fun checkTestDataFile(testDataFile: File) {
if (".reversed." !in testDataFile.path) return
val originalFile = helper.getClassicFileToCompare(testDataFile).path.replace(".reversed", "").let(::File)
val baseFile = originalFile.llFirTestDataFile.takeIf(File::exists)
?: originalFile.firTestDataFile.takeIf(File::exists)
?: originalFile
val baseContent = helper.readContent(baseFile, trimLines = false)
val reversedFirContent = helper.readContent(testDataFile, trimLines = false)
if (baseContent == reversedFirContent) {
testServices.assertions.fail {
"`${testDataFile.name}` and `${baseFile.name}` are identical. Remove `$testDataFile`."
}
} else {
assertPreprocessedTestDataAreEqual(testServices, baseFile, baseContent, testDataFile, reversedFirContent) {
"When ignoring diagnostics, the contents of `${baseFile.name}` (expected) and `${testDataFile.name}` (actual) are not" +
" identical. `.reversed.kt` test data may only differ from its base `.fir.kt` or `.kt` test data in the reported" +
" diagnostics. Update one of these test data files."
}
}
}
}
@@ -1,4 +1,4 @@
FILE: implicitTypes.kt
FILE: implicitTypes.reversed.kt
public final fun <T, R> use(x: R|(T) -> R|): R|(T) -> R| {
^use R|<local>/x|
}
@@ -11,6 +11,6 @@ FILE: implicitTypes.kt
public final fun loop1(): R|(ERROR CLASS: Cannot infer argument for type parameter T) -> ERROR CLASS: Cannot infer argument for type parameter R| {
^loop1 R|/use<Inapplicable(INAPPLICABLE): /use>#|<<ERROR TYPE REF: Cannot infer argument for type parameter T>, <ERROR TYPE REF: Cannot infer argument for type parameter R>>(::<Unresolved reference: loop2>#)
}
public final fun loop2(): <ERROR TYPE REF: cycle> {
public final fun loop2(): R|(ERROR CLASS: Cannot infer argument for type parameter T) -> ERROR CLASS: Cannot infer argument for type parameter R| {
^loop2 R|/loop1|()
}
@@ -4,4 +4,4 @@ fun foo() = use(::bar)
fun bar(x: String) = 1
fun loop1() = <!INAPPLICABLE_CANDIDATE!>use<!>(::<!UNRESOLVED_REFERENCE!>loop2<!>)
fun loop2() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>loop1()<!>
fun loop2() = loop1()
@@ -22,8 +22,8 @@ FILE: A.kt
public get(): R|kotlin/Number|
public final fun rest(): R|kotlin/Unit| {
lval aI: R|kotlin/Int| = R|/A.A|().R|/A.a|.R|kotlin/Int.plus|(Int(10))
lval bI: R|kotlin/Int| = R|/A.A|().R|/A.b|.R|kotlin/Int.plus|(Int(20))
lval aI: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.a|.<Unresolved name: plus>#(Int(10))
lval bI: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.b|.<Unresolved name: plus>#(Int(20))
lval cI: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.c|.<Unresolved name: plus>#(Int(30))
lval dI: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.d|.<Unresolved name: plus>#(Int(40))
}
@@ -31,7 +31,7 @@ FILE: A.kt
}
public final fun test(): R|kotlin/Unit| {
lval aA: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.a|.<Unresolved name: plus>#(Int(10))
lval bA: R|kotlin/Int| = R|/A.A|().R|/A.b|.R|kotlin/Int.plus|(Int(20))
lval bA: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.b|.<Unresolved name: plus>#(Int(20))
lval cA: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.c|.<Unresolved name: plus>#(Int(30))
lval dA: <ERROR TYPE REF: Unresolved name: plus> = R|/A.A|().R|/A.d|.<Unresolved name: plus>#(Int(40))
}
@@ -15,8 +15,8 @@ class A {
<!WRONG_MODIFIER_TARGET!>public<!> field = 5
fun rest() {
val aI = A().a + 10
val bI = A().b + 20
val aI = A().a <!UNRESOLVED_REFERENCE!>+<!> 10
val bI = A().b <!UNRESOLVED_REFERENCE!>+<!> 20
val cI = A().c <!UNRESOLVED_REFERENCE!>+<!> 30
val dI = A().d <!UNRESOLVED_REFERENCE!>+<!> 40
}
@@ -24,7 +24,7 @@ class A {
fun test() {
val aA = A().a <!UNRESOLVED_REFERENCE!>+<!> 10
val bA = A().b + 20
val bA = A().b <!UNRESOLVED_REFERENCE!>+<!> 20
val cA = A().c <!UNRESOLVED_REFERENCE!>+<!> 30
val dA = A().d <!UNRESOLVED_REFERENCE!>+<!> 40
}
@@ -1,7 +1,7 @@
FILE: backingFieldWithSmartTypeParameters.kt
FILE: backingFieldWithSmartTypeParameters.reversed.kt
public final val items: R|kotlin/collections/List<kotlin/String>|
private <explicit backing field>: R|kotlin/collections/MutableList<kotlin/String>| = R|kotlin/collections/mutableListOf|<R|kotlin/String|>()
public get(): R|kotlin/collections/List<kotlin/String>|
public final fun test(): R|kotlin/Unit| {
R|/items|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|(String(one more item))
R|/items|.<Unresolved name: add>#(String(one more item))
}
@@ -2,5 +2,5 @@ val items: List<String>
field = mutableListOf()
fun test() {
items.add("one more item")
items.<!UNRESOLVED_REFERENCE!>add<!>("one more item")
}
@@ -1,7 +1,7 @@
FILE: filePrivateBackingFieldAccess.kt
FILE: filePrivateBackingFieldAccess.reversed.kt
public final val list: R|kotlin/collections/List<kotlin/String>|
private <explicit backing field>: R|kotlin/collections/MutableList<kotlin/String>| = R|kotlin/collections/mutableListOf|<R|kotlin/String|>()
public get(): R|kotlin/collections/List<kotlin/String>|
public final fun add(s: R|kotlin/String|): R|kotlin/Unit| {
R|/list|.R|SubstitutionOverride<kotlin/collections/MutableList.add: R|kotlin/Boolean|>|(R|<local>/s|)
R|/list|.<Unresolved name: add>#(R|<local>/s|)
}
@@ -2,5 +2,5 @@ val list: List<String>
field = mutableListOf<String>()
fun add(s: String) {
list.add(s)
list.<!UNRESOLVED_REFERENCE!>add<!>(s)
}
@@ -1,4 +1,4 @@
FILE: propertyTypeNarrowing.kt
FILE: propertyTypeNarrowing.reversed.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
@@ -8,8 +8,8 @@ FILE: propertyTypeNarrowing.kt
private <explicit backing field>: R|kotlin/Int| = Int(4)
public get(): R|kotlin/Number|
public final fun test(): R|kotlin/Int| {
^test this@R|/A|.R|/A.it|.R|kotlin/Int.plus|(Int(3))
public final fun test(): <ERROR TYPE REF: Unresolved name: plus> {
^test this@R|/A|.R|/A.it|.<Unresolved name: plus>#(Int(3))
}
public final val p: R|kotlin/Int| = Int(5)
@@ -2,7 +2,7 @@ class A {
val it: Number
field = 4
fun test() = it + 3
fun test() = it <!UNRESOLVED_REFERENCE!>+<!> 3
val p = 5
get() = field
@@ -10,5 +10,5 @@ typealias AliasedEFT = ExtensionFunctionType
fun foo(a: <!WRONG_EXTENSION_FUNCTION_TYPE!>@AliasedEFT<!> A) {
// @Extension annotation on an unrelated type shouldn't have any effect on this diagnostic.
// Only kotlin.Function{n} type annotated with @Extension should
"".a()
"".<!UNRESOLVED_REFERENCE!>a<!>()
}
@@ -1,4 +1,4 @@
// Functions can be recursively annotated
annotation class ann(val x: Int)
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>bar()<!>) fun foo() = 1
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>foo()<!>) fun bar() = 2
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>) fun foo() = 1
@ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>foo()<!>) fun bar() = 2
@@ -15,6 +15,6 @@ class J extends I {
// FILE: K.kt
open class K : <!CYCLIC_INHERITANCE_HIERARCHY!>J<!>() {
open class K : <!EXPOSED_SUPER_CLASS!>J<!>() {
fun baz() {}
}
@@ -1,6 +1,6 @@
// FILE: ExceptionTracker.kt
interface ExceptionTracker : <!EXPOSED_SUPER_INTERFACE!>LockBasedStorageManager.ExceptionHandlingStrategy<!> {
interface ExceptionTracker : <!CYCLIC_INHERITANCE_HIERARCHY!>LockBasedStorageManager.ExceptionHandlingStrategy<!> {
}
// FILE: StorageManager.kt
@@ -7,8 +7,8 @@ val a by <!RECURSION_IN_IMPLICIT_TYPES, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBL
val b by Delegate(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>b<!>)
val c by d
val d by <!RECURSION_IN_IMPLICIT_TYPES, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>c<!>
val c by <!RECURSION_IN_IMPLICIT_TYPES, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>d<!>
val d by c
class Delegate(i: Int) {
operator fun getValue(t: Any?, p: KProperty<*>): Int {
@@ -8,7 +8,7 @@ inline fun <reified Self : DatabaseEntity, reified Target : DatabaseEntity> Self
property: KProperty1<Target, MutableCollection<Self>>): Delegate<Self, Target?> = TODO()
class GitLabBuildProcessor: DatabaseEntity {
var processor by parent(GitLabChangesProcessor::buildProcessors)
var processor by parent(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>GitLabChangesProcessor::buildProcessors<!>)
}
interface DatabaseEntity: Entity
@@ -24,9 +24,9 @@ infix fun filter(filter: (R, Any?) -> Boolean): Delegate<R, T>
}
class GitLabChangesProcessor: DatabaseEntity {
var buildProcessors by <!INAPPLICABLE_CANDIDATE!>child_many<!>(
var buildProcessors by child_many(
GitLabBuildProcessor::class.java,
GitLabBuildProcessor::<!UNRESOLVED_REFERENCE!>processor<!>
GitLabBuildProcessor::processor
)
}
@@ -9,7 +9,7 @@ inline fun <reified Self : DatabaseEntity, reified Target : DatabaseEntity> Self
property: KProperty1<Target, MutableCollection<Self>>): Delegate<Self, Target?> = TODO()
class GitLabBuildProcessor: DatabaseEntity {
var processor by parent(GitLabChangesProcessor::buildProcessors)
var processor by parent(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>GitLabChangesProcessor::buildProcessors<!>)
}
interface DatabaseEntity: Entity
@@ -25,9 +25,9 @@ infix fun filter(filter: (R, Any?) -> Boolean): Delegate<R, T>
}
class GitLabChangesProcessor: DatabaseEntity {
var buildProcessors by <!INAPPLICABLE_CANDIDATE!>child_many<!>(
var buildProcessors by child_many(
GitLabBuildProcessor::class.java,
GitLabBuildProcessor::<!UNRESOLVED_REFERENCE!>processor<!>
GitLabBuildProcessor::processor
)
}
@@ -7,10 +7,10 @@ fun <T> simpleAsync1(block: suspend Scope.() -> T) {}
suspend fun <T> simpleAsync2(block: Scope.() -> T) {}
suspend fun <T> simpleAsync3(block: suspend Scope.() -> T) {}
fun insideJob0() = doTheJob0()
fun insideJob1() = doTheJob1()
suspend fun insideJob2() = doTheJob2()
suspend fun insideJob3() = doTheJob3()
fun insideJob0() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>doTheJob0()<!>
fun insideJob1() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>doTheJob1()<!>
suspend fun insideJob2() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>doTheJob2()<!>
suspend fun insideJob3() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>doTheJob3()<!>
fun doTheJob0() = simpleAsync0 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>insideJob0()<!> }
fun doTheJob1() = simpleAsync1 { <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>insideJob1()<!> }
@@ -29,5 +29,5 @@ fun modality(): Modality = Modality.FINAL
class DeserializedClassDescriptor2 : ClassDescriptor {
private val modality = modality()
override fun getModality() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>modality<!>
override fun getModality() = modality
}
@@ -8,5 +8,5 @@ class Foo<P1 : Boo<P2, P3, P4>, P2 : Boo<P1, P3, P4>, P3 : Boo<P1, P2, P4>, P4 :
// FILE: main.kt
fun main() {
val x = <!DEBUG_INFO_EXPRESSION_TYPE("Foo<Boo<Boo<*, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>, Boo<*, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>, Boo<*, *, Boo<*, *, *>>, Boo<*, *, *>>..Foo<*, *, *, *>?!")!>Boo.test1()<!>
val x = <!DEBUG_INFO_EXPRESSION_TYPE("Foo<kotlin.Any, kotlin.Any, kotlin.Any, kotlin.Any>..Foo<*, *, *, *>?!")!>Boo.test1()<!>
}
@@ -13,5 +13,5 @@ fun applyEditorTo(arg: CidrRunConfiguration<Any?, CidrBuildTarget<Any?>>) {}
fun main() {
// Previously, for CidrRunConfiguration raw type, it's lower bound was resolved as CidrRunConfiguration<Any?, CidrBuildTarget<*>> in K2
// That is not a subtype of CidrRunConfiguration<Any?, CidrBuildTarget<Any?>>
applyEditorTo(CustomGdbServerRunConfiguration()) // K1: ok, K2: was ARGUMENT_TYPE_MISMATCH
applyEditorTo(<!ARGUMENT_TYPE_MISMATCH!>CustomGdbServerRunConfiguration()<!>) // K1: ok, K2: was ARGUMENT_TYPE_MISMATCH
}
@@ -71,7 +71,7 @@ object Obj {
fun test9(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById9()<!>
inline fun <reified T> findViewById10(): T where T: View3, T: View5 = null as T
fun test10(): View1 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById10()<!>
fun test10(): View1 = <!INFERRED_TYPE_VARIABLE_INTO_POSSIBLE_EMPTY_INTERSECTION!>findViewById10<!>()
fun <T: View2> findViewById11(): T = null as T
fun test11(): View4 = <!NEW_INFERENCE_ERROR, RETURN_TYPE_MISMATCH!>findViewById11()<!>
@@ -12,5 +12,5 @@ object Host {
import bar.HostAlias.foo
fun test() {
foo()
}
<!UNRESOLVED_REFERENCE!>foo<!>()
}
@@ -25,5 +25,5 @@ fun foo(
sample: <!UNRESOLVED_REFERENCE!>JavaSample<!>,
alias: JavaAlias
) {
member()
<!UNRESOLVED_REFERENCE!>member<!>()
}
@@ -23,6 +23,6 @@ import test.EnumAlias
fun bar() {
Entry
<!UNRESOLVED_REFERENCE!>Entry<!>
EnumAlias.Entry
}
@@ -1,4 +1,4 @@
FILE: kt50994.fir.kt
FILE: kt50994.reversed.kt
public final class ProcessorWithParent : R|Entity| {
public constructor(): R|ProcessorWithParent| {
super<R|kotlin/Any|>()
@@ -18,11 +18,11 @@ FILE: kt50994.fir.kt
super<R|kotlin/Any|>()
}
public final var processors: R|kotlin/collections/MutableCollection<ERROR CLASS: Type for TC is not inferred>|by this@R|/ProcessorWithChildren|.R|/children<Inapplicable(INAPPLICABLE): /children>#|<<ERROR TYPE REF: Type for SC is not inferred>, <ERROR TYPE REF: Type for TC is not inferred>>(<getClass>(Q|ProcessorWithParent|).R|kotlin/jvm/java|<R|ProcessorWithParent|>, Q|ProcessorWithParent|::<Unresolved reference: processor>#)
public get(): R|kotlin/collections/MutableCollection<ERROR CLASS: Type for TC is not inferred>| {
public final var processors: R|kotlin/collections/MutableCollection<ProcessorWithParent>|by this@R|/ProcessorWithChildren|.R|/children|<R|ProcessorWithChildren|, R|ProcessorWithParent|>(<getClass>(Q|ProcessorWithParent|).R|kotlin/jvm/java|<R|ProcessorWithParent|>, Q|ProcessorWithParent|::R|/ProcessorWithParent.processor|)
public get(): R|kotlin/collections/MutableCollection<ProcessorWithParent>| {
^ this@R|/ProcessorWithChildren|.D|/ProcessorWithChildren.processors|.R|SubstitutionOverride</Delegate.getValue: R|kotlin/collections/MutableCollection<Stub (chain inference): TypeVariable(_TC)>|>|(this@R|/ProcessorWithChildren|, ::R|/ProcessorWithChildren.processors|)
}
public set(<set-?>: R|kotlin/collections/MutableCollection<ERROR CLASS: Type for TC is not inferred>|): R|kotlin/Unit| {
public set(<set-?>: R|kotlin/collections/MutableCollection<ProcessorWithParent>|): R|kotlin/Unit| {
this@R|/ProcessorWithChildren|.D|/ProcessorWithChildren.processors|.R|SubstitutionOverride</Delegate.setValue: R|kotlin/Unit|>|(this@R|/ProcessorWithChildren|, ::R|/ProcessorWithChildren.processors|, R|<local>/processors|)
}
@@ -5,11 +5,11 @@ import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty1
class ProcessorWithParent : Entity {
var processor by parent(ProcessorWithChildren::processors)
var processor by parent(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>ProcessorWithChildren::processors<!>)
}
class ProcessorWithChildren : Entity {
var processors by <!INAPPLICABLE_CANDIDATE!>children<!>(ProcessorWithParent::class.java, ProcessorWithParent::<!UNRESOLVED_REFERENCE!>processor<!>)
var processors by children(ProcessorWithParent::class.java, ProcessorWithParent::processor)
}
class Processor2WithParent : Entity {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -13,6 +13,10 @@ import org.jetbrains.kotlin.test.utils.FirIdenticalCheckerHelper
import org.jetbrains.kotlin.test.utils.firTestDataFile
import org.jetbrains.kotlin.test.utils.originalTestDataFile
import java.io.File
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.services.assertions
import org.jetbrains.kotlin.test.services.sourceFileProvider
abstract class AbstractFirIdenticalChecker(testServices: TestServices) : AfterAnalysisChecker(testServices) {
protected inner class SpecificHelper : FirIdenticalCheckerHelper(testServices) {
@@ -29,4 +33,40 @@ abstract class AbstractFirIdenticalChecker(testServices: TestServices) : AfterAn
val testDataFile = testServices.moduleStructure.originalTestDataFiles.first()
checkTestDataFile(testDataFile)
}
/**
* Asserts that [baseFile] and [customFile] have the same content after preprocessing (which removes diagnostics and other meta info). This
* prevents situations where one test data changes, but changes to the other test data are forgotten.
*/
protected fun assertPreprocessedTestDataAreEqual(
testServices: TestServices,
baseFile: File,
baseContent: String,
customFile: File,
customContent: String,
message: () -> String,
) {
val processedBaseContent = testServices.sourceFileProvider.getContentOfSourceFile(
TestFile(
baseFile.path,
baseContent,
baseFile,
startLineNumberInOriginalFile = 0,
isAdditional = false,
RegisteredDirectives.Empty,
)
)
val processedLlContent = testServices.sourceFileProvider.getContentOfSourceFile(
TestFile(
customFile.path,
customContent,
customFile,
startLineNumberInOriginalFile = 0,
isAdditional = false,
RegisteredDirectives.Empty,
)
)
testServices.assertions.assertEquals(processedBaseContent, processedLlContent, message)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -17,6 +17,8 @@ class FirIdenticalChecker(testServices: TestServices) : AbstractFirIdenticalChec
if (testDataFile.isFirTestData) {
val classicFile = helper.getClassicFileToCompare(testDataFile)
if (".reversed." in classicFile.path) return
if (helper.contentsAreEquals(classicFile, testDataFile, trimLines = true)) {
helper.deleteFirFile(testDataFile)
helper.addDirectiveToClassicFileAndAssert(classicFile)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -18,7 +18,7 @@ class FirOldFrontendMetaConfigurator(testServices: TestServices) : MetaTestConfi
// Skip `.ll.kt` tests, whose path is provided by `LLFirMetaTestConfigurator`. Because `FirOldFrontendMetaConfigurator` is usually
// configured with `forTestsMatching`, it'll be executed after `LLFirMetaTestConfigurator`, which is configured generally.
if (originalFile.isLLFirTestData) return testDataFileName
if (originalFile.isLLFirTestData || ".reversed." in originalFile.path) return testDataFileName
val isFirIdentical = originalFile.useLines { lines -> lines.any { it == "// ${FirDiagnosticsDirectives.FIR_IDENTICAL.name}" } }
return if (isFirIdentical) {