[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:
committed by
Space Team
parent
152e63b198
commit
314784f435
+2
-2
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.CanNotCreateSymbolPoin
|
|||||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
|
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.fir.resolve.getHasStableParameterNames
|
import org.jetbrains.kotlin.fir.declarations.utils.hasStableParameterNames
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ internal class KtFirAnonymousFunctionSymbol(
|
|||||||
|
|
||||||
override val hasStableParameterNames: Boolean
|
override val hasStableParameterNames: Boolean
|
||||||
get() = withValidityAssertion {
|
get() = withValidityAssertion {
|
||||||
firSymbol.fir.getHasStableParameterNames(firSymbol.moduleData.session)
|
firSymbol.fir.hasStableParameterNames
|
||||||
}
|
}
|
||||||
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
|
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -24,8 +24,8 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
|||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.hasStableParameterNames
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||||
import org.jetbrains.kotlin.fir.resolve.getHasStableParameterNames
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ internal class KtFirConstructorSymbol(
|
|||||||
|
|
||||||
override val hasStableParameterNames: Boolean
|
override val hasStableParameterNames: Boolean
|
||||||
get() = withValidityAssertion {
|
get() = withValidityAssertion {
|
||||||
firSymbol.fir.getHasStableParameterNames(firSymbol.moduleData.session)
|
firSymbol.fir.hasStableParameterNames
|
||||||
}
|
}
|
||||||
|
|
||||||
override val visibility: Visibility get() = withValidityAssertion { firSymbol.visibility }
|
override val visibility: Visibility get() = withValidityAssertion { firSymbol.visibility }
|
||||||
|
|||||||
+1
-2
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.descriptors.Visibility
|
|||||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
import org.jetbrains.kotlin.fir.contracts.FirEffectDeclaration
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.getHasStableParameterNames
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
@@ -65,7 +64,7 @@ internal class KtFirFunctionSymbol(
|
|||||||
override val valueParameters: List<KtValueParameterSymbol> by cached { firSymbol.createKtValueParameters(builder) }
|
override val valueParameters: List<KtValueParameterSymbol> by cached { firSymbol.createKtValueParameters(builder) }
|
||||||
|
|
||||||
override val hasStableParameterNames: Boolean
|
override val hasStableParameterNames: Boolean
|
||||||
get() = withValidityAssertion { firSymbol.fir.getHasStableParameterNames(firSymbol.moduleData.session) }
|
get() = withValidityAssertion { firSymbol.fir.hasStableParameterNames }
|
||||||
|
|
||||||
override val annotationsList by cached {
|
override val annotationsList by cached {
|
||||||
KtFirAnnotationListForDeclaration.create(
|
KtFirAnnotationListForDeclaration.create(
|
||||||
|
|||||||
+2
-2
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtTypeParameterSymbol
|
|||||||
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
import org.jetbrains.kotlin.fir.resolve.getHasStableParameterNames
|
import org.jetbrains.kotlin.fir.declarations.utils.hasStableParameterNames
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
import org.jetbrains.kotlin.fir.symbols.impl.isExtension
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
@@ -54,7 +54,7 @@ internal class KtFirSamConstructorSymbol(
|
|||||||
|
|
||||||
override val hasStableParameterNames: Boolean
|
override val hasStableParameterNames: Boolean
|
||||||
get() = withValidityAssertion {
|
get() = withValidityAssertion {
|
||||||
firSymbol.fir.getHasStableParameterNames(firSymbol.moduleData.session)
|
firSymbol.fir.hasStableParameterNames
|
||||||
}
|
}
|
||||||
|
|
||||||
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
|
override val isExtension: Boolean get() = withValidityAssertion { firSymbol.isExtension }
|
||||||
|
|||||||
+12
@@ -22094,6 +22094,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForDelegationToJavaMethods.kt")
|
||||||
|
public void testDisallowForDelegationToJavaMethods() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForDelegationToJavaMethods.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForFunctionTypes.kt")
|
||||||
|
public void testDisallowForFunctionTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForFunctionTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("disallowForJavaConstructor.kt")
|
@TestMetadata("disallowForJavaConstructor.kt")
|
||||||
public void testDisallowForJavaConstructor() throws Exception {
|
public void testDisallowForJavaConstructor() throws Exception {
|
||||||
|
|||||||
+12
@@ -22100,6 +22100,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForDelegationToJavaMethods.kt")
|
||||||
|
public void testDisallowForDelegationToJavaMethods() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForDelegationToJavaMethods.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForFunctionTypes.kt")
|
||||||
|
public void testDisallowForFunctionTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForFunctionTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("disallowForJavaConstructor.kt")
|
@TestMetadata("disallowForJavaConstructor.kt")
|
||||||
public void testDisallowForJavaConstructor() throws Exception {
|
public void testDisallowForJavaConstructor() throws Exception {
|
||||||
|
|||||||
+12
@@ -22094,6 +22094,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForDelegationToJavaMethods.kt")
|
||||||
|
public void testDisallowForDelegationToJavaMethods() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForDelegationToJavaMethods.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForFunctionTypes.kt")
|
||||||
|
public void testDisallowForFunctionTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForFunctionTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("disallowForJavaConstructor.kt")
|
@TestMetadata("disallowForJavaConstructor.kt")
|
||||||
public void testDisallowForJavaConstructor() throws Exception {
|
public void testDisallowForJavaConstructor() throws Exception {
|
||||||
|
|||||||
+2
@@ -502,6 +502,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
|||||||
isTailRec = Flags.IS_TAILREC.get(flags)
|
isTailRec = Flags.IS_TAILREC.get(flags)
|
||||||
isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags)
|
isExternal = Flags.IS_EXTERNAL_FUNCTION.get(flags)
|
||||||
isSuspend = Flags.IS_SUSPEND.get(flags)
|
isSuspend = Flags.IS_SUSPEND.get(flags)
|
||||||
|
hasStableParameterNames = !Flags.IS_FUNCTION_WITH_NON_STABLE_PARAMETER_NAMES.get(flags)
|
||||||
}
|
}
|
||||||
this.symbol = symbol
|
this.symbol = symbol
|
||||||
dispatchReceiverType = c.dispatchReceiver
|
dispatchReceiverType = c.dispatchReceiver
|
||||||
@@ -571,6 +572,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
|
|||||||
visibility.toEffectiveVisibility(classBuilder.symbol)
|
visibility.toEffectiveVisibility(classBuilder.symbol)
|
||||||
).apply {
|
).apply {
|
||||||
isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
||||||
|
hasStableParameterNames = !Flags.IS_CONSTRUCTOR_WITH_NON_STABLE_PARAMETER_NAMES.get(flags)
|
||||||
isActual = false
|
isActual = false
|
||||||
isOverride = false
|
isOverride = false
|
||||||
this.isInner = isInner
|
this.isInner = isInner
|
||||||
|
|||||||
+12
-2
@@ -433,8 +433,9 @@ class FirElementSerializer private constructor(
|
|||||||
simpleFunction?.isExternal == true,
|
simpleFunction?.isExternal == true,
|
||||||
simpleFunction?.isSuspend == true,
|
simpleFunction?.isSuspend == true,
|
||||||
simpleFunction?.isExpect == true,
|
simpleFunction?.isExpect == true,
|
||||||
true // TODO: supply 'hasStableParameterNames' flag for metadata
|
shouldSetStableParameterNames(simpleFunction),
|
||||||
)
|
)
|
||||||
|
|
||||||
if (flags != builder.flags) {
|
if (flags != builder.flags) {
|
||||||
builder.flags = flags
|
builder.flags = flags
|
||||||
}
|
}
|
||||||
@@ -507,6 +508,15 @@ class FirElementSerializer private constructor(
|
|||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun shouldSetStableParameterNames(simpleFunction: FirSimpleFunction?): Boolean {
|
||||||
|
return when {
|
||||||
|
simpleFunction?.hasStableParameterNames == true -> true
|
||||||
|
// for backward compatibility with K1, remove this line to fix KT-4758
|
||||||
|
simpleFunction?.origin == FirDeclarationOrigin.Delegated -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun typeAliasProto(typeAlias: FirTypeAlias): ProtoBuf.TypeAlias.Builder? = whileAnalysing(session, typeAlias) {
|
private fun typeAliasProto(typeAlias: FirTypeAlias): ProtoBuf.TypeAlias.Builder? = whileAnalysing(session, typeAlias) {
|
||||||
if (!extension.shouldSerializeTypeAlias(typeAlias)) return null
|
if (!extension.shouldSerializeTypeAlias(typeAlias)) return null
|
||||||
|
|
||||||
@@ -570,7 +580,7 @@ class FirElementSerializer private constructor(
|
|||||||
constructor.nonSourceAnnotations(session).isNotEmpty(),
|
constructor.nonSourceAnnotations(session).isNotEmpty(),
|
||||||
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
ProtoEnumFlags.visibility(normalizeVisibility(constructor)),
|
||||||
!constructor.isPrimary,
|
!constructor.isPrimary,
|
||||||
true // TODO: supply 'hasStableParameterNames' flag for metadata
|
constructor.hasStableParameterNames,
|
||||||
)
|
)
|
||||||
if (flags != builder.flags) {
|
if (flags != builder.flags) {
|
||||||
builder.flags = flags
|
builder.flags = flags
|
||||||
|
|||||||
@@ -572,6 +572,7 @@ abstract class FirJavaFacade(
|
|||||||
// Approximation: all Java methods with name that allows to use it in operator form are considered operators
|
// Approximation: all Java methods with name that allows to use it in operator form are considered operators
|
||||||
// We need here more detailed checks (see modifierChecks.kt)
|
// We need here more detailed checks (see modifierChecks.kt)
|
||||||
isOperator = name in ALL_JAVA_OPERATION_NAMES || OperatorNameConventions.COMPONENT_REGEX.matches(name.asString())
|
isOperator = name in ALL_JAVA_OPERATION_NAMES || OperatorNameConventions.COMPONENT_REGEX.matches(name.asString())
|
||||||
|
hasStableParameterNames = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!javaMethod.isStatic) {
|
if (!javaMethod.isStatic) {
|
||||||
@@ -628,6 +629,7 @@ abstract class FirJavaFacade(
|
|||||||
visibility.toEffectiveVisibility(ownerClassBuilder.symbol)
|
visibility.toEffectiveVisibility(ownerClassBuilder.symbol)
|
||||||
).apply {
|
).apply {
|
||||||
isInner = isThisInner
|
isInner = isThisInner
|
||||||
|
hasStableParameterNames = false
|
||||||
}
|
}
|
||||||
this.visibility = visibility
|
this.visibility = visibility
|
||||||
isPrimary = javaConstructor == null
|
isPrimary = javaConstructor == null
|
||||||
|
|||||||
+3
-4
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
|
|||||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
|
import org.jetbrains.kotlin.fir.expressions.unexpandedClassId
|
||||||
@@ -262,6 +259,8 @@ class FirSignatureEnhancement(
|
|||||||
FirDeclarationStatusImpl(firMethod.visibility, Modality.FINAL)
|
FirDeclarationStatusImpl(firMethod.visibility, Modality.FINAL)
|
||||||
}.apply {
|
}.apply {
|
||||||
isInner = firMethod.isInner
|
isInner = firMethod.isInner
|
||||||
|
// Java annotation class constructors have stable names, copy flag.
|
||||||
|
hasStableParameterNames = firMethod.hasStableParameterNames
|
||||||
}
|
}
|
||||||
this.symbol = symbol
|
this.symbol = symbol
|
||||||
dispatchReceiverType = firMethod.dispatchReceiverType
|
dispatchReceiverType = firMethod.dispatchReceiverType
|
||||||
|
|||||||
+7
-3
@@ -74,13 +74,16 @@ abstract class FirSyntheticFunctionInterfaceProviderBase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {}
|
override fun getTopLevelCallableSymbolsTo(destination: MutableList<FirCallableSymbol<*>>, packageFqName: FqName, name: Name) {
|
||||||
|
}
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {}
|
override fun getTopLevelFunctionSymbolsTo(destination: MutableList<FirNamedFunctionSymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
}
|
||||||
|
|
||||||
@FirSymbolProviderInternals
|
@FirSymbolProviderInternals
|
||||||
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {}
|
override fun getTopLevelPropertySymbolsTo(destination: MutableList<FirPropertySymbol>, packageFqName: FqName, name: Name) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun getPackage(fqName: FqName): FqName? {
|
override fun getPackage(fqName: FqName): FqName? {
|
||||||
return fqName.takeIf { session.functionTypeService.hasKindWithSpecificPackage(it) }
|
return fqName.takeIf { session.functionTypeService.hasKindWithSpecificPackage(it) }
|
||||||
@@ -162,6 +165,7 @@ abstract class FirSyntheticFunctionInterfaceProviderBase(
|
|||||||
).apply {
|
).apply {
|
||||||
isOperator = true
|
isOperator = true
|
||||||
isSuspend = kind.isSuspendOrKSuspendFunction
|
isSuspend = kind.isSuspendOrKSuspendFunction
|
||||||
|
hasStableParameterNames = false
|
||||||
}
|
}
|
||||||
val typeArguments = typeParameters.map {
|
val typeArguments = typeParameters.map {
|
||||||
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false).toFirResolvedTypeRef()
|
ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false).toFirResolvedTypeRef()
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
|||||||
import org.jetbrains.kotlin.fakeElement
|
import org.jetbrains.kotlin.fakeElement
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
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.diagnostics.*
|
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||||
@@ -560,20 +557,14 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
|
|||||||
// for intersection/substitution overrides
|
// for intersection/substitution overrides
|
||||||
originScope: FirTypeScope? = null
|
originScope: FirTypeScope? = null
|
||||||
): ForbiddenNamedArgumentsTarget? {
|
): ForbiddenNamedArgumentsTarget? {
|
||||||
if (this is FirConstructor && this.isPrimary) {
|
if (hasStableParameterNames) return null
|
||||||
this.getContainingClass(session)?.let { containingClass ->
|
|
||||||
if (containingClass.classKind == ClassKind.ANNOTATION_CLASS) {
|
|
||||||
// Java annotation classes allow (actually require) named parameters.
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return when (origin) {
|
return when (origin) {
|
||||||
FirDeclarationOrigin.Source, FirDeclarationOrigin.Precompiled, FirDeclarationOrigin.Library -> null
|
|
||||||
FirDeclarationOrigin.Delegated -> delegatedWrapperData?.wrapped?.getAsForbiddenNamedArgumentsTarget(session)
|
FirDeclarationOrigin.Delegated -> delegatedWrapperData?.wrapped?.getAsForbiddenNamedArgumentsTarget(session)
|
||||||
FirDeclarationOrigin.ImportedFromObjectOrStatic -> importedFromObjectOrStaticData?.original?.getAsForbiddenNamedArgumentsTarget(session)
|
|
||||||
is FirDeclarationOrigin.Java, FirDeclarationOrigin.Enhancement -> ForbiddenNamedArgumentsTarget.NON_KOTLIN_FUNCTION
|
FirDeclarationOrigin.ImportedFromObjectOrStatic ->
|
||||||
FirDeclarationOrigin.SamConstructor -> null
|
importedFromObjectOrStaticData?.original?.getAsForbiddenNamedArgumentsTarget(session)
|
||||||
|
|
||||||
FirDeclarationOrigin.IntersectionOverride, FirDeclarationOrigin.SubstitutionOverride -> {
|
FirDeclarationOrigin.IntersectionOverride, FirDeclarationOrigin.SubstitutionOverride -> {
|
||||||
var result: ForbiddenNamedArgumentsTarget? =
|
var result: ForbiddenNamedArgumentsTarget? =
|
||||||
originalIfFakeOverride()?.getAsForbiddenNamedArgumentsTarget(session) ?: return null
|
originalIfFakeOverride()?.getAsForbiddenNamedArgumentsTarget(session) ?: return null
|
||||||
@@ -587,25 +578,13 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(
|
|||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
// referenced function of a Kotlin function type
|
|
||||||
FirDeclarationOrigin.BuiltIns -> runIf(dispatchReceiverClassLookupTagOrNull()?.isSomeFunctionType(session) == true) {
|
|
||||||
ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
|
|
||||||
}
|
|
||||||
|
|
||||||
FirDeclarationOrigin.Synthetic,
|
FirDeclarationOrigin.BuiltIns -> ForbiddenNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE
|
||||||
FirDeclarationOrigin.DynamicScope,
|
|
||||||
FirDeclarationOrigin.RenamedForOverride,
|
|
||||||
FirDeclarationOrigin.WrappedIntegerOperator,
|
|
||||||
FirDeclarationOrigin.ScriptCustomization,
|
|
||||||
is FirDeclarationOrigin.Plugin -> null // TODO: figure out what to do with plugin generated functions
|
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)
|
@OptIn(ExperimentalContracts::class)
|
||||||
fun FirExpression?.isIntegerLiteralOrOperatorCall(): Boolean {
|
fun FirExpression?.isIntegerLiteralOrOperatorCall(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ interface FirDeclarationStatus : FirElement {
|
|||||||
val isFromSealedClass: Boolean
|
val isFromSealedClass: Boolean
|
||||||
val isFromEnumClass: Boolean
|
val isFromEnumClass: Boolean
|
||||||
val isFun: Boolean
|
val isFun: Boolean
|
||||||
|
val hasStableParameterNames: Boolean
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data)
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDeclarationStatus(this, data)
|
||||||
|
|
||||||
|
|||||||
+1
@@ -39,6 +39,7 @@ interface FirResolvedDeclarationStatus : FirDeclarationStatus {
|
|||||||
override val isFromSealedClass: Boolean
|
override val isFromSealedClass: Boolean
|
||||||
override val isFromEnumClass: Boolean
|
override val isFromEnumClass: Boolean
|
||||||
override val isFun: Boolean
|
override val isFun: Boolean
|
||||||
|
override val hasStableParameterNames: Boolean
|
||||||
val effectiveVisibility: EffectiveVisibility
|
val effectiveVisibility: EffectiveVisibility
|
||||||
|
|
||||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedDeclarationStatus(this, data)
|
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedDeclarationStatus(this, data)
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ fun FirDeclarationStatus.copy(
|
|||||||
isFromSealedClass: Boolean = this.isFromSealedClass,
|
isFromSealedClass: Boolean = this.isFromSealedClass,
|
||||||
isFromEnumClass: Boolean = this.isFromEnumClass,
|
isFromEnumClass: Boolean = this.isFromEnumClass,
|
||||||
isFun: Boolean = this.isFun,
|
isFun: Boolean = this.isFun,
|
||||||
|
hasStableParameterNames: Boolean = this.hasStableParameterNames,
|
||||||
): FirDeclarationStatus {
|
): FirDeclarationStatus {
|
||||||
val newVisibility = visibility ?: this.visibility
|
val newVisibility = visibility ?: this.visibility
|
||||||
val newModality = modality ?: this.modality
|
val newModality = modality ?: this.modality
|
||||||
@@ -137,6 +138,7 @@ fun FirDeclarationStatus.copy(
|
|||||||
this.isFromSealedClass = isFromSealedClass
|
this.isFromSealedClass = isFromSealedClass
|
||||||
this.isFromEnumClass = isFromEnumClass
|
this.isFromEnumClass = isFromEnumClass
|
||||||
this.isFun = isFun
|
this.isFun = isFun
|
||||||
|
this.hasStableParameterNames = hasStableParameterNames
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-2
@@ -20,7 +20,7 @@ open class FirDeclarationStatusImpl(
|
|||||||
override val modality: Modality?
|
override val modality: Modality?
|
||||||
) : FirPureAbstractElement(), FirDeclarationStatus {
|
) : FirPureAbstractElement(), FirDeclarationStatus {
|
||||||
override val source: KtSourceElement? get() = null
|
override val source: KtSourceElement? get() = null
|
||||||
protected var flags: Int = 0
|
protected var flags: Int = HAS_STABLE_PARAMETER_NAMES.mask
|
||||||
|
|
||||||
operator fun get(modifier: Modifier): Boolean = (flags and modifier.mask) != 0
|
operator fun get(modifier: Modifier): Boolean = (flags and modifier.mask) != 0
|
||||||
|
|
||||||
@@ -140,6 +140,12 @@ open class FirDeclarationStatusImpl(
|
|||||||
this[FUN] = value
|
this[FUN] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var hasStableParameterNames: Boolean
|
||||||
|
get() = this[HAS_STABLE_PARAMETER_NAMES]
|
||||||
|
set(value) {
|
||||||
|
this[HAS_STABLE_PARAMETER_NAMES] = value
|
||||||
|
}
|
||||||
|
|
||||||
enum class Modifier(val mask: Int) {
|
enum class Modifier(val mask: Int) {
|
||||||
EXPECT(0x1),
|
EXPECT(0x1),
|
||||||
ACTUAL(0x2),
|
ACTUAL(0x2),
|
||||||
@@ -158,7 +164,8 @@ open class FirDeclarationStatusImpl(
|
|||||||
STATIC(0x4000),
|
STATIC(0x4000),
|
||||||
FROM_SEALED(0x8000),
|
FROM_SEALED(0x8000),
|
||||||
FROM_ENUM(0x10000),
|
FROM_ENUM(0x10000),
|
||||||
FUN(0x20000)
|
FUN(0x20000),
|
||||||
|
HAS_STABLE_PARAMETER_NAMES(0x40000),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ inline val FirMemberDeclaration.isLateInit: Boolean get() = status.isLateInit
|
|||||||
inline val FirMemberDeclaration.isFromSealedClass: Boolean get() = status.isFromSealedClass
|
inline val FirMemberDeclaration.isFromSealedClass: Boolean get() = status.isFromSealedClass
|
||||||
inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEnumClass
|
inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEnumClass
|
||||||
inline val FirMemberDeclaration.isFun: Boolean get() = status.isFun
|
inline val FirMemberDeclaration.isFun: Boolean get() = status.isFun
|
||||||
|
inline val FirMemberDeclaration.hasStableParameterNames: Boolean get() = status.hasStableParameterNames
|
||||||
|
|
||||||
inline val FirClassLikeDeclaration.isLocal: Boolean get() = symbol.classId.isLocal
|
inline val FirClassLikeDeclaration.isLocal: Boolean get() = symbol.classId.isLocal
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -382,7 +382,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
|||||||
generateBooleanFields(
|
generateBooleanFields(
|
||||||
"expect", "actual", "override", "operator", "infix", "inline", "tailRec",
|
"expect", "actual", "override", "operator", "infix", "inline", "tailRec",
|
||||||
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static",
|
"external", "const", "lateInit", "inner", "companion", "data", "suspend", "static",
|
||||||
"fromSealedClass", "fromEnumClass", "fun"
|
"fromSealedClass", "fromEnumClass", "fun", "hasStableParameterNames",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ abstract class AbstractFieldConfigurator<T : AbstractFirTreeBuilder>(private val
|
|||||||
|
|
||||||
fun generateBooleanFields(vararg names: String) {
|
fun generateBooleanFields(vararg names: String) {
|
||||||
names.forEach {
|
names.forEach {
|
||||||
+booleanField("is${it.replaceFirstChar(Char::uppercaseChar)}")
|
+booleanField(if (it.startsWith("is") || it.startsWith("has")) it else "is${it.replaceFirstChar(Char::uppercaseChar)}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public interface JavaInterface {
|
||||||
|
public void foo(int javaName);
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
public class JavaSuperClass implements JavaInterface {
|
||||||
|
@Override
|
||||||
|
public void foo(int javaName) {}
|
||||||
|
}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
class KtClass : JavaInterface by JavaSuperClass()
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
fun test() {
|
||||||
|
val ktInstance = KtClass()
|
||||||
|
// Shouldn't work but is kept for backward compatibility with K1
|
||||||
|
// When KT-4758 is fixed, this should break.
|
||||||
|
ktInstance.foo(javaName = 1)
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
// FILE: JavaInterface.java
|
||||||
|
|
||||||
|
public interface JavaInterface {
|
||||||
|
public void foo(int javaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: JavaClass.java
|
||||||
|
|
||||||
|
public class JavaSuperClass implements JavaInterface {
|
||||||
|
@Override
|
||||||
|
public void foo(int javaName) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
class KtClass: JavaInterface by JavaSuperClass()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val ktInstance = KtClass()
|
||||||
|
ktInstance.foo(<!NAMED_ARGUMENTS_NOT_ALLOWED!>javaName<!> = 1)
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// SKIP_TXT
|
||||||
|
|
||||||
|
fun test(f: (String) -> Unit) {
|
||||||
|
f(<!NAMED_ARGUMENTS_NOT_ALLOWED!>p1<!> = "")
|
||||||
|
}
|
||||||
Generated
+12
@@ -22100,6 +22100,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
runTest("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForDelegationToJavaMethods.kt")
|
||||||
|
public void testDisallowForDelegationToJavaMethods() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForDelegationToJavaMethods.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("disallowForFunctionTypes.kt")
|
||||||
|
public void testDisallowForFunctionTypes() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/namedArguments/disallowForFunctionTypes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("disallowForJavaConstructor.kt")
|
@TestMetadata("disallowForJavaConstructor.kt")
|
||||||
public void testDisallowForJavaConstructor() throws Exception {
|
public void testDisallowForJavaConstructor() throws Exception {
|
||||||
|
|||||||
+5
@@ -371,6 +371,11 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration
|
|||||||
compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library")))
|
compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testHasStableParameterNames() {
|
||||||
|
val library = compileLibrary("library", additionalOptions = listOf("-language-version", "2.0"))
|
||||||
|
compileKotlin("source.kt", tmpdir, listOf(library), additionalOptions = listOf("-language-version", "2.0"))
|
||||||
|
}
|
||||||
|
|
||||||
fun testRequireKotlinInNestedClasses() {
|
fun testRequireKotlinInNestedClasses() {
|
||||||
compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library")))
|
compileKotlin("source.kt", tmpdir, listOf(compileLibrary("library")))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user