[FIR] Fix the TODO in FirConflictsHelpers

According to
https://github.com/Kotlin/KEEP/blob/master/proposals/enhancing-main-convention.md#rules-and-semantics,
only main function without args may avoid
`CONFLICTING_OVERLOADS`, but since the
jps/jps-plugin/testData/incremental/withJava/other/mainRedeclaration
test dates back to 2015, this is not the
current behavior.
This commit is contained in:
Nikolay Lunyak
2023-06-28 11:52:22 +03:00
committed by Space Team
parent 3014c7b353
commit 8541143d6f
5 changed files with 69 additions and 9 deletions
@@ -6,15 +6,22 @@
package org.jetbrains.kotlin.fir.analysis.checkers
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentation
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentationAfterCallableId
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirMethodOfAnyImplementedInInterfaceChecker.appendRepresentationBeforeCallableId
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.impl.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.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
@@ -22,9 +29,9 @@ import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.util.ListMultimap
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.SmartSet
@@ -32,6 +39,34 @@ internal class FirDefaultDeclarationPresenter : FirDeclarationPresenter
private val NO_NAME_PROVIDED = Name.special("<no name provided>")
private val MAIN_FUNCTION_SHAPES = setOf(
"<>[]():kotlin/Unit",
"<>[](kotlin/Array<kotlin/String,>,):kotlin/Unit",
"<>[](vararg kotlin/String,):kotlin/Unit",
)
val DEFAULT_STATUS_FOR_NORMAL_MAIN_FUNCTION = DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
private val FirSimpleFunction.hasMainFunctionStatus
get() = when (status.modifiersRepresentation) {
DEFAULT_STATUS_FOR_NORMAL_MAIN_FUNCTION.modifiersRepresentation,
DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION.modifiersRepresentation -> true
else -> false
}
private val CallableId.isTopLevel get() = className == null
private val FirSimpleFunction.representsMainFunctionAllowingConflictingOverloads
get(): Boolean = when {
name != StandardNames.MAIN || !symbol.callableId.isTopLevel || !hasMainFunctionStatus -> false
else -> buildString {
appendRepresentationBeforeCallableId(this@representsMainFunctionAllowingConflictingOverloads)
appendRepresentationAfterCallableId(this@representsMainFunctionAllowingConflictingOverloads)
append(':')
appendRepresentation(returnTypeRef)
} in MAIN_FUNCTION_SHAPES
}
// - see testEnumValuesValueOf.
// it generates a static function that has
// the same signature as the function defined
@@ -211,12 +246,11 @@ class FirDeclarationInspector {
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
}
) = file1 != file2
&& declaration1 is FirSimpleFunction
&& declaration2 is FirSimpleFunction
&& declaration1.representsMainFunctionAllowingConflictingOverloads
&& declaration2.representsMainFunctionAllowingConflictingOverloads
private fun collectExternalConflict(
declaration: FirDeclaration,
@@ -158,7 +158,7 @@ interface FirDeclarationPresenter {
}
}
fun represent(it: FirSimpleFunction) = buildString {
fun StringBuilder.appendRepresentationBeforeCallableId(it: FirSimpleFunction) {
it.contextReceivers.forEach {
appendRepresentation(it)
append(',')
@@ -175,7 +175,9 @@ interface FirDeclarationPresenter {
}
append(']')
appendOperatorTag(it)
appendRepresentation(it.symbol.callableId)
}
fun StringBuilder.appendRepresentationAfterCallableId(it: FirSimpleFunction) {
append('(')
it.valueParameters.forEach {
appendRepresentation(it)
@@ -184,6 +186,12 @@ interface FirDeclarationPresenter {
append(')')
}
fun represent(it: FirSimpleFunction) = buildString {
appendRepresentationBeforeCallableId(it)
appendRepresentation(it.symbol.callableId)
appendRepresentationAfterCallableId(it)
}
fun represent(it: FirTypeAlias) = buildString {
append('[')
append(']')
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirPureAbstractElement
import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl.Modifier.*
@@ -22,6 +23,9 @@ open class FirDeclarationStatusImpl(
override val source: KtSourceElement? get() = null
protected var flags: Int = HAS_STABLE_PARAMETER_NAMES.mask
@FirImplementationDetail
internal val rawFlags get() = flags
operator fun get(modifier: Modifier): Boolean = (flags and modifier.mask) != 0
operator fun set(modifier: Modifier, value: Boolean) {
@@ -182,3 +186,10 @@ open class FirDeclarationStatusImpl(
return FirResolvedDeclarationStatusImpl(visibility, modality, effectiveVisibility, flags)
}
}
@OptIn(FirImplementationDetail::class)
val FirDeclarationStatus.modifiersRepresentation: Any
get() = when (this) {
is FirDeclarationStatusImpl -> rawFlags
else -> error("Generating modifier representations for ${this::class.simpleName} is not supported")
}
@@ -28,6 +28,11 @@ class FirResolvedDeclarationStatusImpl(
Modality.FINAL,
EffectiveVisibility.Public
).apply { isSuspend = true }
val DEFAULT_STATUS_FOR_SUSPEND_MAIN_FUNCTION = FirResolvedDeclarationStatusImpl(
Visibilities.Public,
Modality.FINAL,
EffectiveVisibility.Public
).apply { isSuspend = true }
}
internal constructor(
@@ -36,6 +36,8 @@ object StandardNames {
@JvmField val NAME = Name.identifier("name")
@JvmField val MAIN = Name.identifier("main")
@JvmField val NEXT_CHAR = Name.identifier("nextChar")
@JvmField val IMPLICIT_LAMBDA_PARAMETER_NAME = Name.identifier("it")