diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt index f2339f2aebf..9006621e920 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationInspector.kt @@ -188,9 +188,27 @@ interface FirDeclarationPresenter { append(']') appendRepresentation(it.symbol.classId) } + + fun represent(it: FirConstructor, owner: FirRegularClass) = buildString { + append('<') + it.typeParameters.forEach { + appendRepresentation(it) + append(',') + } + append('>') + append('[') + append(']') + appendRepresentation(owner.symbol.classId) + append('(') + it.valueParameters.forEach { + appendRepresentation(it) + append(',') + } + append(')') + } } -private class FirDefaultDeclarationPresenter : FirDeclarationPresenter +internal class FirDefaultDeclarationPresenter : FirDeclarationPresenter private val NO_NAME_PROVIDED = Name.special("") @@ -209,49 +227,35 @@ private fun FirDeclaration.isCollectable() = when (this) { /** * Collects FirDeclarations for further analysis. */ -class FirDeclarationInspector( - private val presenter: FirDeclarationPresenter = FirDefaultDeclarationPresenter() +open class FirDeclarationInspector( + protected val presenter: FirDeclarationPresenter = FirDefaultDeclarationPresenter() ) { val otherDeclarations = mutableMapOf>() val functionDeclarations = mutableMapOf>() fun collect(declaration: FirDeclaration) { - if (!declaration.isCollectable()) { - return + when { + !declaration.isCollectable() -> {} + declaration is FirSimpleFunction -> collectFunction(presenter.represent(declaration), declaration) + declaration is FirRegularClass -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration) + declaration is FirTypeAlias -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration) + declaration is FirProperty -> collectNonFunctionDeclaration(presenter.represent(declaration), declaration) } - - if (declaration is FirSimpleFunction) { - return collectFunction(declaration) - } - - val key = when (declaration) { - is FirRegularClass -> presenter.represent(declaration) - is FirTypeAlias -> presenter.represent(declaration) - is FirProperty -> presenter.represent(declaration) - else -> return - } - - var value = otherDeclarations[key] - - if (value == null) { - value = mutableListOf() - otherDeclarations[key] = value - } - - value.add(declaration) } - private fun collectFunction(declaration: FirSimpleFunction) { - val key = presenter.represent(declaration) - var value = functionDeclarations[key] - - if (value == null) { - value = mutableListOf() - functionDeclarations[key] = value + protected open fun collectNonFunctionDeclaration(key: String, declaration: FirDeclaration): MutableList = + otherDeclarations.getOrPut(key) { + mutableListOf() + }.also { + it.add(declaration) } - value.add(declaration) - } + protected open fun collectFunction(key: String, declaration: FirSimpleFunction): MutableList = + functionDeclarations.getOrPut(key) { + mutableListOf() + }.also { + it.add(declaration) + } fun contains(declaration: FirDeclaration) = when (declaration) { is FirSimpleFunction -> presenter.represent(declaration) in functionDeclarations diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsChecker.kt index c408453b811..b08fef18b4b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirConflictsChecker.kt @@ -5,19 +5,208 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration -import org.jetbrains.kotlin.fir.FirSymbolOwner +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationInspector +import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.declarations.* -import org.jetbrains.kotlin.fir.lookupTracker +import org.jetbrains.kotlin.fir.resolve.firProvider +import org.jetbrains.kotlin.fir.scopes.PACKAGE_MEMBER +import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol +import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.SmartSet object FirConflictsChecker : FirBasicDeclarationChecker() { + + private class DeclarationInspector : FirDeclarationInspector() { + + val declarationConflictingSymbols: HashMap>> = hashMapOf() + + override fun collectNonFunctionDeclaration(key: String, declaration: FirDeclaration): MutableList = + super.collectNonFunctionDeclaration(key, declaration).also { + collectLocalConflicts(declaration, it) + } + + override fun collectFunction(key: String, declaration: FirSimpleFunction): MutableList = + super.collectFunction(key, declaration).also { + collectLocalConflicts(declaration, it) + } + + private fun collectLocalConflicts(declaration: FirDeclaration, conflicting: List) { + val localConflicts = SmartSet.create>() + for (otherDeclaration in conflicting) { + if (otherDeclaration is FirSymbolOwner<*>) { + if (otherDeclaration != declaration && declaration is FirSymbolOwner<*> && + !isExpectAndActual(declaration, otherDeclaration) + ) { + localConflicts.add(otherDeclaration.symbol) + declarationConflictingSymbols.getOrPut(otherDeclaration) { SmartSet.create() }.add(declaration.symbol) + } + } + } + declarationConflictingSymbols[declaration] = localConflicts + } + + private fun isExpectAndActual(declaration1: FirDeclaration, declaration2: FirDeclaration): Boolean { + if (declaration1 !is FirMemberDeclaration) return false + if (declaration2 !is FirMemberDeclaration) return false + return (declaration1.status.isExpect && declaration2.status.isActual) || + (declaration1.status.isActual && declaration2.status.isExpect) + } + + private fun areCompatibleMainFunctions( + declaration1: FirDeclaration, file1: FirFile, declaration2: FirDeclaration, file2: FirFile? + ): Boolean { + // TODO: proper main function detector + if (declaration1 !is FirSimpleFunction || declaration2 !is FirSimpleFunction) return false + if (declaration1.name.asString() != "main" || declaration2.name.asString() != "main") return false + return file1 != file2 + } + + private fun collectExternalConflict( + declaration: FirDeclaration, + declarationPresentation: String, + containingFile: FirFile, + conflictingSymbol: AbstractFirBasedSymbol<*>, + conflictingPresentation: String?, + conflictingFile: FirFile?, + session: FirSession + ) { + val conflicting = conflictingSymbol.fir as? FirDeclaration ?: return + if (declaration.session.moduleInfo != conflicting.session.moduleInfo) return + val actualConflictingPresentation = conflictingPresentation ?: presenter.represent(conflicting) + if (conflicting == declaration || actualConflictingPresentation != declarationPresentation) return + val actualConflictingFile = + conflictingFile ?: when (conflictingSymbol) { + is FirClassLikeSymbol<*> -> session.firProvider.getFirClassifierContainerFileIfAny(conflictingSymbol) + is FirCallableSymbol<*> -> session.firProvider.getFirCallableContainerFile(conflictingSymbol) + else -> null + } + if (containingFile == actualConflictingFile) return // TODO: rewrite local decls checker to the same logic and then remove the check + if (areCompatibleMainFunctions(declaration, containingFile, conflicting, actualConflictingFile)) return + if (isExpectAndActual(declaration, conflicting)) return + if (conflicting is FirMemberDeclaration && !(conflicting is FirSymbolOwner<*> && + session.visibilityChecker.isVisible(conflicting, session, containingFile, emptyList(), null)) + ) { + return + } + declarationConflictingSymbols.getOrPut(declaration) { SmartSet.create() }.add(conflictingSymbol) + } + + fun collectWithExternalConflicts( + declaration: FirDeclaration, + containingFile: FirFile, + session: FirSession, + packageMemberScope: FirPackageMemberScope + ) { + collect(declaration) + var declarationName: Name? = null + val declarationPresentation = presenter.represent(declaration) ?: return + + when (declaration) { + is FirSimpleFunction -> { + declarationName = declaration.name + if (!declarationName.isSpecial) { + packageMemberScope.processFunctionsByName(declarationName) { + collectExternalConflict( + declaration, declarationPresentation, containingFile, it, null, null, session + ) + } + packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ -> + val classWithSameName = symbol.fir as? FirRegularClass + classWithSameName?.onConstructors { constructor -> + collectExternalConflict( + declaration, declarationPresentation, containingFile, + constructor.symbol, presenter.represent(constructor, classWithSameName), null, + session + ) + } + } + } + } + is FirVariable<*> -> { + declarationName = declaration.name + if (!declarationName.isSpecial) { + packageMemberScope.processPropertiesByName(declarationName) { + collectExternalConflict( + declaration, declarationPresentation, containingFile, it, null, null, session + ) + } + } + } + is FirRegularClass -> { + declarationName = declaration.name + + if (!declarationName.isSpecial) { + packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ -> + collectExternalConflict( + declaration, declarationPresentation, containingFile, symbol, null, null, session + ) + } + declaration.onConstructors { constructor -> + packageMemberScope.processFunctionsByName(declarationName!!) { + collectExternalConflict( + constructor, presenter.represent(constructor, declaration), containingFile, + it, null, null, session + ) + } + } + + session.nameConflictsTracker?.let { it as? FirNameConflictsTracker } + ?.redeclaredClassifiers?.get(declaration.symbol.classId)?.forEach { + collectExternalConflict( + declaration, + declarationPresentation, + containingFile, + it.classifier, + null, + it.file, + session + ) + } + } + } + is FirTypeAlias -> { + declarationName = declaration.name + if (!declarationName.isSpecial) { + packageMemberScope.processClassifiersByNameWithSubstitution(declarationName) { symbol, _ -> + collectExternalConflict( + declaration, declarationPresentation, containingFile, symbol, null, null, session + ) + } + session.nameConflictsTracker?.let { it as? FirNameConflictsTracker } + ?.redeclaredClassifiers?.get(declaration.symbol.classId)?.forEach { + collectExternalConflict( + declaration, + declarationPresentation, + containingFile, + it.classifier, + null, + it.file, + session + ) + } + } + } + } + if (declarationName != null) { + session.lookupTracker?.recordLookup( + declarationName, containingFile.packageFqName.asString(), declaration.source, containingFile.source + ) + } + } + } + override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { - val inspector = FirDeclarationInspector() + val inspector = DeclarationInspector() when (declaration) { is FirFile -> checkFile(declaration, inspector, context) @@ -25,48 +214,80 @@ object FirConflictsChecker : FirBasicDeclarationChecker() { else -> return } - inspector.functionDeclarations.forEachNonSingle { it, symbols -> - reporter.reportOn(it.source, FirErrors.CONFLICTING_OVERLOADS, symbols, context) - } - - inspector.otherDeclarations.forEachNonSingle { it, symbols -> - reporter.reportOn(it.source, FirErrors.REDECLARATION, symbols, context) - } - } - - private fun Map>.forEachNonSingle(action: (FirDeclaration, Collection>) -> Unit) { - for (value in values) { - if (value.size > 1) { - val symbols = value.mapNotNull { (it as? FirSymbolOwner<*>)?.symbol } - - value.forEach { - action(it, symbols) + inspector.declarationConflictingSymbols.forEach { (declaration, symbols) -> + when { + symbols.isEmpty() -> {} + declaration is FirSimpleFunction || declaration is FirConstructor -> { + reporter.reportOn(declaration.source, FirErrors.CONFLICTING_OVERLOADS, symbols, context) + } + else -> { + reporter.reportOn(declaration.source, FirErrors.REDECLARATION, symbols, context) } } } } - private fun checkFile(file: FirFile, inspector: FirDeclarationInspector, context: CheckerContext) { - val lookupTracker = context.session.lookupTracker + private fun checkFile(file: FirFile, inspector: DeclarationInspector, context: CheckerContext) { + val packageMemberScope: FirPackageMemberScope = context.sessionHolder.scopeSession.getOrBuild(file.packageFqName, PACKAGE_MEMBER) { + FirPackageMemberScope(file.packageFqName, context.sessionHolder.session) + } for (topLevelDeclaration in file.declarations) { - inspector.collect(topLevelDeclaration) - if (lookupTracker != null) { - when (topLevelDeclaration) { - is FirSimpleFunction -> topLevelDeclaration.name - is FirVariable<*> -> topLevelDeclaration.name - is FirRegularClass -> topLevelDeclaration.name - is FirTypeAlias -> topLevelDeclaration.name - else -> null - }?.let { - lookupTracker.recordLookup(it, file.packageFqName.asString(), topLevelDeclaration.source, file.source) - } - } + inspector.collectWithExternalConflicts(topLevelDeclaration, file, context.session, packageMemberScope) } } - private fun checkRegularClass(declaration: FirRegularClass, inspector: FirDeclarationInspector) { + private fun checkRegularClass(declaration: FirRegularClass, inspector: DeclarationInspector) { for (it in declaration.declarations) { inspector.collect(it) } } } + +private fun FirDeclarationPresenter.represent(declaration: FirDeclaration): String? = + when (declaration) { + is FirSimpleFunction -> represent(declaration) + is FirRegularClass -> represent(declaration) + is FirTypeAlias -> represent(declaration) + is FirProperty -> represent(declaration) + else -> null + } + +class FirNameConflictsTracker : FirNameConflictsTrackerComponent() { + + data class ClassifierWithFile( + val classifier: FirClassLikeSymbol<*>, + val file: FirFile? + ) + + val redeclaredClassifiers = HashMap>() + + override fun registerClassifierRedeclaration( + classId: ClassId, + newSymbol: FirClassLikeSymbol<*>, newSymbolFile: FirFile, + prevSymbol: FirClassLikeSymbol<*>, prevSymbolFile: FirFile? + ) { + redeclaredClassifiers.merge( + classId, linkedSetOf(ClassifierWithFile(newSymbol, newSymbolFile), ClassifierWithFile(prevSymbol, prevSymbolFile)) + ) { a, b -> a + b } + } +} + +private fun FirDeclaration.onConstructors(action: (ctor: FirConstructor) -> Unit) { + + class ClassConstructorVisitor : FirVisitorVoid() { + override fun visitElement(element: FirElement) {} + + override fun visitConstructor(constructor: FirConstructor) { + action(constructor) + } + + override fun visitDeclarationStatus(declarationStatus: FirDeclarationStatus) {} + override fun visitRegularClass(regularClass: FirRegularClass) {} + override fun visitProperty(property: FirProperty) {} + override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {} + } + + acceptChildren(ClassConstructorVisitor()) +} + + diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt index 47dcb9dcfc3..331af0b92d2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/FirDiagnosticsCollector.kt @@ -9,7 +9,7 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.resolve.ScopeSession object FirDiagnosticsCollector { - fun create(session: FirSession, scopeSession: ScopeSession = ScopeSession()): SimpleDiagnosticsCollector { + fun create(session: FirSession, scopeSession: ScopeSession): SimpleDiagnosticsCollector { val collector = SimpleDiagnosticsCollector(session, scopeSession) collector.registerAllComponents() return collector diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt index 4423453a464..e606c8ec1b7 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/ComponentsContainers.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiFile import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.CheckersComponent +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirNameConflictsTracker import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.caches.FirThreadUnsafeCachesFactory import org.jetbrains.kotlin.fir.extensions.FirExtensionService @@ -61,6 +62,7 @@ fun FirSession.registerResolveComponents(lookupTracker: LookupTracker? = null) { register(FirQualifierResolver::class, FirQualifierResolverImpl(this)) register(FirTypeResolver::class, FirTypeResolverImpl(this)) register(CheckersComponent::class, CheckersComponent()) + register(FirNameConflictsTrackerComponent::class, FirNameConflictsTracker()) if (lookupTracker != null) { val firFileToPath: (FirSourceElement) -> String = { val psiSource = (it as? FirPsiSourceElement<*>) ?: TODO("Not implemented for non-FirPsiSourceElement") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirNameConflictsTrackerComponent.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirNameConflictsTrackerComponent.kt new file mode 100644 index 00000000000..094f09eaaac --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirNameConflictsTrackerComponent.kt @@ -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() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirProviderImpl.kt index d8b31e04cba..5b2fe3734ec 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirProviderImpl.kt @@ -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>, 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>() { - override fun visitElement(element: FirElement, data: Pair) {} + private object FirRecorder : FirDefaultVisitor() { + override fun visitElement(element: FirElement, data: FirRecorderData) {} - override fun visitRegularClass(regularClass: FirRegularClass, data: Pair) { + 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) { + 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 + data: FirRecorderData ) { val symbol = propertyAccessor.symbol - val (state, file) = data - state.callableContainerMap[symbol] = file + data.state.callableContainerMap[symbol] = data.file } private inline fun , S : FirCallableSymbol> registerCallable( symbol: S, - data: Pair, + data: FirRecorderData, map: MutableMap> ) { 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) { + 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) { + 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) { + 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) { + 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 } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt index 8678c3a69bc..f9327fe46e3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/Scopes.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.name.FqName private val INVISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey() private val VISIBLE_DEFAULT_STAR_IMPORT = scopeSessionKey() private val DEFAULT_SIMPLE_IMPORT = scopeSessionKey() -private val PACKAGE_MEMBER = scopeSessionKey() +val PACKAGE_MEMBER = scopeSessionKey() private val ALL_IMPORTS = scopeSessionKey() private class ListStorageFirScope(val result: List) : FirScope() diff --git a/compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt b/compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt index aff7e8872c4..ee499ee0a9a 100644 --- a/compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt +++ b/compiler/testData/codegen/box/compileKotlinAgainstKotlin/expectClassActualTypeAlias.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: NATIVE // !LANGUAGE: +MultiPlatformProjects // MODULE: lib diff --git a/compiler/testData/codegen/box/multiplatform/annotationsViaActualTypeAliasFromBinary.kt b/compiler/testData/codegen/box/multiplatform/annotationsViaActualTypeAliasFromBinary.kt index 095307c0718..27fb9a98d80 100644 --- a/compiler/testData/codegen/box/multiplatform/annotationsViaActualTypeAliasFromBinary.kt +++ b/compiler/testData/codegen/box/multiplatform/annotationsViaActualTypeAliasFromBinary.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // TARGET_BACKEND: JVM // !LANGUAGE: +MultiPlatformProjects // WITH_REFLECT diff --git a/compiler/testData/diagnostics/tests/redeclarations/ClassRedeclarationInDifferentFiles.fir.kt b/compiler/testData/diagnostics/tests/redeclarations/ClassRedeclarationInDifferentFiles.fir.kt index c6b6cfd77f9..adfd5421eed 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/ClassRedeclarationInDifferentFiles.fir.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/ClassRedeclarationInDifferentFiles.fir.kt @@ -1,11 +1,11 @@ // FILE: f1.kt package test -class A +class A class F1 // FILE: f2.kt package test -class A +class A class F2 \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.fir.kt b/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.fir.kt deleted file mode 100644 index 0e47fe33efd..00000000000 --- a/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.fir.kt +++ /dev/null @@ -1,10 +0,0 @@ -// FILE: test1.kt -class A -class B(val x: Int) { - constructor(x: Int, y: Int): this(x + y) -} - -// FILE: test2.kt -fun A() {} -fun B(x: Int) = x -fun B(x: Int, y: Int) = x + y \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.kt b/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.kt index ea1aab8e583..d2ba882c004 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/FunVsCtorInDifferentFiles.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // FILE: test1.kt class A class B(val x: Int) { diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.fir.kt b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.fir.kt index 2e34762bb74..676291d6c5d 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.fir.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclarationInMultiFile.fir.kt @@ -1,9 +1,9 @@ // FILE: a.kt -val a : Int = 1 -fun f() { +val a : Int = 1 +fun f() { } // FILE: b.kt -val a : Int = 1 -fun f() { +val a : Int = 1 +fun f() { } diff --git a/compiler/testData/diagnostics/tests/redeclarations/RedeclaringPrivateToFile.fir.kt b/compiler/testData/diagnostics/tests/redeclarations/RedeclaringPrivateToFile.fir.kt index 0d4d6ac0d36..938236dd0c0 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/RedeclaringPrivateToFile.fir.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/RedeclaringPrivateToFile.fir.kt @@ -7,8 +7,8 @@ interface B : A private fun validFun() {} private val validVal = 1 -private fun invalidFun0() {} -private val invalidProp0 = 1 +private fun invalidFun0() {} +private val invalidProp0 = 1 // NB invalidFun0 and invalidProp0 are conflicting overloads, since the following is an ambiguity: fun useInvalidFun0() = invalidFun0() @@ -20,7 +20,7 @@ fun useInvalidProp0() = invalidProp0 private fun invalidFun2() {} public fun invalidFun2() {} -public fun invalidFun3() {} +public fun invalidFun3() {} private fun invalidFun4() {} public fun invalidFun4() {} @@ -34,16 +34,16 @@ package a private fun validFun() {} private val validVal = 1 -private fun invalidFun0() {} +private fun invalidFun0() {} -private val invalidProp0 = 1 +private val invalidProp0 = 1 -internal fun invalidFun3() {} -internal fun invalidFun4() {} +internal fun invalidFun3() {} +internal fun invalidFun4() {} // FILE: c.kt package a public fun invalidFun0() {} -public val invalidProp0 = 1 \ No newline at end of file +public val invalidProp0 = 1 diff --git a/compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.fir.kt b/compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.fir.kt index 453f0be155c..3f2237e17a2 100644 --- a/compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.fir.kt +++ b/compiler/testData/diagnostics/tests/redeclarations/TypeAliasVsClass.fir.kt @@ -15,4 +15,4 @@ class Outer { } // FILE: file2.kt -typealias SomeClass = Any \ No newline at end of file +typealias SomeClass = Any diff --git a/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt b/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt index 11605605936..740fcab3ee4 100644 --- a/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt +++ b/compiler/testData/diagnostics/tests/typealias/privateInFile.fir.kt @@ -18,5 +18,5 @@ private val test1co: C.Companion = C private val test2: TA = TA() private val test2co = TA -private class C -private typealias TA = Int +private class C +private typealias TA = Int diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt index 0ac7239eeca..383d7b13d72 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/AbstractFirDiagnosticTest.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.dfa.cfg.FirControlFlowGraphRenderVisitor import org.jetbrains.kotlin.fir.resolve.transformers.createAllCompilerResolveProcessors import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol @@ -273,7 +274,7 @@ abstract class AbstractFirDiagnosticsTest : AbstractFirBaseDiagnosticsTest() { } private fun createCollector(session: FirSession): AbstractDiagnosticCollector { - return FirDiagnosticsCollector.create(session) + return FirDiagnosticsCollector.create(session, ScopeSession()) // seems this class is obsolete, so do not care about correctness of the scope session here } private fun checkCfgDump(testDataFile: File, firFiles: List) { diff --git a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-without-an-explicit-receiver/p-5/neg/2.4.fir.kt b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-without-an-explicit-receiver/p-5/neg/2.4.fir.kt index b51a49349ff..53320a63cf1 100644 --- a/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-without-an-explicit-receiver/p-5/neg/2.4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/linked/overload-resolution/building-the-overload-candidate-set-ocs/call-without-an-explicit-receiver/p-5/neg/2.4.fir.kt @@ -8,7 +8,7 @@ package testsCase1 import libPackageCase1.* import libPackageCase1Explicit.emptyArray -fun Case1.emptyArray(): Array = TODO() +fun Case1.emptyArray(): Array = TODO() class Case1(){ @@ -33,7 +33,7 @@ public fun emptyArray(): Array = TODO() // FILE: LibtestsPack1.kt // TESTCASE NUMBER: 1 package testsCase1 -fun Case1.emptyArray(): Array = TODO() +fun Case1.emptyArray(): Array = TODO() public fun emptyArray(): Array = TODO() @@ -46,7 +46,7 @@ package testsCase2 import libPackageCase2.* import libPackageCase2Explicit.emptyArray -fun Case2.emptyArray(): Array = TODO() +fun Case2.emptyArray(): Array = TODO() class Case2(){ @@ -77,6 +77,6 @@ public fun emptyArray(): Array = TODO() // FILE: LibtestsPack2.kt // TESTCASE NUMBER: 2 package testsCase2 -fun Case2.emptyArray(): Array = TODO() +fun Case2.emptyArray(): Array = TODO() public fun emptyArray(): Array = TODO() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/3.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/3.fir.kt index 6b52e7f78bb..91c78d22399 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/3.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/3.fir.kt @@ -5,8 +5,6 @@ annotation class Ann(val x: Int) // TESTCASE NUMBER: 1 -class Inv - fun foo(i: Inv<@Ann(unresolved_reference) String>) {} // TESTCASE NUMBER: 2 diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/4.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/4.fir.kt index 5186cbcaf64..34d1a6060dc 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/4.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/annotations/type-annotations/neg/4.fir.kt @@ -2,6 +2,4 @@ @Target(AnnotationTarget.TYPE) annotation class Ann(val x: Int) -class Inv - fun case_1(): Inv<@Ann(unresolved_reference) String> = TODO() diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt index de341abcac6..8b0ec28fd57 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.fir.kt @@ -183,8 +183,8 @@ fun case_13(x: otherpackage.Case13?) = if ((x == null !is Boolean) !== true) { throw Exception() } else { - x - x.equals(x) + x + x.equals(x) } // TESTCASE NUMBER: 14