[FIR] Create fake hidden versions of List.getFirst/getLast in JDK < 21
... so that overrides are marked as deprecated regardless of the JDK. #KT-65440 Fixed
This commit is contained in:
committed by
Space Team
parent
c6b2675089
commit
2f49272c42
+1
@@ -62,6 +62,7 @@ internal tailrec fun FirDeclaration.ktSymbolOrigin(): KtSymbolOrigin = when (ori
|
||||
FirDeclarationOrigin.Enhancement -> KtSymbolOrigin.JAVA
|
||||
FirDeclarationOrigin.IntersectionOverride -> KtSymbolOrigin.INTERSECTION_OVERRIDE
|
||||
FirDeclarationOrigin.Delegated -> KtSymbolOrigin.DELEGATED
|
||||
FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk -> KtSymbolOrigin.LIBRARY
|
||||
is FirDeclarationOrigin.Synthetic -> {
|
||||
when {
|
||||
source?.kind == KtFakeSourceElementKind.DataClassGeneratedMembers -> KtSymbolOrigin.SOURCE_MEMBER_GENERATED
|
||||
|
||||
+4
@@ -45,3 +45,7 @@ open operator fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||
open fun hashCode(): kotlin.Int
|
||||
|
||||
open fun toString(): kotlin.String
|
||||
|
||||
fun getFirst(): E
|
||||
|
||||
fun getLast(): E
|
||||
+82
@@ -1546,4 +1546,86 @@ KtFunctionSymbol:
|
||||
getContainingFileSymbol: null
|
||||
getContainingJvmClassName: kotlin.Any
|
||||
getContainingModule: KtBinaryModule "Builtins for JVM (1.8)"
|
||||
deprecationStatus: null
|
||||
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/MutableList.getFirst
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getFirst
|
||||
origin: SUBSTITUTION_OVERRIDE
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: [
|
||||
KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
]
|
||||
type: kotlin/collections/MutableList<E>
|
||||
getContainingFileSymbol: null
|
||||
getContainingJvmClassName: kotlin.collections.MutableList
|
||||
getContainingModule: KtBinaryModule "Builtins for JVM (1.8)"
|
||||
deprecationStatus: null
|
||||
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/MutableList.getLast
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getLast
|
||||
origin: SUBSTITUTION_OVERRIDE
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
getDispatchReceiver(): KtUsualClassType:
|
||||
annotationsList: []
|
||||
ownTypeArguments: [
|
||||
KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
]
|
||||
type: kotlin/collections/MutableList<E>
|
||||
getContainingFileSymbol: null
|
||||
getContainingJvmClassName: kotlin.collections.MutableList
|
||||
getContainingModule: KtBinaryModule "Builtins for JVM (1.8)"
|
||||
deprecationStatus: null
|
||||
+5
@@ -13,6 +13,8 @@ val size: kotlin.Int
|
||||
fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||
fun hashCode(): kotlin.Int
|
||||
fun toString(): kotlin.String
|
||||
fun getFirst(): kotlin.Int
|
||||
fun getLast(): kotlin.Int
|
||||
|
||||
|
||||
Declaration Scope:
|
||||
@@ -30,3 +32,6 @@ val size: kotlin.Int
|
||||
fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||
fun hashCode(): kotlin.Int
|
||||
fun toString(): kotlin.String
|
||||
fun getFirst(): E
|
||||
fun getLast(): E
|
||||
|
||||
|
||||
+68
@@ -148,6 +148,18 @@ KtFunctionLikeSignature:
|
||||
symbol = kotlin/Any.toString(<dispatch receiver>: kotlin.Any): kotlin.String
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/Any.toString
|
||||
KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = kotlin.Int
|
||||
symbol = kotlin/collections/List.getFirst(<dispatch receiver>: kotlin.collections.List<E>): E
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/collections/List.getFirst
|
||||
KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = kotlin.Int
|
||||
symbol = kotlin/collections/List.getLast(<dispatch receiver>: kotlin.collections.List<E>): E
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/collections/List.getLast
|
||||
|
||||
|
||||
Declaration Scope:
|
||||
@@ -798,4 +810,60 @@ KtFunctionSymbol:
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/List.getFirst
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getFirst
|
||||
origin: LIBRARY
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/List.getLast
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getLast
|
||||
origin: LIBRARY
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
|
||||
|
||||
+5
@@ -13,6 +13,8 @@ val size: kotlin.Int
|
||||
fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||
fun hashCode(): kotlin.Int
|
||||
fun toString(): kotlin.String
|
||||
fun getFirst(): AAA
|
||||
fun getLast(): AAA
|
||||
|
||||
|
||||
Declaration Scope:
|
||||
@@ -30,3 +32,6 @@ val size: kotlin.Int
|
||||
fun equals(other: kotlin.Any?): kotlin.Boolean
|
||||
fun hashCode(): kotlin.Int
|
||||
fun toString(): kotlin.String
|
||||
fun getFirst(): E
|
||||
fun getLast(): E
|
||||
|
||||
|
||||
+68
@@ -148,6 +148,18 @@ KtFunctionLikeSignature:
|
||||
symbol = kotlin/Any.toString(<dispatch receiver>: kotlin.Any): kotlin.String
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/Any.toString
|
||||
KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = AAA
|
||||
symbol = kotlin/collections/List.getFirst(<dispatch receiver>: kotlin.collections.List<E>): E
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/collections/List.getFirst
|
||||
KtFunctionLikeSignature:
|
||||
receiverType = null
|
||||
returnType = AAA
|
||||
symbol = kotlin/collections/List.getLast(<dispatch receiver>: kotlin.collections.List<E>): E
|
||||
valueParameters = []
|
||||
callableIdIfNonLocal = kotlin/collections/List.getLast
|
||||
|
||||
|
||||
Declaration Scope:
|
||||
@@ -798,4 +810,60 @@ KtFunctionSymbol:
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/List.getFirst
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getFirst
|
||||
origin: LIBRARY
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
KtFunctionSymbol:
|
||||
annotationsList: []
|
||||
callableIdIfNonLocal: kotlin/collections/List.getLast
|
||||
contextReceivers: []
|
||||
contractEffects: []
|
||||
hasStableParameterNames: true
|
||||
isActual: false
|
||||
isBuiltinFunctionInvoke: false
|
||||
isExpect: false
|
||||
isExtension: false
|
||||
isExternal: false
|
||||
isInfix: false
|
||||
isInline: false
|
||||
isOperator: false
|
||||
isOverride: false
|
||||
isStatic: false
|
||||
isSuspend: false
|
||||
modality: OPEN
|
||||
name: getLast
|
||||
origin: LIBRARY
|
||||
receiverParameter: null
|
||||
returnType: KtTypeParameterType:
|
||||
annotationsList: []
|
||||
type: E
|
||||
symbolKind: CLASS_MEMBER
|
||||
typeParameters: []
|
||||
valueParameters: []
|
||||
visibility: Public
|
||||
|
||||
|
||||
+6
@@ -38708,6 +38708,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.(kt|kts)$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("newListMethods.kt")
|
||||
public void testNewListMethods() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+6
@@ -38708,6 +38708,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.(kt|kts)$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("newListMethods.kt")
|
||||
public void testNewListMethods() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+6
@@ -36334,6 +36334,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("newListMethods.kt")
|
||||
public void testNewListMethods() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+6
@@ -36460,6 +36460,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true, "multiplatform");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("newListMethods.kt")
|
||||
public void testNewListMethods() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+3
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.jvm
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.isJavaOrEnhancement
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
|
||||
@@ -19,6 +20,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
*/
|
||||
object FirJvmOverridesBackwardCompatibilityHelper : FirOverridesBackwardCompatibilityHelper() {
|
||||
override fun additionalCheck(member: FirCallableSymbol<*>): Boolean? {
|
||||
if (member.origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return true
|
||||
|
||||
if (!member.isJavaOrEnhancement) return false
|
||||
val containingClassName = member.containingClassLookupTag()?.classId?.asSingleFqName()?.toUnsafe() ?: return false
|
||||
// If the super class is mapped to a Kotlin built-in class, then we don't require `override` keyword.
|
||||
|
||||
+1
@@ -314,6 +314,7 @@ class FakeOverrideGenerator(
|
||||
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
|
||||
|
||||
if (!session.visibilityChecker.isVisibleForOverriding(klass.moduleData, klass.symbol, baseSymbol.fir)) return
|
||||
if (originalDeclaration.originalOrSelf().origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return
|
||||
|
||||
val (fakeOverrideFirDeclaration, baseFirSymbolsForFakeOverride) = when {
|
||||
originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> {
|
||||
|
||||
@@ -229,6 +229,7 @@ class Fir2IrLazyClass(
|
||||
}
|
||||
|
||||
private fun shouldBuildStub(fir: FirDeclaration): Boolean {
|
||||
if (fir is FirCallableDeclaration && fir.originalOrSelf().origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk) return false
|
||||
if (fir !is FirMemberDeclaration) return true
|
||||
return when {
|
||||
fir is FirConstructor -> isObject || isEnumClass || !Visibilities.isPrivate(fir.visibility) // This special case seams to be not needed anymore - KT-65172
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ class FirJvmDelegatedMembersFilter(private val session: FirSession) : FirDelegat
|
||||
|
||||
override fun shouldNotGenerateDelegatedMember(memberSymbolFromSuperInterface: FirCallableSymbol<*>): Boolean {
|
||||
val original = memberSymbolFromSuperInterface.unwrapFakeOverrides()
|
||||
return original.isNonAbstractJavaMethod() || original.hasJvmDefaultAnnotation() || original.isBuiltInMemberMappedToJavaDefault()
|
||||
return original.isNonAbstractJavaMethod() || original.hasJvmDefaultAnnotation() || original.isBuiltInMemberMappedToJavaDefault() || original.origin == FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk
|
||||
}
|
||||
|
||||
// If java interface method is not abstract, then it's a default method.
|
||||
|
||||
@@ -7,11 +7,17 @@ package org.jetbrains.kotlin.fir.scopes.jvm
|
||||
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsSignatures
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.caches.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.defaultType
|
||||
import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf
|
||||
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
@@ -26,6 +32,8 @@ import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
|
||||
@@ -36,6 +44,7 @@ import org.jetbrains.kotlin.load.kotlin.SignatureBuildingComponents
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
/**
|
||||
* @param firKotlinClass Kotlin version of built-in class mapped to some JDK class (e.g. kotlin.collections.List)
|
||||
@@ -75,8 +84,10 @@ class JvmMappedScope(
|
||||
}
|
||||
}
|
||||
|
||||
private val isList: Boolean = firKotlinClass.classId == StandardClassIds.List
|
||||
|
||||
// It's ok to have a super set of actually available member names
|
||||
private val myCallableNames by lazy {
|
||||
private val myCallableNames: Set<Name> by lazy {
|
||||
if (firKotlinClass.isFinal) {
|
||||
// For final classes we don't need to load HIDDEN members at all because they might not be overridden
|
||||
val signaturePrefix = firJavaClass.symbol.classId.toString()
|
||||
@@ -91,6 +102,13 @@ class JvmMappedScope(
|
||||
declaredMemberScope.getCallableNames() + names
|
||||
} else {
|
||||
declaredMemberScope.getCallableNames() + javaMappedClassUseSiteScope.getCallableNames()
|
||||
}.let {
|
||||
// If getFirst/getLast don't exist, we need to add them so that we can mark overrides as deprecated (KT-65440)
|
||||
if (isList && (GET_FIRST_NAME !in it || GET_LAST_NAME !in it)) {
|
||||
it + listOf(GET_FIRST_NAME, GET_LAST_NAME)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +130,8 @@ class JvmMappedScope(
|
||||
}
|
||||
}
|
||||
|
||||
var needsHiddenFake = isList && (name == GET_FIRST_NAME || name == GET_LAST_NAME)
|
||||
|
||||
javaMappedClassUseSiteScope.processFunctionsByName(name) processor@{ symbol ->
|
||||
if (!symbol.isDeclaredInMappedJavaClass() || !(symbol.fir.status as FirResolvedDeclarationStatus).visibility.isPublicAPI) {
|
||||
return@processor
|
||||
@@ -137,8 +157,46 @@ class JvmMappedScope(
|
||||
if ((jdkMemberStatus == JDKMemberStatus.HIDDEN || jdkMemberStatus == JDKMemberStatus.HIDDEN_IN_DECLARING_CLASS_ONLY) && firKotlinClass.isFinal) return@processor
|
||||
|
||||
val newSymbol = mappedSymbolCache.mappedFunctions.getValue(symbol, this to jdkMemberStatus)
|
||||
|
||||
if (needsHiddenFake &&
|
||||
allJavaMappedSuperClassIds.any {
|
||||
SignatureBuildingComponents.signature(it, jvmDescriptor) in JvmBuiltInsSignatures.DEPRECATED_LIST_METHODS
|
||||
}
|
||||
) {
|
||||
needsHiddenFake = false
|
||||
}
|
||||
|
||||
processor(newSymbol)
|
||||
}
|
||||
|
||||
if (needsHiddenFake) {
|
||||
// We're in JDK < 21, i.e., getFirst/getLast don't exist in the List interface yet.
|
||||
// We create a fake version of them for the sole purpose of reporting deprecations on to-become-overrides like in LinkedList.
|
||||
// This is because we want to rename these two methods in the future,
|
||||
// and we want to warn users of older JDKs of a potential breaking change caused by upgrading to JDK >= 21.
|
||||
// See KT-65440.
|
||||
val fakeSymbol = mappedSymbolCache.hiddenFakeFunctions.getValue(name, this)
|
||||
processor(fakeSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createHiddenFakeFunction(name: Name): FirNamedFunctionSymbol {
|
||||
return buildSimpleFunction {
|
||||
moduleData = firKotlinClass.moduleData
|
||||
origin = FirDeclarationOrigin.Synthetic.FakeHiddenInPreparationForNewJdk
|
||||
status = FirResolvedDeclarationStatusImpl(Visibilities.Public, Modality.OPEN, EffectiveVisibility.Public)
|
||||
returnTypeRef = buildResolvedTypeRef {
|
||||
type = firKotlinClass.typeParameters.firstOrNull()
|
||||
?.let { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) }
|
||||
?: ConeErrorType(ConeSimpleDiagnostic("No type parameter found on '${firKotlinClass.classKind}'"))
|
||||
}
|
||||
this.name = name
|
||||
dispatchReceiverType = firKotlinClass.defaultType()
|
||||
symbol = FirNamedFunctionSymbol(CallableId(firKotlinClass.classId, name))
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
}.apply {
|
||||
isHiddenEverywhereBesideSuperCalls = HiddenEverywhereBesideSuperCallsStatus.HIDDEN_FAKE
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private fun isOverrideOfKotlinDeclaredFunction(symbol: FirNamedFunctionSymbol) =
|
||||
@@ -335,6 +393,11 @@ class JvmMappedScope(
|
||||
scope.createMappedFunction(symbol, jdkMemberStatus)
|
||||
}
|
||||
|
||||
val hiddenFakeFunctions: FirCache<Name, FirNamedFunctionSymbol, JvmMappedScope> =
|
||||
cachesFactory.createCache { name, scope ->
|
||||
scope.createHiddenFakeFunction(name)
|
||||
}
|
||||
|
||||
val mappedConstructors: FirCache<FirConstructorSymbol, FirConstructorSymbol, JvmMappedScope> =
|
||||
cachesFactory.createCache { symbol, scope ->
|
||||
scope.createMappedConstructor(symbol)
|
||||
@@ -357,6 +420,9 @@ class JvmMappedScope(
|
||||
},
|
||||
session
|
||||
)
|
||||
|
||||
private val GET_FIRST_NAME = Name.identifier("getFirst")
|
||||
private val GET_LAST_NAME = Name.identifier("getLast")
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
|
||||
+3
-1
@@ -331,7 +331,7 @@ var FirCallableDeclaration.isHiddenEverywhereBesideSuperCalls: HiddenEverywhereB
|
||||
)
|
||||
|
||||
enum class HiddenEverywhereBesideSuperCallsStatus {
|
||||
HIDDEN, HIDDEN_IN_DECLARING_CLASS_ONLY
|
||||
HIDDEN, HIDDEN_IN_DECLARING_CLASS_ONLY, HIDDEN_FAKE,
|
||||
}
|
||||
|
||||
private object IsHiddenToOvercomeSignatureClash : FirDeclarationDataKey()
|
||||
@@ -360,5 +360,7 @@ fun FirCallableSymbol<*>.isHidden(isSuperCall: Boolean, isOverridden: Boolean):
|
||||
// we report a deprecation warning on super calls because we might want to rename the method in the future
|
||||
// (getFirst -> first).
|
||||
HiddenEverywhereBesideSuperCallsStatus.HIDDEN_IN_DECLARING_CLASS_ONLY -> if (isSuperCall || isOverridden) CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation else CallToPotentiallyHiddenSymbolResult.Hidden
|
||||
// HIDDEN_FAKE is always hidden (even for super calls), unless overridden.
|
||||
HiddenEverywhereBesideSuperCallsStatus.HIDDEN_FAKE -> if (isOverridden) CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation else CallToPotentiallyHiddenSymbolResult.Hidden
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ sealed class FirDeclarationOrigin(
|
||||
object FakeFunction : Synthetic()
|
||||
object ForwardDeclaration : Synthetic()
|
||||
object ScriptTopLevelDestructuringDeclarationContainer : Synthetic()
|
||||
object FakeHiddenInPreparationForNewJdk : Synthetic()
|
||||
}
|
||||
object DynamicScope : FirDeclarationOrigin()
|
||||
object SamConstructor : FirDeclarationOrigin()
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import java.util.LinkedList
|
||||
|
||||
class A<T> : ArrayList<T>() {
|
||||
fun getFirst(): T = super.<!UNRESOLVED_REFERENCE!>getFirst<!>()
|
||||
fun getLast(): T = super.<!UNRESOLVED_REFERENCE!>getLast<!>()
|
||||
}
|
||||
|
||||
fun foo(x: List<String>, y: LinkedList<String>, z: A<String>) {
|
||||
x.<!UNRESOLVED_REFERENCE!>getFirst<!>()
|
||||
x.<!FUNCTION_CALL_EXPECTED!>first<!>
|
||||
x.first() // stdlib extension on List
|
||||
x.<!UNRESOLVED_REFERENCE!>getLast<!>()
|
||||
x.<!FUNCTION_CALL_EXPECTED!>last<!>
|
||||
x.last()
|
||||
|
||||
y.<!DEPRECATION!>getFirst<!>()
|
||||
y.<!DEPRECATION!>first<!>
|
||||
y.first()
|
||||
y.<!DEPRECATION!>getLast<!>()
|
||||
y.<!DEPRECATION!>last<!>
|
||||
y.last()
|
||||
|
||||
z.<!DEPRECATION!>getFirst<!>()
|
||||
z.<!FUNCTION_CALL_EXPECTED!>first<!>
|
||||
z.first()
|
||||
z.<!DEPRECATION!>getLast<!>()
|
||||
z.<!FUNCTION_CALL_EXPECTED!>last<!>
|
||||
z.last()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import java.util.LinkedList
|
||||
|
||||
class A<T> : ArrayList<T>() {
|
||||
fun getFirst(): T = super.<!UNRESOLVED_REFERENCE!>getFirst<!>()
|
||||
fun getLast(): T = super.<!UNRESOLVED_REFERENCE!>getLast<!>()
|
||||
}
|
||||
|
||||
fun foo(x: List<String>, y: LinkedList<String>, z: A<String>) {
|
||||
x.<!UNRESOLVED_REFERENCE!>getFirst<!>()
|
||||
x.<!FUNCTION_CALL_EXPECTED!>first<!>
|
||||
x.first() // stdlib extension on List
|
||||
x.<!UNRESOLVED_REFERENCE!>getLast<!>()
|
||||
x.<!FUNCTION_CALL_EXPECTED!>last<!>
|
||||
x.last()
|
||||
|
||||
y.getFirst()
|
||||
y.first
|
||||
y.first()
|
||||
y.getLast()
|
||||
y.last
|
||||
y.last()
|
||||
|
||||
z.getFirst()
|
||||
z.<!FUNCTION_CALL_EXPECTED!>first<!>
|
||||
z.first()
|
||||
z.getLast()
|
||||
z.<!FUNCTION_CALL_EXPECTED!>last<!>
|
||||
z.last()
|
||||
}
|
||||
Generated
+6
@@ -38708,6 +38708,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/testsWithJava17"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("newListMethods.kt")
|
||||
public void testNewListMethods() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/testsWithJava17/newListMethods.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/testsWithJava17/jvmRecord")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
@@ -83,6 +83,7 @@ class InlinerCycleReporter(
|
||||
|
||||
} finally {
|
||||
if (!inlineCallInfos.isEmpty()) {
|
||||
@Suppress("DEPRECATION") // KT-65247
|
||||
if (inlineCallInfos.last.call == call) {
|
||||
inlineCallInfos.removeLast()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user