diff --git a/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/intentions/AbstractAddAccessorsIntention.kt b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/intentions/AbstractAddAccessorsIntention.kt new file mode 100644 index 00000000000..e2304d42ffb --- /dev/null +++ b/idea/idea-frontend-independent/src/org/jetbrains/kotlin/idea/intentions/AbstractAddAccessorsIntention.kt @@ -0,0 +1,56 @@ +/* + * 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.intentions + +import com.intellij.openapi.editor.Editor +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.KtPropertyAccessor +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.psiUtil.startOffset + +abstract class AbstractAddAccessorsIntention( + protected val addGetter: Boolean, + protected val addSetter: Boolean +) : SelfTargetingRangeIntention(KtProperty::class.java, createFamilyName(addGetter, addSetter)) { + + override fun applyTo(element: KtProperty, editor: Editor?) { + val hasInitializer = element.hasInitializer() + val psiFactory = KtPsiFactory(element) + if (addGetter) { + val expression = if (hasInitializer) psiFactory.createExpression("field") else psiFactory.createBlock("TODO()") + val getter = psiFactory.createPropertyGetter(expression) + val added = if (element.setter != null) { + element.addBefore(getter, element.setter) + } else { + element.add(getter) + } + if (!hasInitializer) { + (added as? KtPropertyAccessor)?.bodyBlockExpression?.statements?.firstOrNull()?.let { + editor?.caretModel?.moveToOffset(it.startOffset) + } + } + } + if (addSetter) { + val expression = if (hasInitializer) psiFactory.createBlock("field = value") else psiFactory.createEmptyBody() + val setter = psiFactory.createPropertySetter(expression) + val added = element.add(setter) + if (!hasInitializer && !addGetter) { + (added as? KtPropertyAccessor)?.bodyBlockExpression?.lBrace?.let { + editor?.caretModel?.moveToOffset(it.startOffset + 1) + } + } + } + } +} + +private fun createFamilyName(addGetter: Boolean, addSetter: Boolean): () -> String = when { + addGetter && addSetter -> KotlinBundle.lazyMessage("text.add.getter.and.setter") + addGetter -> KotlinBundle.lazyMessage("text.add.getter") + addSetter -> KotlinBundle.lazyMessage("text.add.setter") + else -> throw AssertionError("At least one from (addGetter, addSetter) should be true") +} + diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/AddAccessorIntentions.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/AddAccessorIntentions.kt index b1dbd271833..343d50b057c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/AddAccessorIntentions.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/AddAccessorIntentions.kt @@ -7,25 +7,20 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.codeInsight.intention.IntentionAction import com.intellij.codeInsight.intention.LowPriorityAction -import com.intellij.openapi.editor.Editor import com.intellij.openapi.util.TextRange import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory import org.jetbrains.kotlin.idea.refactoring.isAbstract import org.jetbrains.kotlin.idea.util.hasJvmFieldAnnotation import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.psiUtil.startOffset -abstract class AbstractAddAccessorsIntention( - private val addGetter: Boolean, - private val addSetter: Boolean -) : SelfTargetingRangeIntention(KtProperty::class.java, createFamilyName(addGetter, addSetter)) { +abstract class AddAccessorsIntention( + addGetter: Boolean, + addSetter: Boolean +) : AbstractAddAccessorsIntention(addGetter, addSetter) { override fun applicabilityRange(element: KtProperty): TextRange? { if (element.isLocal || element.isAbstract() || element.hasDelegate() || @@ -45,35 +40,6 @@ abstract class AbstractAddAccessorsIntention( return if (hasInitializer) element.nameIdentifier?.textRange else element.textRange } - override fun applyTo(element: KtProperty, editor: Editor?) { - val hasInitializer = element.hasInitializer() - val psiFactory = KtPsiFactory(element) - if (addGetter) { - val expression = if (hasInitializer) psiFactory.createExpression("field") else psiFactory.createBlock("TODO()") - val getter = psiFactory.createPropertyGetter(expression) - val added = if (element.setter != null) { - element.addBefore(getter, element.setter) - } else { - element.add(getter) - } - if (!hasInitializer) { - (added as? KtPropertyAccessor)?.bodyBlockExpression?.statements?.firstOrNull()?.let { - editor?.caretModel?.moveToOffset(it.startOffset) - } - } - } - if (addSetter) { - val expression = if (hasInitializer) psiFactory.createBlock("field = value") else psiFactory.createEmptyBody() - val setter = psiFactory.createPropertySetter(expression) - val added = element.add(setter) - if (!hasInitializer && !addGetter) { - (added as? KtPropertyAccessor)?.bodyBlockExpression?.lBrace?.let { - editor?.caretModel?.moveToOffset(it.startOffset + 1) - } - } - } - } - companion object : KotlinSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic): IntentionAction? { val property = diagnostic.psiElement as? KtProperty ?: return null @@ -92,15 +58,8 @@ abstract class AbstractAddAccessorsIntention( } } -private fun createFamilyName(addGetter: Boolean, addSetter: Boolean): () -> String = when { - addGetter && addSetter -> KotlinBundle.lazyMessage("text.add.getter.and.setter") - addGetter -> KotlinBundle.lazyMessage("text.add.getter") - addSetter -> KotlinBundle.lazyMessage("text.add.setter") - else -> throw AssertionError("At least one from (addGetter, addSetter) should be true") -} +class AddPropertyAccessorsIntention : AddAccessorsIntention(true, true), LowPriorityAction -class AddPropertyAccessorsIntention : AbstractAddAccessorsIntention(true, true), LowPriorityAction +class AddPropertyGetterIntention : AddAccessorsIntention(true, false) -class AddPropertyGetterIntention : AbstractAddAccessorsIntention(true, false) - -class AddPropertySetterIntention : AbstractAddAccessorsIntention(false, true) +class AddPropertySetterIntention : AddAccessorsIntention(false, true) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index afcd63f6892..a08a01df905 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -620,8 +620,8 @@ class QuickFixRegistrar : QuickFixContributor { NO_SET_METHOD.registerFactory(ChangeToMutableCollectionFix) - MUST_BE_INITIALIZED_OR_BE_ABSTRACT.registerFactory(AbstractAddAccessorsIntention) - MUST_BE_INITIALIZED.registerFactory(AbstractAddAccessorsIntention) + MUST_BE_INITIALIZED_OR_BE_ABSTRACT.registerFactory(AddAccessorsIntention) + MUST_BE_INITIALIZED.registerFactory(AddAccessorsIntention) RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION.registerFactory(RestrictedRetentionForExpressionAnnotationFactory) RESTRICTED_RETENTION_FOR_EXPRESSION_ANNOTATION_WARNING.registerFactory(RestrictedRetentionForExpressionAnnotationFactory)