Minor: refactoring replaceWith package

This commit is contained in:
Dmitry Gridin
2019-03-27 16:23:31 +07:00
parent c343876f7c
commit b0f7ddd693
5 changed files with 55 additions and 57 deletions
@@ -41,7 +41,7 @@ class DeprecatedSymbolUsageFix(
override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) { override fun invoke(replacementStrategy: UsageReplacementStrategy, project: Project, editor: Editor?) {
val element = element ?: return val element = element ?: return
val result = replacementStrategy.createReplacer(element)!!.invoke() val result = replacementStrategy.createReplacer(element)?.invoke()
if (result != null) { if (result != null) {
val offset = (result.getCalleeExpressionIfAny() ?: result).textOffset val offset = (result.getCalleeExpressionIfAny() ?: result).textOffset
editor?.moveCaret(offset) editor?.moveCaret(offset)
@@ -50,7 +50,7 @@ class DeprecatedSymbolUsageFix(
companion object : KotlinSingleIntentionActionFactory() { companion object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? { override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val (nameExpression, replacement) = DeprecatedSymbolUsageFixBase.extractDataFromDiagnostic(diagnostic) ?: return null val (nameExpression, replacement) = extractDataFromDiagnostic(diagnostic) ?: return null
return DeprecatedSymbolUsageFix(nameExpression, replacement) return DeprecatedSymbolUsageFix(nameExpression, replacement)
} }
@@ -61,7 +61,7 @@ class DeprecatedSymbolUsageFix(
if (targetDescriptors.isEmpty()) return false if (targetDescriptors.isEmpty()) return false
return targetDescriptors.all { return targetDescriptors.all {
DeprecatedSymbolUsageFixBase.fetchReplaceWithPattern(it, import.project) != null fetchReplaceWithPattern(it, import.project) != null
} }
} }
} }
@@ -120,7 +120,7 @@ abstract class DeprecatedSymbolUsageFixBase(
else -> throw IllegalStateException("Bad QuickFixRegistrar configuration") else -> throw IllegalStateException("Bad QuickFixRegistrar configuration")
} }
val replacement = DeprecatedSymbolUsageFixBase.fetchReplaceWithPattern(descriptor, nameExpression.project) ?: return null val replacement = fetchReplaceWithPattern(descriptor, nameExpression.project) ?: return null
return Data(nameExpression, replacement, descriptor) return Data(nameExpression, replacement, descriptor)
} }
@@ -135,10 +135,10 @@ abstract class DeprecatedSymbolUsageFixBase(
val bindingContext = resolutionFacade.analyze(element, BodyResolveMode.PARTIAL) val bindingContext = resolutionFacade.analyze(element, BodyResolveMode.PARTIAL)
var target = element.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return null var target = element.mainReference.resolveToDescriptors(bindingContext).singleOrNull() ?: return null
var replacePatternFromSymbol = DeprecatedSymbolUsageFixBase.fetchReplaceWithPattern(target, resolutionFacade.project) var replacePatternFromSymbol = fetchReplaceWithPattern(target, resolutionFacade.project)
if (replacePatternFromSymbol == null && target is ConstructorDescriptor) { if (replacePatternFromSymbol == null && target is ConstructorDescriptor) {
target = target.containingDeclaration target = target.containingDeclaration
replacePatternFromSymbol = DeprecatedSymbolUsageFixBase.fetchReplaceWithPattern(target, resolutionFacade.project) replacePatternFromSymbol = fetchReplaceWithPattern(target, resolutionFacade.project)
} }
// check that ReplaceWith hasn't changed // check that ReplaceWith hasn't changed
@@ -207,7 +207,7 @@ abstract class DeprecatedSymbolUsageFixBase(
project: Project, classifier: ClassifierDescriptorWithTypeParameters, typeAlias: PsiElement project: Project, classifier: ClassifierDescriptorWithTypeParameters, typeAlias: PsiElement
): ConstructorDescriptor? { ): ConstructorDescriptor? {
val specialReplaceWithForConstructor = classifier.constructors.filter { val specialReplaceWithForConstructor = classifier.constructors.filter {
DeprecatedSymbolUsageFixBase.fetchReplaceWithPattern(it, project) != null fetchReplaceWithPattern(it, project) != null
}.toSet() }.toSet()
if (specialReplaceWithForConstructor.isEmpty()) { if (specialReplaceWithForConstructor.isEmpty()) {
@@ -77,8 +77,7 @@ class DeprecatedSymbolUsageInWholeProjectFix(
} }
override fun createAction(diagnostic: Diagnostic): IntentionAction? { override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val (nameExpression, replacement, descriptor) = val (nameExpression, replacement, descriptor) = extractDataFromDiagnostic(diagnostic) ?: return null
DeprecatedSymbolUsageFixBase.extractDataFromDiagnostic(diagnostic) ?: return null
val descriptorName = RENDERER.render(descriptor) val descriptorName = RENDERER.render(descriptor)
return DeprecatedSymbolUsageInWholeProjectFix( return DeprecatedSymbolUsageInWholeProjectFix(
nameExpression, nameExpression,
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
import org.jetbrains.kotlin.idea.quickfix.replaceWith.ReplaceProtectedToPublishedApiCallFix.Companion.newName
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -40,42 +39,42 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
class ReplaceProtectedToPublishedApiCallFix( class ReplaceProtectedToPublishedApiCallFix(
element: KtExpression, element: KtExpression,
val classOwnerPointer: SmartPsiElementPointer<KtClass>, val classOwnerPointer: SmartPsiElementPointer<KtClass>,
val originalName: String, val originalName: String,
val paramNames: Map<String, String>, val paramNames: Map<String, String>,
val newSignature: String, val newSignature: String,
val isProperty: Boolean, val isProperty: Boolean,
val isVar: Boolean, val isVar: Boolean,
val isPublishedMemberAlreadyExists: Boolean val isPublishedMemberAlreadyExists: Boolean
) : KotlinQuickFixAction<KtExpression>(element) { ) : KotlinQuickFixAction<KtExpression>(element) {
override fun getFamilyName() = "Replace with @PublishedApi bridge call" override fun getFamilyName() = "Replace with @PublishedApi bridge call"
override fun getText() = "Replace with generated @PublishedApi bridge call '${originalName.newNameQuoted}${if (!isProperty) "(...)" else ""}'" override fun getText() =
"Replace with generated @PublishedApi bridge call '${originalName.newNameQuoted}${if (!isProperty) "(...)" else ""}'"
override fun invoke(project: Project, editor: Editor?, file: KtFile) { override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return val element = element ?: return
if (!isPublishedMemberAlreadyExists) { if (!isPublishedMemberAlreadyExists) {
val classOwner = classOwnerPointer.element ?: return val classOwner = classOwnerPointer.element ?: return
val newMember: KtDeclaration = val newMember: KtDeclaration =
if (isProperty) { if (isProperty) {
KtPsiFactory(classOwner).createProperty( KtPsiFactory(classOwner).createProperty(
"@kotlin.PublishedApi\n" + "@kotlin.PublishedApi\n" +
"internal " + newSignature + "internal " + newSignature +
"\n" + "\n" +
"get() = $originalName\n" + "get() = $originalName\n" +
if (isVar) "set(value) { $originalName = value }" else "" if (isVar) "set(value) { $originalName = value }" else ""
) )
} } else {
else { KtPsiFactory(classOwner).createFunction(
KtPsiFactory(classOwner).createFunction( "@kotlin.PublishedApi\n" +
"@kotlin.PublishedApi\n" +
"internal " + newSignature + "internal " + newSignature +
" = $originalName(${paramNames.keys.joinToString(", ") { it }})" " = $originalName(${paramNames.keys.joinToString(", ") { it }})"
) )
} }
ShortenReferences.DEFAULT.process(classOwner.addDeclaration(newMember)) ShortenReferences.DEFAULT.process(classOwner.addDeclaration(newMember))
} }
@@ -100,13 +99,12 @@ class ReplaceProtectedToPublishedApiCallFix(
val signature = signatureRenderer.render(descriptor) val signature = signatureRenderer.render(descriptor)
val originalName = descriptor.name.asString() val originalName = descriptor.name.asString()
val newSignature = val newSignature =
if (isProperty) { if (isProperty) {
signature.replaceFirst("$originalName:", "${originalName.newNameQuoted}:") signature.replaceFirst("$originalName:", "${originalName.newNameQuoted}:")
} } else {
else { signature.replaceFirst("$originalName(", "${originalName.newNameQuoted}(")
signature.replaceFirst("$originalName(", "${originalName.newNameQuoted}(") }
} val paramNameAndType = descriptor.valueParameters.associate { it.name.asString() to it.type.getJetTypeFqName(false) }
val paramNameAndType = descriptor.valueParameters.associate { it.name.asString() to it.type.getJetTypeFqName(false)}
val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null val classDescriptor = descriptor.containingDeclaration as? ClassDescriptor ?: return null
val source = classDescriptor.source.getPsi() as? KtClass ?: return null val source = classDescriptor.source.getPsi() as? KtClass ?: return null
@@ -119,8 +117,8 @@ class ReplaceProtectedToPublishedApiCallFix(
} }
return ReplaceProtectedToPublishedApiCallFix( return ReplaceProtectedToPublishedApiCallFix(
psiElement, source.createSmartPointer(), originalName, paramNameAndType, newSignature, psiElement, source.createSmartPointer(), originalName, paramNameAndType, newSignature,
isProperty, isVar, isPublishedMemberAlreadyExists isProperty, isVar, isPublishedMemberAlreadyExists
) )
} }
@@ -128,6 +126,6 @@ class ReplaceProtectedToPublishedApiCallFix(
get() = "access\$$this" get() = "access\$$this"
val String.newNameQuoted: String val String.newNameQuoted: String
get() = "`$newName`" get() = "`$newName`"
} }
} }
@@ -72,14 +72,7 @@ object ReplaceWithAnnotationAnalyzer {
} }
val module = resolutionFacade.moduleDescriptor val module = resolutionFacade.moduleDescriptor
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module) val scope = buildScope(resolutionFacade, annotation, symbolDescriptor) ?: return null
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val defaultImportsScopes = buildDefaultImportsScopes(resolutionFacade, module, languageVersionSettings)
val scope = getResolutionScope(
symbolDescriptor, symbolDescriptor,
listOf(explicitImportsScope), defaultImportsScopes, languageVersionSettings
) ?: return null
val expressionTypingServices = resolutionFacade.getFrontendService(module, ExpressionTypingServices::class.java) val expressionTypingServices = resolutionFacade.getFrontendService(module, ExpressionTypingServices::class.java)
@@ -102,14 +95,7 @@ object ReplaceWithAnnotationAnalyzer {
} }
if (typeReference.typeElement !is KtUserType) return null if (typeReference.typeElement !is KtUserType) return null
val module = resolutionFacade.moduleDescriptor val scope = buildScope(resolutionFacade, annotation, symbolDescriptor) ?: return null
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val defaultImportScopes = buildDefaultImportsScopes(resolutionFacade, module, languageVersionSettings)
val scope = getResolutionScope(
symbolDescriptor, symbolDescriptor, listOf(explicitImportsScope), defaultImportScopes, languageVersionSettings
) ?: return null
val typeResolver = resolutionFacade.getFrontendService(TypeResolver::class.java) val typeResolver = resolutionFacade.getFrontendService(TypeResolver::class.java)
val bindingTrace = BindingTraceContext() val bindingTrace = BindingTraceContext()
@@ -121,7 +107,7 @@ object ReplaceWithAnnotationAnalyzer {
val parentType = expression.parent as? KtUserType ?: return@forEachDescendantOfType val parentType = expression.parent as? KtUserType ?: return@forEachDescendantOfType
if (parentType.qualifier != null) return@forEachDescendantOfType if (parentType.qualifier != null) return@forEachDescendantOfType
val targetClass = bindingTrace.bindingContext[BindingContext.REFERENCE_TARGET, expression] as? ClassDescriptor val targetClass = bindingTrace.bindingContext[BindingContext.REFERENCE_TARGET, expression] as? ClassDescriptor
?: return@forEachDescendantOfType ?: return@forEachDescendantOfType
val fqName = targetClass.fqNameUnsafe val fqName = targetClass.fqNameUnsafe
if (fqName.isSafe) { if (fqName.isSafe) {
typesToQualify.add(expression to fqName.toSafe()) typesToQualify.add(expression to fqName.toSafe())
@@ -135,6 +121,21 @@ object ReplaceWithAnnotationAnalyzer {
return typeReference.typeElement as KtUserType return typeReference.typeElement as KtUserType
} }
private fun buildScope(
resolutionFacade: ResolutionFacade,
annotation: ReplaceWith,
symbolDescriptor: DeclarationDescriptor
): LexicalScope? {
val module = resolutionFacade.moduleDescriptor
val explicitImportsScope = buildExplicitImportsScope(annotation, resolutionFacade, module)
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val defaultImportsScopes = buildDefaultImportsScopes(resolutionFacade, module, languageVersionSettings)
return getResolutionScope(
symbolDescriptor, symbolDescriptor, listOf(explicitImportsScope), defaultImportsScopes, languageVersionSettings
)
}
private fun buildDefaultImportsScopes( private fun buildDefaultImportsScopes(
resolutionFacade: ResolutionFacade, resolutionFacade: ResolutionFacade,
module: ModuleDescriptor, module: ModuleDescriptor,