提交 a9f19c4a 编写于 作者: M Mark Punzalan 提交者: Ilya Kirillov

FIR IDE: Move ChangeVariableMutabilityFix to idea-frontend-independent.

上级 79622248
......@@ -61,4 +61,8 @@ find.usages.type.super.type.qualifier=Super type qualifier
find.usages.type.receiver=Receiver
find.usages.type.delegate=Delegate
find.usages.type.packageDirective=Package directive
find.usages.type.packageMemberAccess=Package member access
\ No newline at end of file
find.usages.type.packageMemberAccess=Package member access
and.delete.initializer=\ and delete initializer
change.to.val=Change to val
change.to.var=Change to var
\ No newline at end of file
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.idea.quickfix
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
class ChangeVariableMutabilityFix(
element: KtValVarKeywordOwner,
private val makeVar: Boolean,
private val actionText: String? = null,
private val deleteInitializer: Boolean = false
) : KotlinPsiOnlyQuickFixAction<KtValVarKeywordOwner>(element) {
override fun getText() = actionText
?: (if (makeVar) KotlinBundleIndependent.message("change.to.var") else KotlinBundleIndependent.message("change.to.val")) +
if (deleteInitializer) KotlinBundleIndependent.message("and.delete.initializer") else ""
override fun getFamilyName(): String = text
override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
val element = element ?: return false
val valOrVar = element.valOrVarKeyword?.node?.elementType ?: return false
return (valOrVar == KtTokens.VAR_KEYWORD) != makeVar
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val factory = KtPsiFactory(project)
val newKeyword = if (makeVar) factory.createVarKeyword() else factory.createValKeyword()
element.valOrVarKeyword!!.replace(newKeyword)
if (deleteInitializer) {
(element as? KtProperty)?.initializer = null
}
if (makeVar) {
(element as? KtModifierListOwner)?.removeModifier(KtTokens.CONST_KEYWORD)
}
}
companion object {
val VAL_WITH_SETTER_FACTORY: QuickFixesPsiBasedFactory<KtPropertyAccessor> =
quickFixesPsiBasedFactory { psiElement: KtPropertyAccessor ->
listOf(ChangeVariableMutabilityFix(psiElement.property, true))
}
val VAR_OVERRIDDEN_BY_VAL_FACTORY: QuickFixesPsiBasedFactory<PsiElement> =
quickFixesPsiBasedFactory { psiElement: PsiElement ->
when (psiElement) {
is KtProperty, is KtParameter -> listOf(ChangeVariableMutabilityFix(psiElement as KtValVarKeywordOwner, true))
else -> emptyList()
}
}
val VAR_ANNOTATION_PARAMETER_FACTORY: QuickFixesPsiBasedFactory<KtParameter> =
quickFixesPsiBasedFactory { psiElement: KtParameter ->
listOf(ChangeVariableMutabilityFix(psiElement, false))
}
val LATEINIT_VAL_FACTORY: QuickFixesPsiBasedFactory<PsiElement> =
quickFixesPsiBasedFactory { psiElement: PsiElement ->
val property = psiElement.getStrictParentOfType<KtProperty>() ?: return@quickFixesPsiBasedFactory emptyList()
if (property.valOrVarKeyword.text != "val") {
emptyList()
} else {
listOf(ChangeVariableMutabilityFix(property, makeVar = true))
}
}
val MUST_BE_INITIALIZED_FACTORY: QuickFixesPsiBasedFactory<PsiElement> =
quickFixesPsiBasedFactory { psiElement: PsiElement ->
val property = psiElement as? KtProperty ?: return@quickFixesPsiBasedFactory emptyList()
val getter = property.getter ?: return@quickFixesPsiBasedFactory emptyList()
if (!getter.hasBody()) return@quickFixesPsiBasedFactory emptyList()
if (getter.hasBlockBody() && property.typeReference == null) return@quickFixesPsiBasedFactory emptyList()
listOf(ChangeVariableMutabilityFix(property, makeVar = false))
}
}
}
\ No newline at end of file
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.idea.quickfix
import com.intellij.codeInsight.FileModificationService
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.psi.KtFile
abstract class KotlinPsiOnlyQuickFixAction<out T : PsiElement>(element: T) : QuickFixActionBase<T>(element) {
protected open fun isAvailable(project: Project, editor: Editor?, file: KtFile) = true
override fun isAvailableImpl(project: Project, editor: Editor?, file: PsiFile): Boolean {
val ktFile = file as? KtFile ?: return false
return isAvailable(project, editor, ktFile)
}
final override fun invoke(project: Project, editor: Editor?, file: PsiFile) {
val element = element ?: return
if (file is KtFile && FileModificationService.getInstance().prepareFileForWrite(element.containingFile)) {
invoke(project, editor, file)
}
}
protected abstract operator fun invoke(project: Project, editor: Editor?, file: KtFile)
override fun startInWriteAction() = true
}
......@@ -1040,9 +1040,6 @@ replace.with.publishedapi.bridge.call=Replace with @PublishedApi bridge call
replace.with.generated.publishedapi.bridge.call.0=Replace with generated @PublishedApi bridge call ''{0}''
convert.sealed.sub.class.to.object.fix.family.name=Convert sealed sub-class to object
generate.identity.equals.fix.family.name=Generate equals \\& hashCode by identity
and.delete.initializer=\ and delete initializer
change.to.val=Change to val
change.to.var=Change to var
change.type.of.0.to.1=Change type of {0} to ''{1}''
change.type.to.0=Change type to ''{0}''
base.property.0=base property {0}
......
......@@ -17,128 +17,44 @@
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 com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinBundleIndependent
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createCallable.CreatePropertyDelegateAccessorsActionFactory
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtValVarKeywordOwner
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.util.OperatorNameConventions
class ChangeVariableMutabilityFix(
element: KtValVarKeywordOwner,
private val makeVar: Boolean,
private val actionText: String? = null,
private val deleteInitializer: Boolean = false
) : KotlinQuickFixAction<KtValVarKeywordOwner>(element) {
override fun getText() = actionText
?: (if (makeVar) KotlinBundle.message("change.to.var") else KotlinBundle.message("change.to.val")) +
if (deleteInitializer) KotlinBundle.message("and.delete.initializer") else ""
override fun getFamilyName(): String = text
override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean {
val element = element ?: return false
val valOrVar = element.valOrVarKeyword?.node?.elementType ?: return false
return (valOrVar == KtTokens.VAR_KEYWORD) != makeVar
class ReassignmentActionFactory(val factory: DiagnosticFactory1<*, DeclarationDescriptor>) : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val propertyDescriptor = factory.cast(diagnostic).a
val declaration =
DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor) as? KtValVarKeywordOwner ?: return null
return ChangeVariableMutabilityFix(declaration, true)
}
}
override fun invoke(project: Project, editor: Editor?, file: KtFile) {
val element = element ?: return
val factory = KtPsiFactory(project)
val newKeyword = if (makeVar) factory.createVarKeyword() else factory.createValKeyword()
element.valOrVarKeyword!!.replace(newKeyword)
if (deleteInitializer) {
(element as? KtProperty)?.initializer = null
}
if (makeVar) {
(element as? KtModifierListOwner)?.removeModifier(KtTokens.CONST_KEYWORD)
}
// TODO: Move this to idea-fir-independent
object ConstValFactory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val (modifier, element) = Errors.WRONG_MODIFIER_TARGET.cast(diagnostic).run { a to psiElement }
if (modifier != KtTokens.CONST_KEYWORD) return null
val property = element.getStrictParentOfType<KtProperty>() ?: return null
return ChangeVariableMutabilityFix(property, makeVar = false)
}
}
companion object {
val VAL_WITH_SETTER_FACTORY: KotlinSingleIntentionActionFactory = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val accessor = diagnostic.psiElement as KtPropertyAccessor
return ChangeVariableMutabilityFix(accessor.property, true)
}
}
class ReassignmentActionFactory(val factory: DiagnosticFactory1<*, DeclarationDescriptor>) : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val propertyDescriptor = factory.cast(diagnostic).a
val declaration =
DescriptorToSourceUtils.descriptorToDeclaration(propertyDescriptor) as? KtValVarKeywordOwner ?: return null
return ChangeVariableMutabilityFix(declaration, true)
}
}
val VAL_REASSIGNMENT_FACTORY = ReassignmentActionFactory(Errors.VAL_REASSIGNMENT)
val CAPTURED_VAL_INITIALIZATION_FACTORY = ReassignmentActionFactory(Errors.CAPTURED_VAL_INITIALIZATION)
val CAPTURED_MEMBER_VAL_INITIALIZATION_FACTORY = ReassignmentActionFactory(Errors.CAPTURED_MEMBER_VAL_INITIALIZATION)
val VAR_OVERRIDDEN_BY_VAL_FACTORY: QuickFixesPsiBasedFactory<PsiElement> =
quickFixesPsiBasedFactory { psiElement: PsiElement ->
when (psiElement) {
is KtProperty, is KtParameter -> listOf(ChangeVariableMutabilityFix(psiElement as KtValVarKeywordOwner, true))
else -> emptyList()
}
}
val VAR_ANNOTATION_PARAMETER_FACTORY: KotlinSingleIntentionActionFactory = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val element = diagnostic.psiElement as KtParameter
return ChangeVariableMutabilityFix(element, false)
}
}
val LATEINIT_VAL_FACTORY = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val lateinitElement = Errors.INAPPLICABLE_LATEINIT_MODIFIER.cast(diagnostic).psiElement
val property = lateinitElement.getStrictParentOfType<KtProperty>() ?: return null
if (property.valOrVarKeyword.text != "val") return null
return ChangeVariableMutabilityFix(property, makeVar = true)
}
}
val CONST_VAL_FACTORY = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val (modifier, element) = Errors.WRONG_MODIFIER_TARGET.cast(diagnostic).run { a to psiElement }
if (modifier != KtTokens.CONST_KEYWORD) return null
val property = element.getStrictParentOfType<KtProperty>() ?: return null
return ChangeVariableMutabilityFix(property, makeVar = false)
}
}
val DELEGATED_PROPERTY_VAL_FACTORY = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val element = Errors.DELEGATE_SPECIAL_FUNCTION_MISSING.cast(diagnostic).psiElement
val property = element.getStrictParentOfType<KtProperty>() ?: return null
val info = CreatePropertyDelegateAccessorsActionFactory.extractFixData(property, diagnostic).singleOrNull() ?: return null
if (info.name != OperatorNameConventions.SET_VALUE.asString()) return null
return ChangeVariableMutabilityFix(property, makeVar = false, actionText = KotlinBundle.message("change.to.val"))
}
}
val MUST_BE_INITIALIZED_FACTORY = object : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val property = Errors.MUST_BE_INITIALIZED.cast(diagnostic).psiElement as? KtProperty ?: return null
val getter = property.getter ?: return null
if (!getter.hasBody()) return null
if (getter.hasBlockBody() && property.typeReference == null) return null
return ChangeVariableMutabilityFix(property, makeVar = false)
}
}
object DelegatedPropertyValFactory : KotlinSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val element = Errors.DELEGATE_SPECIAL_FUNCTION_MISSING.cast(diagnostic).psiElement
val property = element.getStrictParentOfType<KtProperty>() ?: return null
val info = CreatePropertyDelegateAccessorsActionFactory.extractFixData(property, diagnostic).singleOrNull() ?: return null
if (info.name != OperatorNameConventions.SET_VALUE.asString()) return null
return ChangeVariableMutabilityFix(property, makeVar = false, actionText = KotlinBundleIndependent.message("change.to.val"))
}
}
}
\ No newline at end of file
......@@ -142,7 +142,7 @@ class QuickFixRegistrar : QuickFixContributor {
removeModifierFactory
)
REDUNDANT_MODIFIER_IN_GETTER.registerFactory(removeRedundantModifierFactory)
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory, ChangeVariableMutabilityFix.CONST_VAL_FACTORY)
WRONG_MODIFIER_TARGET.registerFactory(removeModifierFactory, ConstValFactory)
DEPRECATED_MODIFIER.registerFactory(ReplaceModifierFix)
REDUNDANT_MODIFIER_FOR_TARGET.registerFactory(removeModifierFactory)
WRONG_MODIFIER_CONTAINING_DECLARATION.registerFactory(removeModifierFactory)
......@@ -222,10 +222,10 @@ class QuickFixRegistrar : QuickFixContributor {
VAL_WITH_SETTER.registerFactory(ChangeVariableMutabilityFix.VAL_WITH_SETTER_FACTORY)
VAL_REASSIGNMENT.registerFactory(
ChangeVariableMutabilityFix.VAL_REASSIGNMENT_FACTORY, LiftAssignmentOutOfTryFix, AssignToPropertyFix
ReassignmentActionFactory(VAL_REASSIGNMENT), LiftAssignmentOutOfTryFix, AssignToPropertyFix
)
CAPTURED_VAL_INITIALIZATION.registerFactory(ChangeVariableMutabilityFix.CAPTURED_VAL_INITIALIZATION_FACTORY)
CAPTURED_MEMBER_VAL_INITIALIZATION.registerFactory(ChangeVariableMutabilityFix.CAPTURED_MEMBER_VAL_INITIALIZATION_FACTORY)
CAPTURED_VAL_INITIALIZATION.registerFactory(ReassignmentActionFactory(CAPTURED_VAL_INITIALIZATION))
CAPTURED_MEMBER_VAL_INITIALIZATION.registerFactory(ReassignmentActionFactory(CAPTURED_MEMBER_VAL_INITIALIZATION))
VAR_OVERRIDDEN_BY_VAL.registerFactory(ChangeVariableMutabilityFix.VAR_OVERRIDDEN_BY_VAL_FACTORY)
VAR_ANNOTATION_PARAMETER.registerFactory(ChangeVariableMutabilityFix.VAR_ANNOTATION_PARAMETER_FACTORY)
......@@ -418,7 +418,7 @@ class QuickFixRegistrar : QuickFixContributor {
CreateDataClassPropertyFromDestructuringActionFactory
)
DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(ChangeVariableMutabilityFix.DELEGATED_PROPERTY_VAL_FACTORY)
DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(DelegatedPropertyValFactory)
DELEGATE_SPECIAL_FUNCTION_MISSING.registerFactory(CreatePropertyDelegateAccessorsActionFactory)
DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE.registerFactory(CreatePropertyDelegateAccessorsActionFactory)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册