FIR IDE: move common logic in add accessor intention to idea-frontend-independent

This commit is contained in:
Tianyu Geng
2021-03-28 18:21:11 -07:00
committed by Ilya Kirillov
parent 7713d05272
commit 78f450a6ef
3 changed files with 65 additions and 50 deletions
@@ -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>(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")
}
@@ -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>(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)
@@ -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)