diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt index 4333e85111..3b8bca5053 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/files/NewlinesRule.kt @@ -13,11 +13,14 @@ import org.cqfn.diktat.ruleset.utils.emptyBlockList import org.cqfn.diktat.ruleset.utils.extractLineOfText import org.cqfn.diktat.ruleset.utils.findAllDescendantsWithSpecificType import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType +import org.cqfn.diktat.ruleset.utils.getFilePath import org.cqfn.diktat.ruleset.utils.getIdentifierName +import org.cqfn.diktat.ruleset.utils.getRootNode import org.cqfn.diktat.ruleset.utils.hasParent import org.cqfn.diktat.ruleset.utils.isBeginByNewline import org.cqfn.diktat.ruleset.utils.isEol import org.cqfn.diktat.ruleset.utils.isFollowedByNewline +import org.cqfn.diktat.ruleset.utils.isGradleScript import org.cqfn.diktat.ruleset.utils.isSingleLineIfElse import org.cqfn.diktat.ruleset.utils.leaveOnlyOneNewLine @@ -71,7 +74,6 @@ import com.pinterest.ktlint.core.ast.ElementType.SAFE_ACCESS_EXPRESSION import com.pinterest.ktlint.core.ast.ElementType.SECONDARY_CONSTRUCTOR import com.pinterest.ktlint.core.ast.ElementType.SEMICOLON import com.pinterest.ktlint.core.ast.ElementType.SUPER_TYPE_LIST -import com.pinterest.ktlint.core.ast.ElementType.TYPE_REFERENCE import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT import com.pinterest.ktlint.core.ast.ElementType.VALUE_ARGUMENT_LIST import com.pinterest.ktlint.core.ast.ElementType.VALUE_PARAMETER @@ -177,24 +179,24 @@ class NewlinesRule(configRules: List) : DiktatRule( return } val isIncorrect = (if (node.elementType == ELVIS) node.treeParent else node).run { - if (isCallsChain()) { + if (isInvalidCallsChain(dropLeadingProperties = true)) { if (node.isInParentheses()) { - COMPLEX_EXPRESSION.warn(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) + checkForComplexExpression(node) } val isSingleLineIfElse = parent({ it.elementType == IF }, true)?.isSingleLineIfElse() ?: false // to follow functional style these operators should be started by newline (isFollowedByNewline() || !isBeginByNewline()) && !isSingleLineIfElse && (!isFirstCall() || !isMultilineLambda(treeParent)) } else { - if (isCallsChain(false) && node.isInParentheses()) { - COMPLEX_EXPRESSION.warn(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) + if (isInvalidCallsChain(dropLeadingProperties = false) && node.isInParentheses()) { + checkForComplexExpression(node) } // unless statement is simple and on single line, these operators cannot have newline after isFollowedByNewline() && !isSingleDotStatementOnSingleLine() } } if (isIncorrect || node.isElvisCorrect()) { - val freeText = if (node.isCallsChain() || node.isElvisCorrect()) { + val freeText = if (node.isInvalidCallsChain() || node.isElvisCorrect()) { "should follow functional style at ${node.text}" } else { "should break a line before and not after ${node.text}" @@ -216,6 +218,14 @@ class NewlinesRule(configRules: List) : DiktatRule( } } + private fun checkForComplexExpression(node: ASTNode) { + if (node.getRootNode().getFilePath().isGradleScript()) { + // this inspection is softened for gradle scripts, see https://github.com/analysis-dev/diktat/issues/1148 + return + } + COMPLEX_EXPRESSION.warn(configRules, emitWarn, isFixMode, node.text, node.startOffset, node) + } + private fun handleOpeningParentheses(node: ASTNode) { val parent = node.treeParent if (parent.elementType in listOf(VALUE_ARGUMENT_LIST, VALUE_PARAMETER_LIST)) { @@ -536,7 +546,7 @@ class NewlinesRule(configRules: List) : DiktatRule( * * @return true - if there is error, and false if there is no error */ - private fun ASTNode.isCallsChain(dropLeadingProperties: Boolean = true) = getCallChain(dropLeadingProperties)?.isNotValidCalls(this) ?: false + private fun ASTNode.isInvalidCallsChain(dropLeadingProperties: Boolean = true) = getCallChain(dropLeadingProperties)?.isNotValidCalls(this) ?: false private fun ASTNode.getCallChain(dropLeadingProperties: Boolean = true): List? { val parentExpressionList = getParentExpressions() @@ -573,7 +583,8 @@ class NewlinesRule(configRules: List) : DiktatRule( } } callsByNewLine.add(callsInOneNewLine) - return (callsByNewLine.find { it.contains(node) } ?: return false).indexOf(node) + 1 > configuration.maxCallsInOneLine + return (callsByNewLine.find { it.contains(node) } ?: return false) + .indexOf(node) + 1 > configuration.maxCallsInOneLine } /** @@ -583,10 +594,10 @@ class NewlinesRule(configRules: List) : DiktatRule( parents().takeWhile { it.elementType in chainExpressionTypes && it.elementType != LAMBDA_ARGUMENT } private fun isMultilineLambda(node: ASTNode): Boolean = - node.findAllDescendantsWithSpecificType(LAMBDA_ARGUMENT) + (node.findAllDescendantsWithSpecificType(LAMBDA_ARGUMENT) .firstOrNull() ?.text - ?.count { it == '\n' } ?: -1 > 0 + ?.count { it == '\n' } ?: -1) > 0 /** * Getting the first call expression in call chain diff --git a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt index fb418cccbd..2837e95272 100644 --- a/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt +++ b/diktat-rules/src/test/kotlin/org/cqfn/diktat/ruleset/chapter3/files/NewlinesRuleWarnTest.kt @@ -1145,4 +1145,17 @@ class NewlinesRuleWarnTest : LintTestBase(::NewlinesRule) { """.trimMargin(), ) } + + @Test + @Tag(WarningNames.COMPLEX_EXPRESSION) + fun `COMPLEX_EXPRESSION shouldn't trigger for declarations in kts`() { + lintMethod( + """ + |dependencies { + | implementation(libs.spring.cloud.starter.gateway) + |} + """.trimMargin(), + fileName = "build.gradle.kts" + ) + } }