Introduce deprecation of companion objects nested classes
Introdude deprecation as per KT-21515. Warning is reported on type usage, that soon will became invisible. Quickfix by adding explicit import is added. Idea behind implementation is to mark scopes that are deprecated (see ClassResolutionScopesSupport). Then, during walk along hierarchy of scopes, look at deprecation status of the scope that has provided this classifier. Note that we also have to check if there are *some* non-deprecated visibility paths (because we can see classifier by two paths, e.g. if we've added explicit import) -- then this type reference shouldn't be treated as deprecated.
This commit is contained in:
+3
-3
@@ -24,9 +24,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.model.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.SyntheticScopes
|
||||
import org.jetbrains.kotlin.resolve.scopes.*
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -110,3 +108,5 @@ object HiddenDescriptor : ResolutionDiagnostic(HIDDEN)
|
||||
object InvokeConventionCallNoOperatorModifier : ResolutionDiagnostic(CONVENTION_ERROR)
|
||||
object InfixCallNoInfixModifier : ResolutionDiagnostic(CONVENTION_ERROR)
|
||||
object DeprecatedUnaryPlusAsPlus : ResolutionDiagnostic(CONVENTION_ERROR)
|
||||
|
||||
class ResolvedUsingDeprecatedVisbility(val baseSourceScope: ResolutionScope, val lookupLocation: LookupLocation) : ResolutionDiagnostic(RESOLVED)
|
||||
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
internal abstract class AbstractScopeTowerLevel(
|
||||
protected val scopeTower: ImplicitScopeTower
|
||||
@@ -201,15 +201,14 @@ internal class QualifierScopeTowerLevel(scopeTower: ImplicitScopeTower, val qual
|
||||
|
||||
override fun getObjects(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
|
||||
.getContributedObjectVariables(name, location).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name, extensionReceiver: ReceiverValueWithSmartCastInfo?) = qualifier.staticScope
|
||||
.getContributedFunctionsAndConstructors(
|
||||
name,
|
||||
location,
|
||||
scopeTower.syntheticScopes,
|
||||
qualifier.staticScope
|
||||
scopeTower.syntheticScopes
|
||||
).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
@@ -235,20 +234,37 @@ internal open class ScopeBasedTowerLevel protected constructor(
|
||||
override fun getObjects(
|
||||
name: Name,
|
||||
extensionReceiver: ReceiverValueWithSmartCastInfo?
|
||||
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedObjectVariables(name, location).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
}
|
||||
): Collection<CandidateWithBoundDispatchReceiver> =
|
||||
resolutionScope.getContributedObjectVariablesIncludeDeprecated(name, location).map { (classifier, isDeprecated) ->
|
||||
createCandidateDescriptor(
|
||||
classifier,
|
||||
dispatchReceiver = null,
|
||||
specialError = if (isDeprecated) ResolvedUsingDeprecatedVisbility(resolutionScope, location) else null
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFunctions(
|
||||
name: Name,
|
||||
extensionReceiver: ReceiverValueWithSmartCastInfo?
|
||||
): Collection<CandidateWithBoundDispatchReceiver> = resolutionScope.getContributedFunctionsAndConstructors(
|
||||
name,
|
||||
location,
|
||||
scopeTower.syntheticScopes,
|
||||
resolutionScope
|
||||
).map {
|
||||
createCandidateDescriptor(it, dispatchReceiver = null)
|
||||
): Collection<CandidateWithBoundDispatchReceiver> {
|
||||
val result: ArrayList<CandidateWithBoundDispatchReceiver> = ArrayList()
|
||||
|
||||
resolutionScope.getContributedFunctionsAndConstructors(name, location, scopeTower.syntheticScopes)
|
||||
.mapTo(result) { createCandidateDescriptor(it, dispatchReceiver = null) }
|
||||
|
||||
// Add constructors of deprecated classifier with an additional diagnostic
|
||||
val descriptorWithDeprecation = resolutionScope.getContributedClassifierIncludeDeprecated(name, location)
|
||||
if (descriptorWithDeprecation != null && descriptorWithDeprecation.isDeprecated) {
|
||||
getConstructorsOfClassifier(descriptorWithDeprecation.descriptor).mapTo(result) {
|
||||
createCandidateDescriptor(
|
||||
it,
|
||||
dispatchReceiver = null,
|
||||
specialError = ResolvedUsingDeprecatedVisbility(resolutionScope, location)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun recordLookup(name: Name) {
|
||||
@@ -339,32 +355,41 @@ private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocatio
|
||||
private fun ResolutionScope.getContributedFunctionsAndConstructors(
|
||||
name: Name,
|
||||
location: LookupLocation,
|
||||
syntheticScopes: SyntheticScopes,
|
||||
scope: ResolutionScope
|
||||
syntheticScopes: SyntheticScopes
|
||||
): Collection<FunctionDescriptor> {
|
||||
val result = ArrayList<FunctionDescriptor>(getContributedFunctions(name, location))
|
||||
|
||||
val classifier = getContributedClassifier(name, location)
|
||||
getContributedClassifier(name, location)?.let {
|
||||
result.addAll(getConstructorsOfClassifier(it))
|
||||
}
|
||||
|
||||
result.addAll(syntheticScopes.collectSyntheticStaticFunctions(this, name, location))
|
||||
result.addAll(syntheticScopes.collectSyntheticConstructors(this, name, location))
|
||||
|
||||
return result.toList()
|
||||
}
|
||||
|
||||
private fun getConstructorsOfClassifier(classifier: ClassifierDescriptor?): List<ConstructorDescriptor> {
|
||||
val callableConstructors = when (classifier) {
|
||||
is TypeAliasDescriptor -> if (classifier.canHaveCallableConstructors) classifier.constructors else emptyList()
|
||||
is ClassDescriptor -> if (classifier.canHaveCallableConstructors) classifier.constructors else emptyList()
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
callableConstructors.filterTo(result) { it.dispatchReceiverParameter == null }
|
||||
|
||||
result.addAll(syntheticScopes.collectSyntheticStaticFunctions(scope, name, location))
|
||||
result.addAll(syntheticScopes.collectSyntheticConstructors(scope, name, location))
|
||||
|
||||
return result.toList()
|
||||
return callableConstructors.filter { it.dispatchReceiverParameter == null }
|
||||
}
|
||||
|
||||
|
||||
private fun ResolutionScope.getContributedObjectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> {
|
||||
val objectDescriptor = getFakeDescriptorForObject(getContributedClassifier(name, location))
|
||||
return listOfNotNull(objectDescriptor)
|
||||
}
|
||||
|
||||
private fun ResolutionScope.getContributedObjectVariablesIncludeDeprecated(name: Name, location: LookupLocation): Collection<DescriptorWithDeprecation<VariableDescriptor>> {
|
||||
val (classifier, isOwnerDeprecated) = getContributedClassifierIncludeDeprecated(name, location) ?: return emptyList()
|
||||
val objectDescriptor = getFakeDescriptorForObject(classifier) ?: return emptyList()
|
||||
return listOf(DescriptorWithDeprecation(objectDescriptor, isOwnerDeprecated))
|
||||
}
|
||||
|
||||
fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeCallableDescriptorForObject? =
|
||||
when (classifier) {
|
||||
is TypeAliasDescriptor ->
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorWithDeprecation
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class DeprecatedLexicalScope(private val workerScope: LexicalScope) : LexicalScope by workerScope {
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
|
||||
|
||||
override fun getContributedClassifierIncludeDeprecated(
|
||||
name: Name,
|
||||
location: LookupLocation
|
||||
): DescriptorWithDeprecation<ClassifierDescriptor>? {
|
||||
return workerScope.getContributedClassifier(name, location)?.let { DescriptorWithDeprecation.createDeprecated(it) }
|
||||
}
|
||||
}
|
||||
|
||||
class DeprecatedMemberScope(private val workerScope: MemberScope) : MemberScope by workerScope {
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = null
|
||||
|
||||
override fun getContributedClassifierIncludeDeprecated(
|
||||
name: Name,
|
||||
location: LookupLocation
|
||||
): DescriptorWithDeprecation<ClassifierDescriptor>? {
|
||||
return workerScope.getContributedClassifier(name, location)?.let { DescriptorWithDeprecation.createDeprecated(it) }
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorWithDeprecation
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -24,6 +26,7 @@ import org.jetbrains.kotlin.resolve.scopes.utils.takeSnapshot
|
||||
import org.jetbrains.kotlin.util.collectionUtils.getFirstClassifierDiscriminateHeaders
|
||||
import org.jetbrains.kotlin.util.collectionUtils.getFromAllScopes
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class LexicalChainedScope @JvmOverloads constructor(
|
||||
parent: LexicalScope,
|
||||
@@ -31,6 +34,8 @@ class LexicalChainedScope @JvmOverloads constructor(
|
||||
override val isOwnerDescriptorAccessibleByLabel: Boolean,
|
||||
override val implicitReceiver: ReceiverParameterDescriptor?,
|
||||
override val kind: LexicalScopeKind,
|
||||
// NB. Here can be very special subtypes of MemberScope (e.g., DeprecatedMemberScope).
|
||||
// Please, do not leak them outside of LexicalChainedScope, because other parts of compiler are not ready to work with them
|
||||
private val memberScopes: List<MemberScope>,
|
||||
@Deprecated("This value is temporary hack for resolve -- don't use it!")
|
||||
val isStaticScope: Boolean = false
|
||||
@@ -43,6 +48,22 @@ class LexicalChainedScope @JvmOverloads constructor(
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) =
|
||||
getFirstClassifierDiscriminateHeaders(memberScopes) { it.getContributedClassifier(name, location) }
|
||||
|
||||
override fun getContributedClassifierIncludeDeprecated(name: Name, location: LookupLocation): DescriptorWithDeprecation<ClassifierDescriptor>? {
|
||||
val (firstClassifier, isFirstDeprecated) = memberScopes.firstNotNullResult {
|
||||
it.getContributedClassifierIncludeDeprecated(name, location)
|
||||
} ?: return null
|
||||
|
||||
if (!isFirstDeprecated) return DescriptorWithDeprecation.createNonDeprecated(firstClassifier)
|
||||
|
||||
// Slow-path: try to find the same classifier, but without deprecation
|
||||
for (scope in memberScopes) {
|
||||
val (descriptor, isDeprecated) = scope.getContributedClassifierIncludeDeprecated(name, location) ?: continue
|
||||
if (descriptor == firstClassifier && !isDeprecated) return DescriptorWithDeprecation.createNonDeprecated(descriptor)
|
||||
}
|
||||
|
||||
return DescriptorWithDeprecation.createDeprecated(firstClassifier)
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation) =
|
||||
getFromAllScopes(memberScopes) { it.getContributedVariables(name, location) }
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class LexicalWritableScope(
|
||||
parent: LexicalScope,
|
||||
@@ -74,6 +75,18 @@ class LexicalWritableScope(
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) =
|
||||
variableOrClassDescriptorByName(name, descriptorLimit) as? ClassifierDescriptor
|
||||
|
||||
// NB. This is important to have this explicit override, otherwise calls will be delegated to `this`-delegate,
|
||||
// which will use default implementation from `ResolutionScope`, which will call `getContributedClassifier` on
|
||||
// the `LexicalWritableScope` instead of calling it on this snapshot
|
||||
override fun getContributedClassifierIncludeDeprecated(
|
||||
name: Name,
|
||||
location: LookupLocation
|
||||
): DescriptorWithDeprecation<ClassifierDescriptor>? {
|
||||
return variableOrClassDescriptorByName(name, descriptorLimit)
|
||||
?.safeAs<ClassifierDescriptor>()
|
||||
?.let { DescriptorWithDeprecation.createNonDeprecated(it) }
|
||||
}
|
||||
|
||||
override fun getContributedVariables(name: Name, location: LookupLocation) =
|
||||
listOfNotNull(variableOrClassDescriptorByName(name, descriptorLimit) as? VariableDescriptor)
|
||||
|
||||
|
||||
@@ -81,6 +81,22 @@ fun LexicalScope.findLocalVariable(name: Name): VariableDescriptor? {
|
||||
fun HierarchicalScope.findClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
|
||||
findFirstFromMeAndParent { it.getContributedClassifier(name, location) }
|
||||
|
||||
fun DeclarationDescriptor.canBeResolvedWithoutDeprecation(
|
||||
scopeForResolution: HierarchicalScope,
|
||||
location: LookupLocation
|
||||
): Boolean {
|
||||
for (scope in scopeForResolution.parentsWithSelf) {
|
||||
val (descriptorFromCurrentScope, isDeprecated) = scope.getContributedClassifierIncludeDeprecated(name, location) ?: continue
|
||||
if (descriptorFromCurrentScope == this && !isDeprecated) return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun HierarchicalScope.findFirstClassifierWithDeprecationStatus(name: Name, location: LookupLocation): DescriptorWithDeprecation<ClassifierDescriptor>? {
|
||||
return findFirstFromMeAndParent { it.getContributedClassifierIncludeDeprecated(name, location) }
|
||||
}
|
||||
|
||||
fun HierarchicalScope.findPackage(name: Name): PackageViewDescriptor? = findFirstFromImportingScopes { it.getContributedPackage(name) }
|
||||
|
||||
fun HierarchicalScope.collectVariables(name: Name, location: LookupLocation): Collection<VariableDescriptor> =
|
||||
|
||||
Reference in New Issue
Block a user