FIR: Reimplement conflicts checker to detect conflicts in different files

also pass correct ScopeSession to checkers
fixes some IC tests
This commit is contained in:
Ilya Chernikov
2021-02-17 21:49:07 +01:00
parent 3e458a1efb
commit 51a1cec08b
21 changed files with 379 additions and 144 deletions
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2021 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.fir
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.name.ClassId
abstract class FirNameConflictsTrackerComponent : FirSessionComponent {
abstract fun registerClassifierRedeclaration(
classId: ClassId,
newSymbol: FirClassLikeSymbol<*>, newSymbolFile: FirFile,
prevSymbol: FirClassLikeSymbol<*>, prevSymbolFile: FirFile?
)
}
val FirSession.nameConflictsTracker: FirNameConflictsTrackerComponent? by FirSession.nullableSessionComponentAccessor()
@@ -6,12 +6,9 @@
package org.jetbrains.kotlin.fir.resolve.providers.impl
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.originalIfFakeOverride
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirProviderInternals
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
@@ -62,7 +59,6 @@ class FirProviderImpl(val session: FirSession, val kotlinScopeProvider: KotlinSc
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
destination += (state.functionMap[CallableId(packageFqName, null, name)] ?: emptyList())
destination += (state.propertyMap[CallableId(packageFqName, null, name)] ?: emptyList())
}
@FirSymbolProviderInternals
@@ -83,12 +79,12 @@ class FirProviderImpl(val session: FirSession, val kotlinScopeProvider: KotlinSc
@FirProviderInternals
override fun recordGeneratedClass(owner: FirAnnotatedDeclaration, klass: FirRegularClass) {
klass.accept(FirRecorder, state to owner.file)
klass.accept(FirRecorder, FirRecorderData(state, owner.file, session.nameConflictsTracker))
}
@FirProviderInternals
override fun recordGeneratedMember(owner: FirAnnotatedDeclaration, klass: FirDeclaration) {
klass.accept(FirRecorder, state to owner.file)
klass.accept(FirRecorder, FirRecorderData(state, owner.file, session.nameConflictsTracker))
}
private val FirAnnotatedDeclaration.file: FirFile
@@ -101,73 +97,78 @@ class FirProviderImpl(val session: FirSession, val kotlinScopeProvider: KotlinSc
private fun recordFile(file: FirFile, state: State) {
val packageName = file.packageFqName
state.fileMap.merge(packageName, listOf(file)) { a, b -> a + b }
file.acceptChildren(FirRecorder, state to file)
file.acceptChildren(FirRecorder, FirRecorderData(state, file, session.nameConflictsTracker))
}
private class FirRecorderData(
val state: State,
val file: FirFile,
val nameConflictsTracker: FirNameConflictsTrackerComponent?
)
private object FirRecorder : FirDefaultVisitor<Unit, Pair<State, FirFile>>() {
override fun visitElement(element: FirElement, data: Pair<State, FirFile>) {}
private object FirRecorder : FirDefaultVisitor<Unit, FirRecorderData>() {
override fun visitElement(element: FirElement, data: FirRecorderData) {}
override fun visitRegularClass(regularClass: FirRegularClass, data: Pair<State, FirFile>) {
override fun visitRegularClass(regularClass: FirRegularClass, data: FirRecorderData) {
val classId = regularClass.symbol.classId
val (state, file) = data
state.classifierMap[classId] = regularClass
state.classifierContainerFileMap[classId] = file
val prevFile = data.state.classifierContainerFileMap.put(classId, data.file)
data.state.classifierMap.put(classId, regularClass)?.let {
data.nameConflictsTracker?.registerClassifierRedeclaration(classId, regularClass.symbol, data.file, it.symbol, prevFile)
}
if (!classId.isNestedClass && !classId.isLocal) {
state.classesInPackage.getOrPut(classId.packageFqName, ::mutableSetOf).add(classId.shortClassName)
data.state.classesInPackage.getOrPut(classId.packageFqName, ::mutableSetOf).add(classId.shortClassName)
}
regularClass.acceptChildren(this, data)
}
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Pair<State, FirFile>) {
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: FirRecorderData) {
val classId = typeAlias.symbol.classId
val (state, file) = data
state.classifierMap[classId] = typeAlias
state.classifierContainerFileMap[classId] = file
val prevFile = data.state.classifierContainerFileMap.put(classId, data.file)
data.state.classifierMap.put(classId, typeAlias)?.let {
data.nameConflictsTracker?.registerClassifierRedeclaration(classId, typeAlias.symbol, data.file, it.symbol, prevFile)
}
}
override fun visitPropertyAccessor(
propertyAccessor: FirPropertyAccessor,
data: Pair<State, FirFile>
data: FirRecorderData
) {
val symbol = propertyAccessor.symbol
val (state, file) = data
state.callableContainerMap[symbol] = file
data.state.callableContainerMap[symbol] = data.file
}
private inline fun <reified D : FirCallableMemberDeclaration<D>, S : FirCallableSymbol<D>> registerCallable(
symbol: S,
data: Pair<State, FirFile>,
data: FirRecorderData,
map: MutableMap<CallableId, List<S>>
) {
val callableId = symbol.callableId
val (state, file) = data
map.merge(callableId, listOf(symbol)) { a, b -> a + b }
state.callableContainerMap[symbol] = file
data.state.callableContainerMap[symbol] = data.file
}
override fun visitConstructor(constructor: FirConstructor, data: Pair<State, FirFile>) {
override fun visitConstructor(constructor: FirConstructor, data: FirRecorderData) {
val symbol = constructor.symbol
registerCallable(symbol, data, data.first.constructorMap)
registerCallable(symbol, data, data.state.constructorMap)
}
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: Pair<State, FirFile>) {
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: FirRecorderData) {
val symbol = simpleFunction.symbol
registerCallable(symbol, data, data.first.functionMap)
registerCallable(symbol, data, data.state.functionMap)
}
override fun visitProperty(property: FirProperty, data: Pair<State, FirFile>) {
override fun visitProperty(property: FirProperty, data: FirRecorderData) {
val symbol = property.symbol
registerCallable(symbol, data, data.first.propertyMap)
registerCallable(symbol, data, data.state.propertyMap)
property.getter?.let { visitPropertyAccessor(it, data) }
property.setter?.let { visitPropertyAccessor(it, data) }
}
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Pair<State, FirFile>) {
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: FirRecorderData) {
val symbol = enumEntry.symbol
val (state, file) = data
state.callableContainerMap[symbol] = file
data.state.callableContainerMap[symbol] = data.file
}
}
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.name.FqName
private val INVISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val VISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultStarImportingScope>()
private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey<DefaultImportPriority, FirDefaultSimpleImportingScope>()
private val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
val PACKAGE_MEMBER = scopeSessionKey<FqName, FirPackageMemberScope>()
private val ALL_IMPORTS = scopeSessionKey<FirFile, ListStorageFirScope>()
private class ListStorageFirScope(val result: List<FirScope>) : FirScope()