[JVM] Split JvmSignatureClashDetector into two classes

One for methods, one for fields.
Later we are going to use the new `SignatureClashDetector` class
for detecting clashes of KLIB signatures.
This commit is contained in:
Sergej Jaskiewicz
2024-01-09 19:42:45 +01:00
committed by Space Team
parent e0f9e09a97
commit e0cb145c6b
4 changed files with 179 additions and 80 deletions
@@ -0,0 +1,70 @@
/*
* 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.ir.linkage
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory1
import org.jetbrains.kotlin.ir.IrDiagnosticReporter
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.sourceElement
import org.jetbrains.kotlin.utils.SmartSet
/**
* Collects the information about declarations and their signatures and reports cases when multiple declarations have the same signature.
*/
abstract class SignatureClashDetector<Signature : Any, Declaration : IrDeclaration> {
private val declarationsBySignature: HashMap<Signature, MutableSet<Declaration>> = LinkedHashMap()
/**
* Returns all the declarations that have [signature] previously recorded by [trackDeclaration].
*/
protected fun declarationsWithSignature(signature: Signature): Set<Declaration> =
declarationsBySignature[signature] ?: emptySet()
/**
* Records the declaration, so it could later participate in signature clash detection.
*/
fun trackDeclaration(declaration: Declaration, rawSignature: Signature) {
declarationsBySignature.computeIfAbsent(rawSignature) { SmartSet.create() }.add(declaration)
}
/**
* Invoked by [reportErrorsTo] whenever at least two declarations with the same [signature] are detected.
*
* Use [reportSignatureClashTo] in the implementation to report a diagnostic.
*/
protected abstract fun reportSignatureConflict(
signature: Signature,
declarations: Collection<Declaration>,
diagnosticReporter: IrDiagnosticReporter,
)
/**
* Reports all detected signature clashes.
*/
open fun reportErrorsTo(diagnosticReporter: IrDiagnosticReporter) {
for ((signature, declarations) in declarationsBySignature) {
if (declarations.size <= 1) continue
reportSignatureConflict(signature, declarations, diagnosticReporter)
}
}
protected inline fun <Data : Any, ConflictingDeclaration : IrDeclaration> reportSignatureClashTo(
diagnosticReporter: IrDiagnosticReporter,
diagnosticFactory: KtDiagnosticFactory1<Data>,
declarations: Collection<ConflictingDeclaration>,
data: Data,
reportOnIfSynthetic: (ConflictingDeclaration) -> IrElement,
) {
declarations.mapTo(LinkedHashSet()) { declaration ->
val reportOn = declaration.takeUnless { it.startOffset < 0 } ?: reportOnIfSynthetic(declaration)
diagnosticReporter.at(reportOn.sourceElement(), reportOn, declaration.file)
}.forEach {
it.report(diagnosticFactory, data)
}
}
}