[FIR] Introduce FirDeclarationStatus.hasStableParameterNames

This flag is true by default but is set to false for

- Java methods and constructors
- interface delegation methods that delegate to Java

The NAMED_ARGUMENTS_NOT_ALLOWED logic is mostly refactored to use the
new flag though some custom logic remains for determining the correct
message and to work around a corner case with fake overrides.

The flag is (de)serialized from/to metadata. For backward compatibility
with K1, delegated methods to Java types are deserialized as stable.

^KT-40480 Fixed
This commit is contained in:
Kirill Rakhman
2023-02-03 12:08:17 +01:00
committed by Space Team
parent 152e63b198
commit 314784f435
29 changed files with 156 additions and 51 deletions
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fakeElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
@@ -560,20 +557,14 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
// for intersection/substitution overrides
originScope: FirTypeScope? = null
): ForbiddenNamedArgumentsTarget? {
if (this is FirConstructor && this.isPrimary) {
this.getContainingClass(session)?.let { containingClass ->
if (containingClass.classKind == ClassKind.ANNOTATION_CLASS) {
// Java annotation classes allow (actually require) named parameters.
return null
}
}
}
if (hasStableParameterNames) return null
return when (origin) {
FirDeclarationOrigin.Source, FirDeclarationOrigin.Precompiled, FirDeclarationOrigin.Library -> null
FirDeclarationOrigin.Delegated -> delegatedWrapperData?.wrapped?.getAsForbiddenNamedArgumentsTarget(session)
FirDeclarationOrigin.ImportedFromObjectOrStatic -> importedFromObjectOrStaticData?.original?.getAsForbiddenNamedArgumentsTarget(session)
is FirDeclarationOrigin.Java, FirDeclarationOrigin.Enhancement -> ForbiddenNamedArgumentsTarget.NON_KOTLIN_FUNCTION
FirDeclarationOrigin.SamConstructor -> null
FirDeclarationOrigin.ImportedFromObjectOrStatic ->
importedFromObjectOrStaticData?.original?.getAsForbiddenNamedArgumentsTarget(session)
FirDeclarationOrigin.IntersectionOverride, FirDeclarationOrigin.SubstitutionOverride -> {
var result: ForbiddenNamedArgumentsTarget? =
originalIfFakeOverride()?.getAsForbiddenNamedArgumentsTarget(session) ?: return null
@@ -587,25 +578,13 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
}
result
}
// referenced function of a Kotlin function type
FirDeclarationOrigin.BuiltIns -> runIf(dispatchReceiverClassLookupTagOrNull()?.isSomeFunctionType(session) == true) {
ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
}
FirDeclarationOrigin.Synthetic,
FirDeclarationOrigin.DynamicScope,
FirDeclarationOrigin.RenamedForOverride,
FirDeclarationOrigin.WrappedIntegerOperator,
FirDeclarationOrigin.ScriptCustomization,
FirDeclarationOrigin.BuiltIns -> ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
else -> ForbiddenNamedArgumentsTarget.NON_KOTLIN_FUNCTION
}
}
// TODO: handle functions with non-stable parameter names, see also
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.functionProto
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.constructorProto
fun FirFunction.getHasStableParameterNames(session: FirSession): Boolean = getAsForbiddenNamedArgumentsTarget(session) == null
@OptIn(ExperimentalContracts::class)
fun FirExpression?.isIntegerLiteralOrOperatorCall(): Boolean {
contract {