K2: report DUPLICATE_CLASS_NAMES error in JVM backend
It was already reported in the K2+PSI mode, but not LT because BuilderFactoryForDuplicateClassNameDiagnostics relied on PSI, and did not do anything if PSI was missing. No tests were added because it fixes the already existing test `compiler/testData/cli/jvm/fileClassClashMultipleFiles` after the project is migrated to 2.0. #KT-59586
This commit is contained in:
committed by
Space Team
parent
84bf411cc3
commit
2823fff63d
+12
-13
@@ -18,34 +18,33 @@ package org.jetbrains.kotlin.codegen.state
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderFactory
|
||||
import org.jetbrains.kotlin.codegen.ClassNameCollectionClassBuilderFactory
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
|
||||
class BuilderFactoryForDuplicateClassNameDiagnostics(
|
||||
builderFactory: ClassBuilderFactory,
|
||||
private val diagnostics: DiagnosticSink
|
||||
builderFactory: ClassBuilderFactory,
|
||||
private val state: GenerationState,
|
||||
) : ClassNameCollectionClassBuilderFactory(builderFactory) {
|
||||
|
||||
private val className = ConcurrentHashMap<String, JvmDeclarationOrigin>()
|
||||
|
||||
override fun handleClashingNames(internalName: String, origin: JvmDeclarationOrigin) {
|
||||
val another = className.getOrPut(internalName, { origin })
|
||||
//workaround for inlined anonymous objects
|
||||
if (origin.element != another.element) {
|
||||
val another = className.getOrPut(internalName) { origin }
|
||||
// Allow clashing classes if they are originated from the same source element. For example, this happens during inlining anonymous
|
||||
// objects. In JVM IR, this also happens for anonymous classes in default arguments of tailrec functions, because default arguments
|
||||
// are deep-copied (see JvmTailrecLowering).
|
||||
if (origin.originalSourceElement != another.originalSourceElement) {
|
||||
reportError(internalName, origin, another)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportError(internalName: String, vararg another: JvmDeclarationOrigin) {
|
||||
val fromString = another.mapNotNull { it.descriptor }.
|
||||
joinToString { DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(it) }
|
||||
val duplicateClasses =
|
||||
another.mapNotNull { it.descriptor }.joinToString { DescriptorRenderer.ONLY_NAMES_WITH_SHORT_TYPES.render(it) }
|
||||
|
||||
another.mapNotNull { it.element }.forEach {
|
||||
diagnostics.report(ErrorsJvm.DUPLICATE_CLASS_NAMES.on(it, internalName, fromString))
|
||||
for (origin in another) {
|
||||
state.reportDuplicateClassNameError(origin, internalName, duplicateClasses)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.OnDemandSuppressCache
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmCompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind.*
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
@@ -291,6 +292,12 @@ class GenerationState private constructor(
|
||||
|
||||
var multiFieldValueClassUnboxInfo: (ClassDescriptor) -> MultiFieldValueClassUnboxInfo? = { null }
|
||||
|
||||
var reportDuplicateClassNameError: (JvmDeclarationOrigin, String, String) -> Unit = { origin, internalName, duplicateClasses ->
|
||||
origin.element?.let {
|
||||
diagnostics.report(ErrorsJvm.DUPLICATE_CLASS_NAMES.on(it, internalName, duplicateClasses))
|
||||
}
|
||||
}
|
||||
|
||||
val typeApproximator: TypeApproximator? =
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.NewInference))
|
||||
TypeApproximator(module.builtIns, languageVersionSettings)
|
||||
@@ -308,7 +315,7 @@ class GenerationState private constructor(
|
||||
},
|
||||
{
|
||||
// In IR backend, we have more precise information about classes and methods we are going to generate,
|
||||
// and report signature conflict errors in JvmSignatureClashTracker.
|
||||
// and report signature conflict errors in JvmSignatureClashDetector.
|
||||
if (isIrBackend)
|
||||
it
|
||||
else
|
||||
@@ -318,7 +325,7 @@ class GenerationState private constructor(
|
||||
shouldGenerate = { origin -> !shouldOnlyCollectSignatures(origin) },
|
||||
).apply { duplicateSignatureFactory = this }
|
||||
},
|
||||
{ BuilderFactoryForDuplicateClassNameDiagnostics(it, diagnostics) },
|
||||
{ BuilderFactoryForDuplicateClassNameDiagnostics(it, this) },
|
||||
{
|
||||
configuration.get(JVMConfigurationKeys.DECLARATIONS_JSON_PATH)
|
||||
?.let { destination -> SignatureDumpingBuilderFactory(it, File(destination)) } ?: it
|
||||
|
||||
Reference in New Issue
Block a user