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
@@ -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("<no name provided>")
@@ -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<String, MutableList<FirDeclaration>>()
val functionDeclarations = mutableMapOf<String, MutableList<FirSimpleFunction>>()
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<FirDeclaration> =
otherDeclarations.getOrPut(key) {
mutableListOf()
}.also {
it.add(declaration)
}
value.add(declaration)
}
protected open fun collectFunction(key: String, declaration: FirSimpleFunction): MutableList<FirSimpleFunction> =
functionDeclarations.getOrPut(key) {
mutableListOf()
}.also {
it.add(declaration)
}
fun contains(declaration: FirDeclaration) = when (declaration) {
is FirSimpleFunction -> presenter.represent(declaration) in functionDeclarations
@@ -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<FirDeclaration, SmartSet<AbstractFirBasedSymbol<*>>> = hashMapOf()
override fun collectNonFunctionDeclaration(key: String, declaration: FirDeclaration): MutableList<FirDeclaration> =
super.collectNonFunctionDeclaration(key, declaration).also {
collectLocalConflicts(declaration, it)
}
override fun collectFunction(key: String, declaration: FirSimpleFunction): MutableList<FirSimpleFunction> =
super.collectFunction(key, declaration).also {
collectLocalConflicts(declaration, it)
}
private fun collectLocalConflicts(declaration: FirDeclaration, conflicting: List<FirDeclaration>) {
val localConflicts = SmartSet.create<AbstractFirBasedSymbol<*>>()
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<String, List<FirDeclaration>>.forEachNonSingle(action: (FirDeclaration, Collection<AbstractFirBasedSymbol<*>>) -> 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<ClassId, Set<ClassifierWithFile>>()
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())
}
@@ -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
@@ -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")
@@ -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()
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: NATIVE
// !LANGUAGE: +MultiPlatformProjects
// MODULE: lib
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// !LANGUAGE: +MultiPlatformProjects
// WITH_REFLECT
@@ -1,11 +1,11 @@
// FILE: f1.kt
package test
class A
<!REDECLARATION!>class A<!>
class F1
// FILE: f2.kt
package test
class A
<!REDECLARATION!>class A<!>
class F2
@@ -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
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: test1.kt
class <!CONFLICTING_OVERLOADS!>A<!>
class B<!CONFLICTING_OVERLOADS!>(val x: Int)<!> {
@@ -1,9 +1,9 @@
// FILE: a.kt
val a : Int = 1
fun f() {
<!REDECLARATION!>val a : Int = 1<!>
<!CONFLICTING_OVERLOADS!>fun f()<!> {
}
// FILE: b.kt
val a : Int = 1
fun f() {
<!REDECLARATION!>val a : Int = 1<!>
<!CONFLICTING_OVERLOADS!>fun f()<!> {
}
@@ -7,8 +7,8 @@ interface B : A
private fun validFun() {}
private val validVal = 1
private fun invalidFun0() {}
private val invalidProp0 = 1
<!CONFLICTING_OVERLOADS!>private fun invalidFun0()<!> {}
<!REDECLARATION!>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
<!CONFLICTING_OVERLOADS!>private fun invalidFun2()<!> {}
<!CONFLICTING_OVERLOADS!>public fun invalidFun2()<!> {}
public fun invalidFun3() {}
<!CONFLICTING_OVERLOADS!>public fun invalidFun3()<!> {}
<!CONFLICTING_OVERLOADS!>private fun invalidFun4()<!> {}
<!CONFLICTING_OVERLOADS!>public fun invalidFun4()<!> {}
@@ -34,16 +34,16 @@ package a
private fun validFun() {}
private val validVal = 1
private fun invalidFun0() {}
<!CONFLICTING_OVERLOADS!>private fun invalidFun0()<!> {}
private val invalidProp0 = 1
<!REDECLARATION!>private val invalidProp0 = 1<!>
internal fun invalidFun3() {}
internal fun invalidFun4() {}
<!CONFLICTING_OVERLOADS!>internal fun invalidFun3()<!> {}
<!CONFLICTING_OVERLOADS!>internal fun invalidFun4()<!> {}
// FILE: c.kt
package a
public fun invalidFun0() {}
public val invalidProp0 = 1
public val invalidProp0 = 1
@@ -15,4 +15,4 @@ class Outer {
}
// FILE: file2.kt
typealias SomeClass = Any
<!REDECLARATION!>typealias SomeClass = Any<!>
@@ -18,5 +18,5 @@ private val test1co: C.Companion = C
private val test2: TA = <!INAPPLICABLE_CANDIDATE!>TA<!>()
private val test2co = TA
private class C
private typealias TA = Int
<!REDECLARATION!>private class C<!>
<!REDECLARATION!>private typealias TA = Int<!>
@@ -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<FirFile>) {
@@ -8,7 +8,7 @@ package testsCase1
import libPackageCase1.*
import libPackageCase1Explicit.emptyArray
fun <T> Case1.emptyArray(): Array<T> = TODO()
<!CONFLICTING_OVERLOADS!>fun <T> Case1.emptyArray(): Array<T><!> = TODO()
class Case1(){
@@ -33,7 +33,7 @@ public fun <T> emptyArray(): Array<T> = TODO()
// FILE: LibtestsPack1.kt
// TESTCASE NUMBER: 1
package testsCase1
fun <T> Case1.emptyArray(): Array<T> = TODO()
<!CONFLICTING_OVERLOADS!>fun <T> Case1.emptyArray(): Array<T><!> = TODO()
public fun <T> emptyArray(): Array<T> = TODO()
@@ -46,7 +46,7 @@ package testsCase2
import libPackageCase2.*
import libPackageCase2Explicit.emptyArray
fun <T> Case2.emptyArray(): Array<T> = TODO()
<!CONFLICTING_OVERLOADS!>fun <T> Case2.emptyArray(): Array<T><!> = TODO()
class Case2(){
@@ -77,6 +77,6 @@ public fun <T> emptyArray(): Array<T> = TODO()
// FILE: LibtestsPack2.kt
// TESTCASE NUMBER: 2
package testsCase2
fun <T> Case2.emptyArray(): Array<T> = TODO()
<!CONFLICTING_OVERLOADS!>fun <T> Case2.emptyArray(): Array<T><!> = TODO()
public fun <T> emptyArray(): Array<T> = TODO()
@@ -5,8 +5,6 @@
annotation class Ann(val x: Int)
// TESTCASE NUMBER: 1
class Inv<T>
fun foo(i: Inv<@Ann(unresolved_reference) String>) {}
// TESTCASE NUMBER: 2
@@ -2,6 +2,4 @@
@Target(AnnotationTarget.TYPE)
annotation class Ann(val x: Int)
class Inv<T>
fun case_1(): Inv<@Ann(unresolved_reference) String> = TODO()
@@ -183,8 +183,8 @@ fun case_13(x: <!UNRESOLVED_REFERENCE!>otherpackage.Case13?<!>) =
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Can't resolve when expression")!>if ((x == null !is Boolean) !== true) {
throw Exception()
} else {
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found, for `otherpackage.Case13?`")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found, for `otherpackage.Case13?`")!>x<!>.<!AMBIGUITY!>equals<!>(x)
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>.<!AMBIGUITY!>equals<!>(x)
}<!>
// TESTCASE NUMBER: 14