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:
@@ -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
|
||||
}
|
||||
|
||||
+52
@@ -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)
|
||||
|
||||
+22
-9
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user