Refactored RemoveModifierFix + some psi API refactoring

#EA-69237 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-08-14 21:21:22 +03:00
parent fd517d41d1
commit ba8c2f1084
7 changed files with 79 additions and 111 deletions
@@ -20,10 +20,6 @@ make.class.annotation.class.family=Make Class an Annotation Class
add.star.projections=Add ''{0}''
change.to.star.projection=Change type arguments to {0}
change.to.star.projection.family=Change to Star Projection
make.element.not.modifier=Make {0} not {1}
remove.modifier=Remove ''{0}'' modifier
remove.modifier.family=Remove Modifier
remove.redundant.modifier=Remove redundant ''{0}'' modifier
remove.parts.from.property=Remove {0} from property
remove.parts.from.property.family=Remove Parts from Property
remove.psi.element.family=Remove Element
@@ -16,16 +16,18 @@
package org.jetbrains.kotlin.idea.quickfix
import com.intellij.extapi.psi.ASTDelegatePsiElement
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.lexer.JetKeywordToken
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetModifierListOwner
import org.jetbrains.kotlin.psi.JetTypeParameter
import org.jetbrains.kotlin.psi.JetTypeProjection
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.types.Variance
public class RemoveModifierFix(
@@ -34,53 +36,37 @@ public class RemoveModifierFix(
private val isRedundant: Boolean
) : JetIntentionAction<JetModifierListOwner>(element) {
override fun getFamilyName() = JetBundle.message("remove.modifier.family")
private val text = run {
val modifierText = modifier.value
when {
isRedundant ->
"Remove redundant '$modifierText' modifier"
modifier === JetTokens.ABSTRACT_KEYWORD || modifier === JetTokens.OPEN_KEYWORD ->
"Make ${AddModifierFix.getElementName(element)} not $modifierText"
else ->
"Remove '$modifierText' modifier"
}
}
override fun getText() = makeText(element, modifier, isRedundant)
override fun getFamilyName() = "Remove modifier"
override fun getText() = text
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile)
= super.isAvailable(project, editor, file) && element.hasModifier(modifier)
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
invoke()
}
public fun invoke() {
//TODO: without this copy&replace we get bad formatting on removing last modifier
val newElement = element.copy() as JetModifierListOwner
element.replace(removeModifier(newElement, modifier))
newElement.removeModifier(modifier)
element.replace(newElement)
}
companion object {
private fun makeText(element: JetModifierListOwner?, modifier: JetKeywordToken, isRedundant: Boolean): String {
if (isRedundant) {
return JetBundle.message("remove.redundant.modifier", modifier.value)
}
if (element != null && (modifier === JetTokens.ABSTRACT_KEYWORD || modifier === JetTokens.OPEN_KEYWORD)) {
return JetBundle.message("make.element.not.modifier", AddModifierFix.getElementName(element), modifier.value)
}
return JetBundle.message("remove.modifier", modifier.value)
}
private fun <T : JetModifierListOwner> removeModifier(element: T, modifier: JetModifierKeywordToken): T {
val modifierList = element.modifierList!!
removeModifierFromList(modifierList, modifier)
if (modifierList.firstChild == null) {
val whiteSpace = modifierList.nextSibling
assert(element is ASTDelegatePsiElement)
(element as ASTDelegatePsiElement).deleteChildInternal(modifierList.node)
QuickFixUtil.removePossiblyWhiteSpace(element, whiteSpace)
}
return element
}
private fun removeModifierFromList(modifierList: JetModifierList, modifier: JetModifierKeywordToken): JetModifierList {
val modifierNode = modifierList.getModifierNode(modifier)!!
val whiteSpace = modifierNode.psi.nextSibling
val wsRemoved = QuickFixUtil.removePossiblyWhiteSpace(modifierList, whiteSpace)
modifierList.deleteChildInternal(modifierNode)
if (!wsRemoved) {
QuickFixUtil.removePossiblyWhiteSpace(modifierList, modifierList.lastChild)
}
return modifierList
}
public fun createRemoveModifierFromListOwnerFactory(modifier: JetModifierKeywordToken, isRedundant: Boolean = false): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): JetIntentionAction<JetModifierListOwner>? {
@@ -93,10 +79,9 @@ public class RemoveModifierFix(
public fun createRemoveModifierFactory(isRedundant: Boolean = false): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): JetIntentionAction<JetModifierListOwner>? {
val modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetModifierListOwner>()) ?: return null
val psiElement = diagnostic.psiElement
val elementType = psiElement.node.elementType
if (elementType !is JetModifierKeywordToken) return null
val elementType = psiElement.node.elementType as? JetModifierKeywordToken ?: return null
val modifierListOwner = psiElement.getStrictParentOfType<JetModifierListOwner>() ?: return null
return RemoveModifierFix(modifierListOwner, elementType, isRedundant)
}
}
@@ -105,10 +90,8 @@ public class RemoveModifierFix(
public fun createRemoveProjectionFactory(isRedundant: Boolean): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): JetIntentionAction<JetModifierListOwner>? {
val projection = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetTypeProjection>()) ?: return null
val projectionAstNode = projection.projectionNode ?: return null
val elementType = projectionAstNode.elementType
if (elementType !is JetModifierKeywordToken) return null
val projection = diagnostic.psiElement as JetTypeProjection
val elementType = projection.projectionToken?.node?.elementType as? JetModifierKeywordToken ?: return null
return RemoveModifierFix(projection, elementType, isRedundant)
}
}
@@ -117,17 +100,13 @@ public class RemoveModifierFix(
public fun createRemoveVarianceFactory(): JetSingleIntentionActionFactory {
return object : JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): JetIntentionAction<JetModifierListOwner>? {
val modifierListOwner = QuickFixUtil.getParentElementOfType(diagnostic, javaClass<JetModifierListOwner>()) ?: return null
val psiElement = diagnostic.psiElement
if (psiElement !is JetTypeParameter) return null
val variance = psiElement.variance
val modifier: JetModifierKeywordToken
when (variance) {
Variance.IN_VARIANCE -> modifier = JetTokens.IN_KEYWORD
Variance.OUT_VARIANCE -> modifier = JetTokens.OUT_KEYWORD
val psiElement = diagnostic.psiElement as JetTypeParameter
val modifier = when (psiElement.variance) {
Variance.IN_VARIANCE -> JetTokens.IN_KEYWORD
Variance.OUT_VARIANCE -> JetTokens.OUT_KEYWORD
else -> return null
}
return RemoveModifierFix(modifierListOwner, modifier, false)
return RemoveModifierFix(psiElement, modifier, isRedundant = false)
}
}
}