FIR IDE: Move ChangeVariableMutabilityFix to idea-frontend-independent.
This commit is contained in:
committed by
Ilya Kirillov
parent
7962224804
commit
a9f19c4a45
+5
-1
@@ -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
|
||||
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
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
|
||||
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: 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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
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"))
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user