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:
Dmitry Savvinov
2017-12-14 18:59:32 +03:00
parent acd8edaa9c
commit d570b863ce
117 changed files with 8027 additions and 113 deletions
@@ -128,6 +128,7 @@ class KotlinImportOptimizer : ImportOptimizer {
is ClassDescriptor ->
scope.findClassifier(target.name, NoLookupLocation.FROM_IDE) == target
&& bindingContext[BindingContext.DEPRECATED_SHORT_NAME_ACCESS, place] != true
else -> false
}
@@ -0,0 +1,52 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile
internal class AddExplicitImportForDeprecatedVisibilityFix(expression: KtElement, private val targetFqName: FqName) : KotlinQuickFixAction<KtElement>(expression) {
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val targetDescriptor = file.resolveImportReference(targetFqName).singleOrNull() ?: return
ImportInsertHelper.getInstance(project).importDescriptor(file, targetDescriptor)
}
override fun getFamilyName(): String = text
override fun getText(): String = "Add explicit import"
object Factory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
if (diagnostic.factory != Errors.DEPRECATED_ACCESS_BY_SHORT_NAME) return null
val castedDiagnostic = Errors.DEPRECATED_ACCESS_BY_SHORT_NAME.cast(diagnostic)
val soonToBeDeprecatedType = castedDiagnostic.psiElement
val importableFqNameOfTargetDescriptor = castedDiagnostic.a.importableFqName ?: return null
return AddExplicitImportForDeprecatedVisibilityFix(soonToBeDeprecatedType, importableFqNameOfTargetDescriptor)
}
}
}
@@ -144,6 +144,7 @@ class QuickFixRegistrar : QuickFixContributor {
UNRESOLVED_REFERENCE.registerFactory(ImportFix)
UNRESOLVED_REFERENCE.registerFactory(ImportConstructorReferenceFix)
DEPRECATED_ACCESS_BY_SHORT_NAME.registerFactory(AddExplicitImportForDeprecatedVisibilityFix.Factory)
TOO_MANY_ARGUMENTS.registerFactory(ImportForMismatchingArgumentsFix)
NO_VALUE_FOR_PARAMETER.registerFactory(ImportForMismatchingArgumentsFix)
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.quickfix.replaceWith
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
@@ -75,8 +76,10 @@ object ReplaceWithAnnotationAnalyzer {
val module = resolutionFacade.moduleDescriptor
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val defaultImportsScopes = buildDefaultImportsScopes(resolutionFacade, module)
val languageVersionSettings = resolutionFacade.getFrontendService(LanguageVersionSettings::class.java)
val scope = getResolutionScope(symbolDescriptor, symbolDescriptor,
listOf(explicitImportsScope) + defaultImportsScopes) ?: return null
listOf(explicitImportsScope) + defaultImportsScopes, languageVersionSettings) ?: return null
val expressionTypingServices = resolutionFacade.getFrontendService(module, ExpressionTypingServices::class.java)
@@ -104,7 +107,12 @@ object ReplaceWithAnnotationAnalyzer {
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val defaultImportScopes = buildDefaultImportsScopes(resolutionFacade, module)
val scope = getResolutionScope(symbolDescriptor, symbolDescriptor, listOf(explicitImportsScope) + defaultImportScopes) ?: return null
val scope = getResolutionScope(
symbolDescriptor,
symbolDescriptor,
listOf(explicitImportsScope) + defaultImportScopes,
resolutionFacade.getFrontendService(LanguageVersionSettings::class.java)
) ?: return null
val typeResolver = resolutionFacade.getFrontendService(TypeResolver::class.java)
val bindingTrace = BindingTraceContext()
@@ -155,11 +163,16 @@ object ReplaceWithAnnotationAnalyzer {
.map(FqNameUnsafe::toSafe)
}
private fun getResolutionScope(descriptor: DeclarationDescriptor, ownerDescriptor: DeclarationDescriptor, additionalScopes: Collection<ImportingScope>): LexicalScope? {
private fun getResolutionScope(
descriptor: DeclarationDescriptor,
ownerDescriptor: DeclarationDescriptor,
additionalScopes: Collection<ImportingScope>,
languageVersionSettings: LanguageVersionSettings
): LexicalScope? {
return when (descriptor) {
is PackageFragmentDescriptor -> {
val moduleDescriptor = descriptor.containingDeclaration
getResolutionScope(moduleDescriptor.getPackage(descriptor.fqName), ownerDescriptor, additionalScopes)
getResolutionScope(moduleDescriptor.getPackage(descriptor.fqName), ownerDescriptor, additionalScopes, languageVersionSettings)
}
is PackageViewDescriptor -> {
@@ -169,12 +182,12 @@ object ReplaceWithAnnotationAnalyzer {
}
is ClassDescriptor -> {
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes) ?: return null
ClassResolutionScopesSupport(descriptor, LockBasedStorageManager.NO_LOCKS, { outerScope }).scopeForMemberDeclarationResolution()
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes, languageVersionSettings) ?: return null
ClassResolutionScopesSupport(descriptor, LockBasedStorageManager.NO_LOCKS, languageVersionSettings, { outerScope }).scopeForMemberDeclarationResolution()
}
is TypeAliasDescriptor -> {
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes) ?: return null
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes, languageVersionSettings) ?: return null
LexicalScopeImpl(outerScope, descriptor, false, null, LexicalScopeKind.TYPE_ALIAS_HEADER, LocalRedeclarationChecker.DO_NOTHING) {
for (typeParameter in descriptor.declaredTypeParameters) {
addClassifierDescriptor(typeParameter)
@@ -183,12 +196,12 @@ object ReplaceWithAnnotationAnalyzer {
}
is FunctionDescriptor -> {
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes) ?: return null
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes, languageVersionSettings) ?: return null
FunctionDescriptorUtil.getFunctionInnerScope(outerScope, descriptor, LocalRedeclarationChecker.DO_NOTHING)
}
is PropertyDescriptor -> {
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes) ?: return null
val outerScope = getResolutionScope(descriptor.containingDeclaration, ownerDescriptor, additionalScopes, languageVersionSettings) ?: return null
val propertyHeader = ScopeUtils.makeScopeForPropertyHeader(outerScope, descriptor)
LexicalScopeImpl(propertyHeader, descriptor, false, descriptor.extensionReceiverParameter, LexicalScopeKind.PROPERTY_ACCESSOR_BODY)
}