diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt index 75bfe0df053..6a55a962e38 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConflictsHelpers.kt @@ -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("") +private val MAIN_FUNCTION_SHAPES = setOf( + "<>[]():kotlin/Unit", + "<>[](kotlin/Array,):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, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationPresenter.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationPresenter.kt index b4c88edf7bc..57152169462 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationPresenter.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirDeclarationPresenter.kt @@ -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(']') diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt index 242c32217a3..67debde3f7c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirDeclarationStatusImpl.kt @@ -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") + } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedDeclarationStatusImpl.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedDeclarationStatusImpl.kt index d19eb549546..b0128cb52ee 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedDeclarationStatusImpl.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/impl/FirResolvedDeclarationStatusImpl.kt @@ -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( diff --git a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt index 3bec03ab851..e7783246200 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/builtins/StandardNames.kt @@ -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")