From 86827dfc92245fd2b3968e5fa9ba7369653b6260 Mon Sep 17 00:00:00 2001 From: Dmitry Gridin Date: Fri, 22 May 2020 15:22:39 +0700 Subject: [PATCH] TrailingCommaVisitor: adapt to `TrailingCommaContext` #KT-39123 Fixed --- .../trailingComma/TrailingCommaContext.kt | 6 ++ .../TrailingCommaPostFormatProcessor.kt | 35 ++++++----- .../idea/formatter/TrailingCommaVisitor.kt | 31 +++++----- .../inspections/TrailingCommaInspection.kt | 58 ++++++++++--------- idea/testData/formatter/When.after.inv.kt | 9 ++- idea/testData/formatter/When.after.kt | 7 +++ idea/testData/formatter/When.kt | 7 +++ 7 files changed, 99 insertions(+), 54 deletions(-) diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/trailingComma/TrailingCommaContext.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/trailingComma/TrailingCommaContext.kt index 161932917cc..cbd29d9492d 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/trailingComma/TrailingCommaContext.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/formatter/trailingComma/TrailingCommaContext.kt @@ -7,8 +7,14 @@ package org.jetbrains.kotlin.idea.formatter.trailingComma import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import org.jetbrains.kotlin.psi.KtElement class TrailingCommaContext private constructor(val element: PsiElement, val state: TrailingCommaState) { + /** + * Return [KtElement] if [state] != [TrailingCommaState.NOT_APPLICABLE] + */ + val ktElement: KtElement get() = element as? KtElement ?: error("State is NOT_APPLICABLE") + companion object { fun create(element: PsiElement): TrailingCommaContext = TrailingCommaContext( element, diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt index d09b480f809..8f785648b03 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaPostFormatProcessor.kt @@ -16,10 +16,12 @@ import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.impl.source.codeStyle.PostFormatProcessor import com.intellij.psi.impl.source.codeStyle.PostFormatProcessorHelper +import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaContext import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper.findInvalidCommas import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper.trailingCommaOrLastElement import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaState import org.jetbrains.kotlin.idea.formatter.trailingComma.addTrailingCommaIsAllowedFor +import org.jetbrains.kotlin.idea.formatter.trailingComma.addTrailingCommaIsAllowedForThis import org.jetbrains.kotlin.idea.util.leafIgnoringWhitespace import org.jetbrains.kotlin.idea.util.leafIgnoringWhitespaceAndComments import org.jetbrains.kotlin.psi.KtElement @@ -38,8 +40,12 @@ class TrailingCommaPostFormatProcessor : PostFormatProcessor { private class TrailingCommaPostFormatVisitor(val settings: CodeStyleSettings) : TrailingCommaVisitor() { private val myPostProcessor = PostFormatProcessorHelper(settings.kotlinCommonSettings) - override fun process(commaOwner: KtElement) = processIfInRange(commaOwner) { - processCommaOwner(commaOwner) + override fun process(trailingCommaContext: TrailingCommaContext) { + val ktElement = trailingCommaContext.ktElement + if (!ktElement.addTrailingCommaIsAllowedForThis()) return + processIfInRange(ktElement) { + processCommaOwner(trailingCommaContext) + } } private fun processIfInRange(element: KtElement, block: () -> Unit = {}) { @@ -48,25 +54,26 @@ private class TrailingCommaPostFormatVisitor(val settings: CodeStyleSettings) : } } - private fun processCommaOwner(parent: KtElement) { - if (!postFormatIsEnable(parent)) return + private fun processCommaOwner(trailingCommaContext: TrailingCommaContext) { + val ktElement = trailingCommaContext.ktElement + if (!postFormatIsEnable(ktElement)) return - val lastElementOrComma = trailingCommaOrLastElement(parent) ?: return - updatePsi(parent) { - val stateForElement = TrailingCommaState.stateForElement(parent) + val lastElementOrComma = trailingCommaOrLastElement(ktElement) ?: return + updatePsi(ktElement) { + val state = trailingCommaContext.state when { - stateForElement == TrailingCommaState.MISSING && settings.kotlinCustomSettings.addTrailingCommaIsAllowedFor(parent) -> { + state == TrailingCommaState.MISSING && settings.kotlinCustomSettings.addTrailingCommaIsAllowedFor(ktElement) -> { // add a missing comma - if (trailingCommaAllowedInModule(parent)) { - lastElementOrComma.addCommaAfter(KtPsiFactory(parent)) + if (trailingCommaAllowedInModule(ktElement)) { + lastElementOrComma.addCommaAfter(KtPsiFactory(ktElement)) } - correctCommaPosition(parent) + correctCommaPosition(ktElement) } - stateForElement == TrailingCommaState.EXISTS -> { - correctCommaPosition(parent) + state == TrailingCommaState.EXISTS -> { + correctCommaPosition(ktElement) } - stateForElement == TrailingCommaState.REDUNDANT -> { + state == TrailingCommaState.REDUNDANT -> { // remove redundant comma lastElementOrComma.delete() } diff --git a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaVisitor.kt b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaVisitor.kt index 757f3891345..93f24146852 100644 --- a/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaVisitor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/formatter/TrailingCommaVisitor.kt @@ -7,48 +7,49 @@ package org.jetbrains.kotlin.idea.formatter import com.intellij.openapi.progress.ProgressIndicatorProvider import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.idea.formatter.trailingComma.addTrailingCommaIsAllowedForThis +import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaContext +import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaState import org.jetbrains.kotlin.psi.* abstract class TrailingCommaVisitor : KtTreeVisitorVoid() { override fun visitParameterList(list: KtParameterList) { super.visitParameterList(list) - runProcessIfAllowed(list) + runProcessIfApplicable(list) } override fun visitValueArgumentList(list: KtValueArgumentList) { super.visitValueArgumentList(list) - runProcessIfAllowed(list) + runProcessIfApplicable(list) } override fun visitArrayAccessExpression(expression: KtArrayAccessExpression) { super.visitArrayAccessExpression(expression) - runProcessIfAllowed(expression.indicesNode) + runProcessIfApplicable(expression.indicesNode) } override fun visitTypeParameterList(list: KtTypeParameterList) { super.visitTypeParameterList(list) - runProcessIfAllowed(list) + runProcessIfApplicable(list) } override fun visitTypeArgumentList(typeArgumentList: KtTypeArgumentList) { super.visitTypeArgumentList(typeArgumentList) - runProcessIfAllowed(typeArgumentList) + runProcessIfApplicable(typeArgumentList) } override fun visitCollectionLiteralExpression(expression: KtCollectionLiteralExpression) { super.visitCollectionLiteralExpression(expression) - runProcessIfAllowed(expression) + runProcessIfApplicable(expression) } override fun visitWhenEntry(jetWhenEntry: KtWhenEntry) { super.visitWhenEntry(jetWhenEntry) - runProcessIfAllowed(jetWhenEntry) + runProcessIfApplicable(jetWhenEntry) } override fun visitDestructuringDeclaration(destructuringDeclaration: KtDestructuringDeclaration) { super.visitDestructuringDeclaration(destructuringDeclaration) - runProcessIfAllowed(destructuringDeclaration) + runProcessIfApplicable(destructuringDeclaration) } override fun visitElement(element: PsiElement) { @@ -57,13 +58,17 @@ abstract class TrailingCommaVisitor : KtTreeVisitorVoid() { if (recursively) super.visitElement(element) } - private fun runProcessIfAllowed(element: KtElement) { - if (element.addTrailingCommaIsAllowedForThis()) { - process(element) + private fun runProcessIfApplicable(element: KtElement) { + val context = TrailingCommaContext.create(element) + if (context.state != TrailingCommaState.NOT_APPLICABLE) { + process(context) } } - protected abstract fun process(commaOwner: KtElement) + /** + * [trailingCommaContext] doesn't contain a state [TrailingCommaState.NOT_APPLICABLE] + */ + protected abstract fun process(trailingCommaContext: TrailingCommaContext) protected open val recursively: Boolean = true } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/TrailingCommaInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/TrailingCommaInspection.kt index 9cc190ff963..e3b526890cd 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/TrailingCommaInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/TrailingCommaInspection.kt @@ -20,8 +20,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.formatter.TrailingCommaVisitor import org.jetbrains.kotlin.idea.formatter.kotlinCustomSettings -import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper -import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaState +import org.jetbrains.kotlin.idea.formatter.trailingComma.* import org.jetbrains.kotlin.idea.formatter.trailingCommaAllowedInModule import org.jetbrains.kotlin.idea.util.isComma import org.jetbrains.kotlin.idea.util.isLineBreak @@ -39,18 +38,20 @@ class TrailingCommaInspection( override val recursively: Boolean = false private var useTrailingComma by Delegates.notNull() - override fun process(commaOwner: KtElement) { - useTrailingComma = CodeStyle.getSettings(commaOwner.project).kotlinCustomSettings.ALLOW_TRAILING_COMMA - val state = TrailingCommaState.stateForElement(commaOwner) - when (state) { + override fun process(trailingCommaContext: TrailingCommaContext) { + val element = trailingCommaContext.ktElement + if (!element.addTrailingCommaIsAllowedForThis()) return + + useTrailingComma = CodeStyle.getSettings(element.project).kotlinCustomSettings.ALLOW_TRAILING_COMMA + when (trailingCommaContext.state) { TrailingCommaState.MISSING, TrailingCommaState.EXISTS -> { - checkCommaPosition(commaOwner) - checkLineBreaks(commaOwner) + checkCommaPosition(element) + checkLineBreaks(element) } else -> Unit } - checkTrailingComma(commaOwner, state) + checkTrailingComma(trailingCommaContext) } private fun checkLineBreaks(commaOwner: KtElement) { @@ -81,24 +82,29 @@ class TrailingCommaInspection( } } - private fun checkTrailingComma(commaOwner: KtElement, state: TrailingCommaState) { + private fun checkTrailingComma(trailingCommaContext: TrailingCommaContext) { + val commaOwner = trailingCommaContext.ktElement val trailingCommaOrLastElement = TrailingCommaHelper.trailingCommaOrLastElement(commaOwner) ?: return - if (state == TrailingCommaState.MISSING) { - if (!trailingCommaAllowedInModule(commaOwner)) return - reportProblem( - trailingCommaOrLastElement, - KotlinBundle.message("inspection.trailing.comma.missing.trailing.comma"), - KotlinBundle.message("inspection.trailing.comma.add.trailing.comma"), - if (addCommaWarning) ProblemHighlightType.GENERIC_ERROR_OR_WARNING else ProblemHighlightType.INFORMATION, - ) - } else if (state == TrailingCommaState.REDUNDANT) { - reportProblem( - trailingCommaOrLastElement, - KotlinBundle.message("inspection.trailing.comma.useless.trailing.comma"), - KotlinBundle.message("inspection.trailing.comma.remove.trailing.comma"), - ProblemHighlightType.LIKE_UNUSED_SYMBOL, - checkTrailingCommaSettings = false, - ) + when (trailingCommaContext.state) { + TrailingCommaState.MISSING -> { + if (!trailingCommaAllowedInModule(commaOwner)) return + reportProblem( + trailingCommaOrLastElement, + KotlinBundle.message("inspection.trailing.comma.missing.trailing.comma"), + KotlinBundle.message("inspection.trailing.comma.add.trailing.comma"), + if (addCommaWarning) ProblemHighlightType.GENERIC_ERROR_OR_WARNING else ProblemHighlightType.INFORMATION, + ) + } + TrailingCommaState.REDUNDANT -> { + reportProblem( + trailingCommaOrLastElement, + KotlinBundle.message("inspection.trailing.comma.useless.trailing.comma"), + KotlinBundle.message("inspection.trailing.comma.remove.trailing.comma"), + ProblemHighlightType.LIKE_UNUSED_SYMBOL, + checkTrailingCommaSettings = false, + ) + } + else -> Unit } } diff --git a/idea/testData/formatter/When.after.inv.kt b/idea/testData/formatter/When.after.inv.kt index 91a96e03a53..3d997ce1eda 100644 --- a/idea/testData/formatter/When.after.inv.kt +++ b/idea/testData/formatter/When.after.inv.kt @@ -1,7 +1,7 @@ fun some(x: Any) { when (x) { is Number -> 0 - else -> 1 + else -> 1 } when { } @@ -37,4 +37,11 @@ fun some(x: Any) { } } +val a = when { + true && true && true -> { + } + else -> { + } +} + // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file diff --git a/idea/testData/formatter/When.after.kt b/idea/testData/formatter/When.after.kt index 91a96e03a53..c1a3163c4bc 100644 --- a/idea/testData/formatter/When.after.kt +++ b/idea/testData/formatter/When.after.kt @@ -37,4 +37,11 @@ fun some(x: Any) { } } +val a = when { + true && true && true -> { + } + else -> { + } +} + // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file diff --git a/idea/testData/formatter/When.kt b/idea/testData/formatter/When.kt index b48ddce8f80..6f41fba2db2 100644 --- a/idea/testData/formatter/When.kt +++ b/idea/testData/formatter/When.kt @@ -43,4 +43,11 @@ else->1 when {} } +val a = when { + true && true && true -> { + } + else -> { + } +} + // SET_FALSE: ALIGN_IN_COLUMNS_CASE_BRANCH \ No newline at end of file