Inspection "MoveVariableDeclarationIntoWhen" should inline variable declaration

This commit is contained in:
Dmitry Gridin
2019-03-21 16:29:08 +07:00
parent f9119c001e
commit c84ff1d8b1
3 changed files with 38 additions and 10 deletions
@@ -23,33 +23,61 @@ class MoveVariableDeclarationIntoWhenInspection : AbstractKotlinInspection(), Cl
whenExpressionVisitor(fun(expression: KtWhenExpression) {
val subjectExpression = expression.subjectExpression ?: return
val property = expression.findDeclarationNear() ?: return
if (!property.isUsedOnlyIn(expression)) return
val action = property.action(expression)
if (action == Action.NOTHING) return
val identifier = property.nameIdentifier ?: return
holder.registerProblem(
property,
TextRange.from(identifier.startOffsetInParent, identifier.textLength),
"Variable declaration could be moved inside `when`",
MoveVariableDeclarationIntoWhenFix(subjectExpression.createSmartPointer())
action.description, action.createFix(subjectExpression.createSmartPointer())
)
})
}
private fun KtProperty.isUsedOnlyIn(element: KtElement): Boolean = countUsages() == countUsages(element)
private enum class Action {
NOTHING,
MOVE,
INLINE;
val description: String
get() = when (this) {
MOVE -> "Variable declaration could be moved into `when`"
INLINE -> "Variable declaration could be inlined"
NOTHING -> "Nothing to do"
}
fun createFix(subjectExpressionPointer: SmartPsiElementPointer<KtExpression>): VariableDeclarationIntoWhenFix = when (this) {
MOVE -> VariableDeclarationIntoWhenFix("Move variable declaration into `when`", subjectExpressionPointer) { it }
INLINE -> VariableDeclarationIntoWhenFix("Inline variable", subjectExpressionPointer) { it.initializer }
else -> error("Illegal action")
}
}
private fun KtProperty.action(element: KtElement): Action = when (val elementUsages = countUsages(element)) {
countUsages() -> if (elementUsages == 1) Action.INLINE else Action.MOVE
else -> Action.NOTHING
}
private fun KtWhenExpression.findDeclarationNear(): KtProperty? {
val previousProperty = previousStatement() as? KtProperty ?: return null
return previousProperty.takeIf { !it.isVar && it.hasInitializer() && it.nameIdentifier?.text == subjectExpression?.text }
}
private class MoveVariableDeclarationIntoWhenFix(val subjectExpressionPointer: SmartPsiElementPointer<KtExpression>) : LocalQuickFix {
override fun getName() = "Move the variable into `when`"
private class VariableDeclarationIntoWhenFix(
private val actionName: String,
private val subjectExpressionPointer: SmartPsiElementPointer<KtExpression>,
private val transform: (KtProperty) -> KtExpression?
) : LocalQuickFix {
override fun getName() = actionName
override fun getFamilyName() = name
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val property = descriptor.psiElement as? KtProperty ?: return
val subjectExpression = subjectExpressionPointer.element ?: return
subjectExpression.replace(property.copy())
val newElement = transform(property)?.copy() ?: return
subjectExpression.replace(newElement)
property.delete()
}
}
}
@@ -1,7 +1,7 @@
fun foo() {
// comment
when (val a = 1) {
when (1) {
1 -> {
}
else -> {
@@ -1,7 +1,7 @@
fun foo() {
when (val a = 1) {
when (1) {
1 -> {
}
else -> {