[FIR] FirDeclarationInspector -> FirDeclarationCollector<T>
Makes more sense when you only want to collect declarations of certain type.
This commit is contained in:
committed by
Space Team
parent
5b9c35de2e
commit
6fa5363cf4
+27
-16
@@ -128,14 +128,15 @@ private fun groupTopLevelByName(declarations: List<FirDeclaration>): Map<Name, D
|
|||||||
/**
|
/**
|
||||||
* Collects FirDeclarations for further analysis.
|
* Collects FirDeclarations for further analysis.
|
||||||
*/
|
*/
|
||||||
class FirDeclarationInspector(
|
class FirDeclarationCollector<D : FirDeclaration>(
|
||||||
private val context: CheckerContext,
|
internal val context: CheckerContext,
|
||||||
) {
|
) {
|
||||||
private val session: FirSession get() = context.sessionHolder.session
|
internal val session: FirSession get() = context.sessionHolder.session
|
||||||
|
|
||||||
val declarationConflictingSymbols: HashMap<FirDeclaration, SmartSet<FirBasedSymbol<*>>> = hashMapOf()
|
val declarationConflictingSymbols: HashMap<D, SmartSet<FirBasedSymbol<*>>> = hashMapOf()
|
||||||
|
}
|
||||||
|
|
||||||
fun collectClassMembers(klass: FirRegularClass) {
|
fun FirDeclarationCollector<FirDeclaration>.collectClassMembers(klass: FirRegularClass) {
|
||||||
val otherDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
|
val otherDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
|
||||||
val functionDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
|
val functionDeclarations = mutableMapOf<String, MutableList<FirDeclaration>>()
|
||||||
|
|
||||||
@@ -156,9 +157,17 @@ class FirDeclarationInspector(
|
|||||||
map.getOrPut(representation, ::mutableListOf).also {
|
map.getOrPut(representation, ::mutableListOf).also {
|
||||||
it.add(declaration)
|
it.add(declaration)
|
||||||
|
|
||||||
|
private fun <D : FirDeclaration> FirDeclarationCollector<D>.collect(
|
||||||
|
declaration: D,
|
||||||
|
representation: String,
|
||||||
|
map: MutableMap<String, MutableList<D>>,
|
||||||
|
) {
|
||||||
|
map.getOrPut(representation, ::mutableListOf).also {
|
||||||
|
it.add(declaration)
|
||||||
|
|
||||||
val conflicts = SmartSet.create<FirBasedSymbol<*>>()
|
val conflicts = SmartSet.create<FirBasedSymbol<*>>()
|
||||||
for (otherDeclaration in it) {
|
for (otherDeclaration in it) {
|
||||||
if (otherDeclaration != declaration && !isOverloadable(declaration, otherDeclaration)) {
|
if (otherDeclaration != declaration && !isOverloadable(declaration, otherDeclaration, session)) {
|
||||||
conflicts.add(otherDeclaration.symbol)
|
conflicts.add(otherDeclaration.symbol)
|
||||||
declarationConflictingSymbols.getOrPut(otherDeclaration) { SmartSet.create() }.add(declaration.symbol)
|
declarationConflictingSymbols.getOrPut(otherDeclaration) { SmartSet.create() }.add(declaration.symbol)
|
||||||
}
|
}
|
||||||
@@ -188,7 +197,7 @@ class FirDeclarationInspector(
|
|||||||
*/
|
*/
|
||||||
@OptIn(SymbolInternals::class)
|
@OptIn(SymbolInternals::class)
|
||||||
@Suppress("GrazieInspection")
|
@Suppress("GrazieInspection")
|
||||||
fun collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
|
fun FirDeclarationCollector<FirDeclaration>.collectTopLevel(file: FirFile, packageMemberScope: FirPackageMemberScope) {
|
||||||
|
|
||||||
for ((declarationName, group) in groupTopLevelByName(file.declarations)) {
|
for ((declarationName, group) in groupTopLevelByName(file.declarations)) {
|
||||||
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
|
val groupHasClassLikesOrProperties = group.classLikes.isNotEmpty() || group.properties.isNotEmpty()
|
||||||
@@ -227,6 +236,7 @@ class FirDeclarationInspector(
|
|||||||
if (conflictingSymbol.classKind == ClassKind.OBJECT || conflictingSymbol.classKind == ClassKind.ENUM_ENTRY) return
|
if (conflictingSymbol.classKind == ClassKind.OBJECT || conflictingSymbol.classKind == ClassKind.ENUM_ENTRY) return
|
||||||
|
|
||||||
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
conflictingSymbol.lazyResolveToPhase(FirResolvePhase.STATUS)
|
||||||
|
|
||||||
val classWithSameName = conflictingSymbol.fir
|
val classWithSameName = conflictingSymbol.fir
|
||||||
classWithSameName.unsubstitutedScope(context).processDeclaredConstructors { constructor ->
|
classWithSameName.unsubstitutedScope(context).processDeclaredConstructors { constructor ->
|
||||||
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, classWithSameName)
|
val ctorRepresentation = FirRedeclarationPresenter.represent(constructor.fir, classWithSameName)
|
||||||
@@ -276,7 +286,7 @@ class FirDeclarationInspector(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun collectTopLevelConflict(
|
private fun FirDeclarationCollector<FirDeclaration>.collectTopLevelConflict(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
declarationPresentation: String,
|
declarationPresentation: String,
|
||||||
containingFile: FirFile,
|
containingFile: FirFile,
|
||||||
@@ -297,17 +307,17 @@ class FirDeclarationInspector(
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
if (!conflicting.isCollectable()) return
|
if (!conflicting.isCollectable()) return
|
||||||
if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile)) return
|
if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile, session)) return
|
||||||
if (
|
if (
|
||||||
conflicting is FirMemberDeclaration &&
|
conflicting is FirMemberDeclaration &&
|
||||||
!session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), dispatchReceiver = null)
|
!session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), dispatchReceiver = null)
|
||||||
) return
|
) return
|
||||||
if (isOverloadable(declaration, conflicting)) return
|
if (isOverloadable(declaration, conflicting, session)) return
|
||||||
|
|
||||||
declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol)
|
declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirSimpleFunction.representsMainFunctionAllowingConflictingOverloads(): Boolean {
|
private fun FirSimpleFunction.representsMainFunctionAllowingConflictingOverloads(session: FirSession): Boolean {
|
||||||
if (name != StandardNames.MAIN || !symbol.callableId.isTopLevel || !hasMainFunctionStatus) return false
|
if (name != StandardNames.MAIN || !symbol.callableId.isTopLevel || !hasMainFunctionStatus) return false
|
||||||
if (receiverParameter != null || typeParameters.isNotEmpty()) return false
|
if (receiverParameter != null || typeParameters.isNotEmpty()) return false
|
||||||
if (valueParameters.isEmpty()) return true
|
if (valueParameters.isEmpty()) return true
|
||||||
@@ -320,16 +330,19 @@ class FirDeclarationInspector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun areCompatibleMainFunctions(
|
private fun areCompatibleMainFunctions(
|
||||||
declaration1: FirDeclaration, file1: FirFile, declaration2: FirDeclaration, file2: FirFile?,
|
declaration1: FirDeclaration, file1: FirFile,
|
||||||
|
declaration2: FirDeclaration, file2: FirFile?,
|
||||||
|
session: FirSession,
|
||||||
) = file1 != file2
|
) = file1 != file2
|
||||||
&& declaration1 is FirSimpleFunction
|
&& declaration1 is FirSimpleFunction
|
||||||
&& declaration2 is FirSimpleFunction
|
&& declaration2 is FirSimpleFunction
|
||||||
&& declaration1.representsMainFunctionAllowingConflictingOverloads()
|
&& declaration1.representsMainFunctionAllowingConflictingOverloads(session)
|
||||||
&& declaration2.representsMainFunctionAllowingConflictingOverloads()
|
&& declaration2.representsMainFunctionAllowingConflictingOverloads(session)
|
||||||
|
|
||||||
private fun isOverloadable(
|
private fun isOverloadable(
|
||||||
declaration: FirDeclaration,
|
declaration: FirDeclaration,
|
||||||
conflicting: FirDeclaration,
|
conflicting: FirDeclaration,
|
||||||
|
session: FirSession,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (isExpectAndActual(declaration, conflicting)) return true
|
if (isExpectAndActual(declaration, conflicting)) return true
|
||||||
|
|
||||||
@@ -342,8 +355,6 @@ class FirDeclarationInspector(
|
|||||||
session.declarationOverloadabilityHelper.isOverloadable(declaration, conflicting)
|
session.declarationOverloadabilityHelper.isOverloadable(declaration, conflicting)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks for redeclarations of value and type parameters, and local variables. */
|
/** Checks for redeclarations of value and type parameters, and local variables. */
|
||||||
fun checkForLocalRedeclarations(elements: List<FirElement>, context: CheckerContext, reporter: DiagnosticReporter) {
|
fun checkForLocalRedeclarations(elements: List<FirElement>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
if (elements.size <= 1) return
|
if (elements.size <= 1) return
|
||||||
|
|||||||
+6
-5
@@ -9,8 +9,10 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind
|
|||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.FirNameConflictsTrackerComponent
|
import org.jetbrains.kotlin.fir.FirNameConflictsTrackerComponent
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationCollector
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkForLocalRedeclarations
|
import org.jetbrains.kotlin.fir.analysis.checkers.checkForLocalRedeclarations
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.collectClassMembers
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.collectTopLevel
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
@@ -27,7 +29,7 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is FirFile -> {
|
is FirFile -> {
|
||||||
val inspector = FirDeclarationInspector(context)
|
val inspector = FirDeclarationCollector<FirDeclaration>(context)
|
||||||
checkFile(declaration, inspector, context)
|
checkFile(declaration, inspector, context)
|
||||||
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
|
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
|
||||||
}
|
}
|
||||||
@@ -35,7 +37,7 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
if (declaration.source?.kind !is KtFakeSourceElementKind) {
|
if (declaration.source?.kind !is KtFakeSourceElementKind) {
|
||||||
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
|
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
|
||||||
}
|
}
|
||||||
val inspector = FirDeclarationInspector(context)
|
val inspector = FirDeclarationCollector<FirDeclaration>(context)
|
||||||
inspector.collectClassMembers(declaration)
|
inspector.collectClassMembers(declaration)
|
||||||
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
|
reportConflicts(reporter, context, inspector.declarationConflictingSymbols)
|
||||||
}
|
}
|
||||||
@@ -46,7 +48,6 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
|
checkForLocalRedeclarations(declaration.typeParameters, context, reporter)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ object FirConflictsDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkFile(file: FirFile, inspector: FirDeclarationInspector, context: CheckerContext) {
|
private fun checkFile(file: FirFile, inspector: FirDeclarationCollector<FirDeclaration>, context: CheckerContext) {
|
||||||
val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
|
val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) {
|
||||||
FirPackageMemberScope(file.packageFqName, context.sessionHolder.session)
|
FirPackageMemberScope(file.packageFqName, context.sessionHolder.session)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user