[FIR] Report top-level conflicts between TA constructors and funs
^KT-59880
This commit is contained in:
committed by
Space Team
parent
01d4f25363
commit
f719436d1f
+65
-15
@@ -15,14 +15,19 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl.Companion.DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.modifiersRepresentation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.expressions.FirBlock
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.outerType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.TypeAliasConstructorsSubstitutingScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -90,7 +95,7 @@ private class DeclarationBuckets {
|
||||
val extensionProperties = mutableListOf<Pair<FirProperty, String>>()
|
||||
}
|
||||
|
||||
private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, DeclarationBuckets> {
|
||||
private fun groupTopLevelByName(declarations: List<FirDeclaration>, context: CheckerContext): Map<Name, DeclarationBuckets> {
|
||||
val groups = mutableMapOf<Name, DeclarationBuckets>()
|
||||
for (declaration in declarations) {
|
||||
if (!declaration.isCollectable()) continue
|
||||
@@ -114,12 +119,20 @@ private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, D
|
||||
if (declaration.classKind != ClassKind.OBJECT) {
|
||||
declaration.declarations
|
||||
.filterIsInstance<FirConstructor>()
|
||||
.mapTo(group.constructors) { it to FirRedeclarationPresenter.represent(it, declaration) }
|
||||
.mapTo(group.constructors) { it to FirRedeclarationPresenter.represent(it, declaration.symbol) }
|
||||
}
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
val group = groups.getOrPut(declaration.name, ::DeclarationBuckets)
|
||||
group.classLikes += declaration to FirRedeclarationPresenter.represent(declaration)
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
declaration.expandedClassWithConstructorsScope(context)?.let { (_, scopeWithConstructors) ->
|
||||
scopeWithConstructors.processDeclaredConstructors {
|
||||
group.constructors += it.fir to FirRedeclarationPresenter.represent(it.fir, declaration.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
is FirTypeAlias ->
|
||||
groups.getOrPut(declaration.name, ::DeclarationBuckets).classLikes +=
|
||||
declaration to FirRedeclarationPresenter.represent(declaration)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -173,8 +186,16 @@ fun collectConflictingLocalFunctionsFrom(block: FirBlock, context: CheckerContex
|
||||
is FirRegularClass ->
|
||||
// TODO, KT-61243: Use declaredMemberScope
|
||||
collectable.declarations.filterIsInstance<FirConstructor>().forEach {
|
||||
inspector.collect(it, FirRedeclarationPresenter.represent(it, collectable), functionDeclarations)
|
||||
inspector.collect(it, FirRedeclarationPresenter.represent(it, collectable.symbol), functionDeclarations)
|
||||
}
|
||||
is FirTypeAlias -> {
|
||||
collectable.expandedClassWithConstructorsScope(context)?.let { (_, scopeWithConstructors) ->
|
||||
scopeWithConstructors.processDeclaredConstructors {
|
||||
@OptIn(SymbolInternals::class)
|
||||
inspector.collect(it.fir, FirRedeclarationPresenter.represent(it.fir, collectable.symbol), functionDeclarations)
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +245,7 @@ private fun <D : FirDeclaration> FirDeclarationCollector<D>.collect(
|
||||
@Suppress("GrazieInspection")
|
||||
fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
|
||||
|
||||
for ((declarationName, group) in groupTopLevelByName(file.declarations)) {
|
||||
for ((declarationName, group) in groupTopLevelByName(file.declarations, context)) {
|
||||
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
|
||||
val groupHasSimpleFunctions = group.simpleFunctions.isNotEmpty()
|
||||
|
||||
@@ -257,15 +278,21 @@ fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packa
|
||||
collect(group.properties, conflictingSymbol, conflictingPresentation, conflictingFile)
|
||||
|
||||
if (groupHasSimpleFunctions) {
|
||||
if (conflictingSymbol !is FirRegularClassSymbol) return
|
||||
if (conflictingSymbol.classKind == ClassKind.OBJECT || conflictingSymbol.classKind == ClassKind.ENUM_ENTRY) return
|
||||
val declaration = conflictingSymbol.fir
|
||||
|
||||
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
||||
if (declaration !is FirClassLikeDeclaration) {
|
||||
return
|
||||
}
|
||||
|
||||
val classWithSameName = conflictingSymbol.fir
|
||||
classWithSameName.unsubstitutedScope(context).processDeclaredConstructors { constructor ->
|
||||
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, classWithSameName)
|
||||
collect(group.simpleFunctions, conflictingSymbol = constructor, conflictingPresentation = ctorRepresentation)
|
||||
declaration.expandedClassWithConstructorsScope(context)?.let { (expandedClass, scopeWithConstructors) ->
|
||||
if (expandedClass.classKind == ClassKind.OBJECT || expandedClass.classKind == ClassKind.ENUM_ENTRY) {
|
||||
return
|
||||
}
|
||||
|
||||
scopeWithConstructors.processDeclaredConstructors { constructor ->
|
||||
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, declaration.symbol)
|
||||
collect(group.simpleFunctions, conflictingSymbol = constructor, conflictingPresentation = ctorRepresentation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +338,29 @@ fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packa
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirClassLikeDeclaration.expandedClassWithConstructorsScope(context: CheckerContext): Pair<FirRegularClassSymbol, FirScope>? {
|
||||
return when (this) {
|
||||
is FirRegularClass -> symbol to unsubstitutedScope(context)
|
||||
is FirTypeAlias -> {
|
||||
val expandedType = expandedConeType
|
||||
val expandedClass = expandedType?.toRegularClassSymbol(context.session)
|
||||
val expandedTypeScope = expandedType?.scope(
|
||||
context.session, context.scopeSession,
|
||||
FakeOverrideTypeCalculator.DoNothing,
|
||||
requiredMembersPhase = FirResolvePhase.STATUS,
|
||||
)
|
||||
|
||||
if (expandedType != null && expandedClass != null && expandedTypeScope != null) {
|
||||
val outerType = outerType(expandedType, context.session) { it.outerClassSymbol(context) }
|
||||
expandedClass to TypeAliasConstructorsSubstitutingScope(symbol, expandedTypeScope, outerType)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirDeclarationCollector<FirDeclaration>.collectTopLevelConflict(
|
||||
declaration: FirDeclaration,
|
||||
declarationPresentation: String,
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
@@ -99,7 +99,7 @@ internal object FirRedeclarationPresenter {
|
||||
appendRepresentation(it.symbol.classId)
|
||||
}
|
||||
|
||||
fun represent(it: FirConstructor, owner: FirRegularClass) = buildString {
|
||||
fun represent(it: FirConstructor, owner: FirClassLikeSymbol<*>) = buildString {
|
||||
repeat(it.contextReceivers.size) {
|
||||
append(',')
|
||||
}
|
||||
@@ -110,7 +110,7 @@ internal object FirRedeclarationPresenter {
|
||||
append('>')
|
||||
append('[')
|
||||
append(']')
|
||||
appendRepresentation(owner.symbol.classId)
|
||||
appendRepresentation(owner.classId)
|
||||
append('(')
|
||||
it.valueParameters.forEach {
|
||||
appendRepresentation(it)
|
||||
|
||||
+3
-1
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.packageFqName
|
||||
import org.jetbrains.kotlin.fir.resolve.getContainingDeclaration
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.PACKAGE_MEMBER
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.typeAliasForConstructor
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
@@ -58,7 +59,8 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
||||
declarationConflictingSymbols: Map<FirDeclaration, SmartSet<FirBasedSymbol<*>>>,
|
||||
) {
|
||||
declarationConflictingSymbols.forEach { (conflictingDeclaration, symbols) ->
|
||||
val source = conflictingDeclaration.source
|
||||
val typeAliasForConstructorSource = (conflictingDeclaration as? FirConstructor)?.typeAliasForConstructor?.source
|
||||
val source = typeAliasForConstructorSource ?: conflictingDeclaration.source
|
||||
if (symbols.isEmpty()) return@forEach
|
||||
|
||||
val factory =
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
|
||||
class C(val x: Int)
|
||||
|
||||
typealias CC = C
|
||||
<!CONFLICTING_OVERLOADS!>typealias CC = C<!>
|
||||
|
||||
fun CC(x: Int) = x
|
||||
<!CONFLICTING_OVERLOADS!>fun CC(x: Int)<!> = x
|
||||
|
||||
class Outer {
|
||||
class C(val x: Int)
|
||||
|
||||
Reference in New Issue
Block a user