From eba1fdec1d46bf5f175914450c1167d133f4b917 Mon Sep 17 00:00:00 2001 From: Kirill Rakhman Date: Mon, 30 Oct 2023 16:58:59 +0100 Subject: [PATCH] [Tests] Check for duplicate file names in FIR diagnostic tests with IR The relative path of a test file is just its name, even if it's in a module. Diagnostics in IR are mapped to the file path and so it's reported on all files with the same path, i.e. name. This doesn't happen in production code because no two files can have the same path. The proper fix would be to prefix the test files' paths with the module name. Unfortunately, this breaks a bunch of test runners that rely on the current behavior. Especially, some JS runners turned out to be hard to fix. The linked YouTrack issue contains a WIP, incomplete patch of fixing some runners. #KT-61592 Fixed #KT-63252 --- .../tests/multiplatform/hmpp/kt57320.fir.kt | 12 ++++---- .../tests/multiplatform/hmpp/kt57320.kt | 4 +-- .../test/runners/AbstractFirDiagnosticTest.kt | 6 +++- .../test/runners/DuplicateFileNameChecker.kt | 28 +++++++++++++++++++ ...stractFirWithInterpreterDiagnosticsTest.kt | 5 ++++ 5 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/DuplicateFileNameChecker.kt diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt index 9964773b496..71c9a8060e1 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.fir.kt @@ -11,10 +11,10 @@ // MODULE: commonJS()()(common) // TARGET_PLATFORM: JS -// FILE: StringValue.kt -actual class StringValue(val value: String) - -actual fun StringValue.plus(other: String) = StringValue(this.value + other) +// FILE: StringValueJs.kt +actual class StringValue(val value: String) + +actual fun StringValue.plus(other: String) = StringValue(this.value + other) // MODULE: intermediate()()(common) // TARGET_PLATFORM: Common @@ -31,10 +31,10 @@ interface KotlinXStringDemoInterface { // MODULE: js()()(common, intermediate) // TARGET_PLATFORM: JS -// FILE: StringDemoInterface.kt +// FILE: StringDemoInterfaceJs.kt actual typealias StringDemoInterface = KotlinXStringDemoInterface -actual fun StringDemoInterface.; The following declaration is incompatible because return type is different: expect fun StringDemoInterface.plusK(): String")!>plusK() = StringValue(value).plus("K").value +actual fun StringDemoInterface.; The following declaration is incompatible because return type is different: expect fun StringDemoInterface.plusK(): String")!>plusK() = StringValue(value).plus("K").value // FILE: main.kt class StringDemo(override val value: String) : StringDemoInterface diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt index 067ecb08938..e6e6ac33470 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/kt57320.kt @@ -11,7 +11,7 @@ expect fun StringValue.plus(other: String): Strin // MODULE: commonJS()()(common) // TARGET_PLATFORM: JS -// FILE: StringValue.kt +// FILE: StringValueJs.kt actual class StringValue(val value: String) actual fun StringValue.plus(other: String) = StringValue(this.value + other) @@ -31,7 +31,7 @@ expect fun StringDemoInterface.plusK(): String // MODULE: js()()(common, intermediate) // TARGET_PLATFORM: JS -// FILE: StringDemoInterface.kt +// FILE: StringDemoInterfaceJs.kt actual typealias StringDemoInterface = KotlinXStringDemoInterface actual fun StringDemoInterface.plusK() = StringValue(value).plus("K").value diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt index 1cbed2ba2ca..c3188cd89b1 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/AbstractFirDiagnosticTest.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.test.runners import org.jetbrains.kotlin.config.ExplicitApiMode import org.jetbrains.kotlin.diagnostics.impl.SimpleDiagnosticsCollector import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.SessionConfiguration import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.test.* @@ -110,6 +111,9 @@ abstract class AbstractFirWithActualizerDiagnosticsTest(val parser: FirParser) : } useAdditionalService(::LibraryProvider) + + @OptIn(TestInfrastructureInternals::class) + useModuleStructureTransformers(DuplicateFileNameChecker) } } @@ -238,7 +242,7 @@ fun TestConfigurationBuilder.baseFirDiagnosticTestConfiguration( class FirLazyDeclarationResolverWithPhaseCheckingSessionComponentRegistrar : FirSessionComponentRegistrar() { private val lazyResolver = FirCompilerLazyDeclarationResolverWithPhaseChecking() - @OptIn(org.jetbrains.kotlin.fir.SessionConfiguration::class) + @OptIn(SessionConfiguration::class) override fun registerAdditionalComponent(session: FirSession) { session.register(FirLazyDeclarationResolver::class, lazyResolver) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/DuplicateFileNameChecker.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/DuplicateFileNameChecker.kt new file mode 100644 index 00000000000..0c0c9850cb7 --- /dev/null +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/DuplicateFileNameChecker.kt @@ -0,0 +1,28 @@ +/* + * 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.test.runners + +import org.jetbrains.kotlin.test.TestInfrastructureInternals +import org.jetbrains.kotlin.test.services.ModuleStructureTransformer +import org.jetbrains.kotlin.test.services.TestModuleStructure + +// TODO remove when duplicate files names are supported by prefix their path with the module name KT-63252 +@OptIn(TestInfrastructureInternals::class) +object DuplicateFileNameChecker : ModuleStructureTransformer() { + override fun transformModuleStructure(moduleStructure: TestModuleStructure): TestModuleStructure { + val files = mutableSetOf() + + for (module in moduleStructure.modules) { + for (file in module.files) { + if (!files.add(file.name)) { + throw IllegalStateException("Duplicate file name: ${file.name}") + } + } + } + + return moduleStructure + } +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/ir/AbstractFirWithInterpreterDiagnosticsTest.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/ir/AbstractFirWithInterpreterDiagnosticsTest.kt index 10cfcf6bc48..160efd7115a 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/ir/AbstractFirWithInterpreterDiagnosticsTest.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/runners/ir/AbstractFirWithInterpreterDiagnosticsTest.kt @@ -7,12 +7,14 @@ package org.jetbrains.kotlin.test.runners.ir import org.jetbrains.kotlin.test.FirParser import org.jetbrains.kotlin.test.TargetBackend +import org.jetbrains.kotlin.test.TestInfrastructureInternals import org.jetbrains.kotlin.test.backend.ir.IrDiagnosticsHandler import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.irHandlersStep import org.jetbrains.kotlin.test.directives.configureFirParser import org.jetbrains.kotlin.test.frontend.fir.Fir2IrResultsConverter import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest +import org.jetbrains.kotlin.test.runners.DuplicateFileNameChecker import org.jetbrains.kotlin.test.runners.baseFirDiagnosticTestConfiguration abstract class AbstractFirWithInterpreterDiagnosticsTest(val parser: FirParser) : AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JVM_IR) { @@ -26,6 +28,9 @@ abstract class AbstractFirWithInterpreterDiagnosticsTest(val parser: FirParser) ::IrDiagnosticsHandler ) } + + @OptIn(TestInfrastructureInternals::class) + useModuleStructureTransformers(DuplicateFileNameChecker) } }