Improve 1.0-compatibility mode for JDK dependent members
Just reporting error by call checker may be too restrictive in case there are some extensions that can be used successfully Solution is to annotate additional members with @Deprecated(level=Error) + @kotlin.internal.LowPriorityInOverloadResolution
This commit is contained in:
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.frontend.java.di
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.*
|
||||
import org.jetbrains.kotlin.context.LazyResolveToken
|
||||
@@ -140,7 +141,8 @@ fun StorageComponentContainer.javaAnalysisInit() {
|
||||
// 'initBuiltIns' body cannot be merged with 'javaAnalysisInit' because the latter is used in IDE,
|
||||
// where built-ins instances are shared between modules and manual initialization is necessary (to avoid multiple initialization)
|
||||
fun StorageComponentContainer.initJvmBuiltInsForTopDownAnalysis() {
|
||||
get<JvmBuiltIns>().initialize(get<ModuleDescriptor>())
|
||||
get<JvmBuiltIns>().initialize(get<ModuleDescriptor>(),
|
||||
get<LanguageVersionSettings>().supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
|
||||
}
|
||||
|
||||
class ContainerForTopDownAnalyzerForJvm(container: StorageComponentContainer) {
|
||||
|
||||
-12
@@ -29,20 +29,8 @@ import org.jetbrains.kotlin.load.java.isFromBuiltins
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeUniqueAsSequence
|
||||
|
||||
object AdditionalBuiltInsMembersCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers)) return
|
||||
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
|
||||
|
||||
reportErrorIfAdditionalBuiltinDescriptor(resultingDescriptor, context.trace, reportOn)
|
||||
}
|
||||
}
|
||||
|
||||
object AdditionalBuiltInsMemberOverrideDeclarationChecker : DeclarationChecker {
|
||||
override fun check(
|
||||
declaration: KtDeclaration,
|
||||
|
||||
+1
-2
@@ -54,8 +54,7 @@ object JvmPlatformConfigurator : PlatformConfigurator(
|
||||
UnsupportedSyntheticCallableReferenceChecker(),
|
||||
SuperCallWithDefaultArgumentsChecker(),
|
||||
MissingDependencyClassChecker(),
|
||||
ProtectedSyntheticExtensionCallChecker,
|
||||
AdditionalBuiltInsMembersCallChecker
|
||||
ProtectedSyntheticExtensionCallChecker
|
||||
),
|
||||
|
||||
additionalTypeCheckers = listOf(
|
||||
|
||||
+15
-6
@@ -1,18 +1,27 @@
|
||||
// !CHECK_TYPE
|
||||
// !LANGUAGE: -AdditionalBuiltInsMembers
|
||||
// SKIP_TXT
|
||||
|
||||
class A : java.util.ArrayList<String>() {
|
||||
<!UNSUPPORTED_FEATURE!>override<!> fun stream(): java.util.stream.Stream<String> = super.<!UNSUPPORTED_FEATURE!>stream<!>()
|
||||
<!UNSUPPORTED_FEATURE!>override<!> fun stream(): java.util.stream.Stream<String> = super.<!DEPRECATION_ERROR!>stream<!>()
|
||||
}
|
||||
|
||||
class A1 : java.util.ArrayList<String>() {
|
||||
// TODO: should be allowed
|
||||
<!VIRTUAL_MEMBER_HIDDEN!>fun stream(): java.util.stream.Stream<String><!> = super.<!UNSUPPORTED_FEATURE!>stream<!>()
|
||||
<!VIRTUAL_MEMBER_HIDDEN!>fun stream(): java.util.stream.Stream<String><!> = super.<!DEPRECATION_ERROR!>stream<!>()
|
||||
}
|
||||
|
||||
class B : <!UNSUPPORTED_FEATURE!>Throwable<!>("", null, false, false)
|
||||
class B : <!DEPRECATION_ERROR!>Throwable<!>("", null, false, false)
|
||||
|
||||
fun foo(x: List<String>) {
|
||||
x.<!UNSUPPORTED_FEATURE!>stream<!>()
|
||||
java.util.ArrayList<String>().<!UNSUPPORTED_FEATURE!>stream<!>()
|
||||
fun Throwable.fillInStackTrace() = 1
|
||||
|
||||
fun foo(x: List<String>, y: Throwable) {
|
||||
x.<!DEPRECATION_ERROR!>stream<!>()
|
||||
java.util.ArrayList<String>().<!DEPRECATION_ERROR!>stream<!>()
|
||||
|
||||
y.fillInStackTrace() checkType { _<Int>() }
|
||||
|
||||
// TODO: Relevant extensions has been removed from stdlib
|
||||
// We should consider reverting their removal
|
||||
y.<!DEPRECATION_ERROR!>printStackTrace<!>()
|
||||
}
|
||||
|
||||
+8
-1
@@ -26,6 +26,9 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -77,7 +80,11 @@ class MultiModuleJavaAnalysisCustomTest : KtUsefulTestCase() {
|
||||
packagePartProviderFactory = { a, b -> JvmPackagePartProvider(environment) }
|
||||
)
|
||||
|
||||
builtIns.initialize(resolverForProject.descriptorForModule(resolverForProject.allModules.first()))
|
||||
builtIns.initialize(
|
||||
resolverForProject.descriptorForModule(resolverForProject.allModules.first()),
|
||||
resolverForProject.resolverForModule(resolverForProject.allModules.first())
|
||||
.componentProvider.get<LanguageVersionSettings>()
|
||||
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
|
||||
|
||||
performChecks(resolverForProject, modules)
|
||||
}
|
||||
|
||||
+43
-4
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
|
||||
import org.jetbrains.kotlin.builtins.BuiltInsInitializer
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||
import org.jetbrains.kotlin.descriptors.annotations.createDeprecatedAnnotation
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.platform.createMappedTypeParametersSubstitution
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
@@ -47,17 +49,20 @@ import org.jetbrains.kotlin.types.LazyWrappedType
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import java.io.Serializable
|
||||
import java.util.*
|
||||
|
||||
open class JvmBuiltInsSettings(
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
storageManager: StorageManager,
|
||||
deferredOwnerModuleDescriptor: () -> ModuleDescriptor
|
||||
deferredOwnerModuleDescriptor: () -> ModuleDescriptor,
|
||||
isAdditionalBuiltInsFeatureSupported: () -> Boolean
|
||||
) : AdditionalClassPartsProvider, PlatformDependentDeclarationFilter {
|
||||
private val j2kClassMap = JavaToKotlinClassMap.INSTANCE
|
||||
|
||||
private val ownerModuleDescriptor: ModuleDescriptor by lazy(deferredOwnerModuleDescriptor)
|
||||
private val isAdditionalBuiltInsFeatureSupported: Boolean by lazy(isAdditionalBuiltInsFeatureSupported)
|
||||
|
||||
private val mockSerializableType = storageManager.createMockJavaIoSerializableType()
|
||||
|
||||
@@ -70,6 +75,28 @@ open class JvmBuiltInsSettings(
|
||||
).let { AnnotationsImpl(listOf(it)) }
|
||||
}
|
||||
|
||||
private val notSupportedDeprecation by storageManager.createLazyValue {
|
||||
// We use both LowPriorityInOverloadResolution to achieve the following goals:
|
||||
// - If there is something to resolve to beside an additional built-in member, it's *almost* always will win
|
||||
// - Otherwise error will be reported because of Deprecated annotation with Error level
|
||||
val lowPriorityAnnotation =
|
||||
ClassDescriptorImpl(
|
||||
moduleDescriptor.getPackage(LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME.parent()),
|
||||
LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME.shortName(), Modality.FINAL, ClassKind.ANNOTATION_CLASS,
|
||||
moduleDescriptor.builtIns.anyType.singletonList(), SourceElement.NO_SOURCE
|
||||
).run {
|
||||
initialize(MemberScope.Empty, emptySet(), null)
|
||||
AnnotationDescriptorImpl(defaultType, emptyMap(), SourceElement.NO_SOURCE)
|
||||
}
|
||||
|
||||
val errorDeprecation = moduleDescriptor.builtIns.createDeprecatedAnnotation(
|
||||
"This member is not supported by Kotlin compiler on this language level",
|
||||
level = DeprecationLevel.ERROR.name
|
||||
)
|
||||
|
||||
AnnotationsImpl(listOf(lowPriorityAnnotation, errorDeprecation))
|
||||
}
|
||||
|
||||
private fun StorageManager.createMockJavaIoSerializableType(): KotlinType {
|
||||
val mockJavaIoPackageFragment = object : PackageFragmentDescriptorImpl(moduleDescriptor, FqName("java.io")) {
|
||||
override fun getMemberScope() = MemberScope.Empty
|
||||
@@ -120,12 +147,21 @@ open class JvmBuiltInsSettings(
|
||||
}
|
||||
|
||||
JDKMemberStatus.NOT_CONSIDERED -> {
|
||||
setAdditionalAnnotations(notConsideredDeprecation)
|
||||
if (!isAdditionalBuiltInsFeatureSupported) {
|
||||
setAdditionalAnnotations(notSupportedDeprecation)
|
||||
}
|
||||
else {
|
||||
setAdditionalAnnotations(notConsideredDeprecation)
|
||||
}
|
||||
}
|
||||
|
||||
JDKMemberStatus.DROP -> return@mapNotNull null
|
||||
|
||||
JDKMemberStatus.WHITE_LIST -> {} // Do nothing
|
||||
JDKMemberStatus.WHITE_LIST -> {
|
||||
if (!isAdditionalBuiltInsFeatureSupported) {
|
||||
setAdditionalAnnotations(notSupportedDeprecation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.build()!!
|
||||
@@ -260,7 +296,10 @@ open class JvmBuiltInsSettings(
|
||||
setPreserveSourceElement()
|
||||
setSubstitution(substitutor.substitution)
|
||||
|
||||
if (SignatureBuildingComponents.signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in WHITE_LIST_CONSTRUCTOR_SIGNATURES) {
|
||||
if (!isAdditionalBuiltInsFeatureSupported) {
|
||||
setAdditionalAnnotations(notSupportedDeprecation)
|
||||
}
|
||||
else if (SignatureBuildingComponents.signature(javaAnalogueDescriptor, javaConstructor.computeJvmDescriptor()) !in WHITE_LIST_CONSTRUCTOR_SIGNATURES) {
|
||||
setAdditionalAnnotations(notConsideredDeprecation)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,12 @@ import org.jetbrains.kotlin.utils.sure
|
||||
class JvmBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManager) {
|
||||
// Module containing JDK classes or having them among dependencies
|
||||
private var ownerModuleDescriptor: ModuleDescriptor? = null
|
||||
private var isAdditionalBuiltInsFeatureSupported: Boolean = true
|
||||
|
||||
fun initialize(moduleDescriptor: ModuleDescriptor) {
|
||||
fun initialize(moduleDescriptor: ModuleDescriptor, isAdditionalBuiltInsFeatureSupported: Boolean) {
|
||||
assert(ownerModuleDescriptor == null) { "JvmBuiltins repeated initialization" }
|
||||
this.ownerModuleDescriptor = moduleDescriptor
|
||||
this.isAdditionalBuiltInsFeatureSupported = isAdditionalBuiltInsFeatureSupported
|
||||
}
|
||||
|
||||
lateinit var settings: JvmBuiltInsSettings
|
||||
@@ -39,7 +41,8 @@ class JvmBuiltIns(storageManager: StorageManager) : KotlinBuiltIns(storageManage
|
||||
override fun getPlatformDependentDeclarationFilter(): PlatformDependentDeclarationFilter {
|
||||
settings = JvmBuiltInsSettings(
|
||||
builtInsModule, storageManager,
|
||||
{ ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } }
|
||||
{ ownerModuleDescriptor.sure { "JvmBuiltins has not been initialized properly" } },
|
||||
{ isAdditionalBuiltInsFeatureSupported }
|
||||
)
|
||||
|
||||
return settings
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class RuntimeModuleData private constructor(val deserialization: Deserialization
|
||||
|
||||
val lazyJavaPackageFragmentProvider = LazyJavaPackageFragmentProvider(globalJavaResolverContext)
|
||||
|
||||
builtIns.initialize(module)
|
||||
builtIns.initialize(module, isAdditionalBuiltInsFeatureSupported = true)
|
||||
|
||||
val javaDescriptorResolver = JavaDescriptorResolver(lazyJavaPackageFragmentProvider, javaResolverCache)
|
||||
val javaClassDataFinder = JavaClassDataFinder(reflectKotlinClassFinder, deserializedDescriptorResolver)
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
private val NO_INFER_ANNOTATION_FQ_NAME = FqName("kotlin.internal.NoInfer")
|
||||
private val EXACT_ANNOTATION_FQ_NAME = FqName("kotlin.internal.Exact")
|
||||
private val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.internal.LowPriorityInOverloadResolution")
|
||||
val LOW_PRIORITY_IN_OVERLOAD_RESOLUTION_FQ_NAME = FqName("kotlin.internal.LowPriorityInOverloadResolution")
|
||||
private val HIDES_MEMBERS_ANNOTATION_FQ_NAME = FqName("kotlin.internal.HidesMembers")
|
||||
private val ONLY_INPUT_TYPES_FQ_NAME = FqName("kotlin.internal.OnlyInputTypes")
|
||||
|
||||
@@ -65,4 +65,4 @@ private class AnnotationsWithOnly(val presentAnnotation: FqName): Annotations {
|
||||
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = emptyList()
|
||||
|
||||
override fun getAllAnnotations(): List<AnnotationWithTarget> = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -32,6 +32,9 @@ import org.jetbrains.kotlin.analyzer.EmptyResolverForProject
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.container.get
|
||||
import org.jetbrains.kotlin.container.getService
|
||||
import org.jetbrains.kotlin.context.GlobalContext
|
||||
import org.jetbrains.kotlin.context.GlobalContextImpl
|
||||
@@ -381,9 +384,12 @@ private fun globalResolveSessionProvider(
|
||||
|
||||
if (newBuiltIns is JvmBuiltIns) {
|
||||
val sdkInfo = SdkInfo(project, sdk!!)
|
||||
newBuiltIns.initialize(moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo))
|
||||
newBuiltIns.initialize(
|
||||
moduleResolverProvider.resolverForProject.descriptorForModule(sdkInfo),
|
||||
moduleResolverProvider.resolverForProject.resolverForModule(sdkInfo)
|
||||
.componentProvider.get<LanguageVersionSettings>()
|
||||
.supportsFeature(LanguageFeature.AdditionalBuiltInsMembers))
|
||||
}
|
||||
|
||||
moduleResolverProvider
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user