diff --git a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt index 67e74061a8..fcf9bf7071 100644 --- a/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt +++ b/diktat-rules/src/main/kotlin/org/cqfn/diktat/ruleset/rules/chapter3/LineLength.kt @@ -103,11 +103,12 @@ class LineLength(configRules: List) : DiktatRule( if (line.length > configuration.lineLength) { val newNode = node.psi.findElementAt(offset + configuration.lineLength.toInt() - 1)!!.node if ((newNode.elementType != KDOC_TEXT && newNode.elementType != KDOC_MARKDOWN_INLINE_LINK) || - !isKdocValid(newNode) + !isKdocValid(newNode) ) { positionByOffset = node.treeParent.calculateLineColByOffset() val fixableType = isFixable(newNode, configuration) - LONG_LINE.warnAndFix(configRules, emitWarn, isFixMode, + LONG_LINE.warnAndFix( + configRules, emitWarn, isFixMode, "max line length ${configuration.lineLength}, but was ${line.length}", offset + node.startOffset, node, fixableType !is None ) { @@ -136,13 +137,15 @@ class LineLength(configRules: List) : DiktatRule( do { when (parent.elementType) { BINARY_EXPRESSION, PARENTHESIZED -> { - val parentIsValArgListOrFunLitOrWhenEntry = listOf(VALUE_ARGUMENT_LIST, FUNCTION_LITERAL, WHEN_CONDITION_WITH_EXPRESSION) + val parentIsValArgListOrFunLitOrWhenEntry = + listOf(VALUE_ARGUMENT_LIST, FUNCTION_LITERAL, WHEN_CONDITION_WITH_EXPRESSION) findParentNodeWithSpecificTypeMany(parent, parentIsValArgListOrFunLitOrWhenEntry)?.let { parent = it } ?: run { val splitOffset = searchRightSplitAfterOperationReference(parent, configuration)?.second splitOffset?.let { - val parentIsBiExprOrParenthesized = parent.treeParent.elementType in listOf(BINARY_EXPRESSION, PARENTHESIZED) + val parentIsBiExprOrParenthesized = + parent.treeParent.elementType in listOf(BINARY_EXPRESSION, PARENTHESIZED) val parentIsFunOrProperty = parent.treeParent.elementType in listOf(FUN, PROPERTY) if (parentIsBiExprOrParenthesized || (parentIsFunOrProperty && splitOffset >= configuration.lineLength)) { parent = parent.treeParent @@ -172,7 +175,8 @@ class LineLength(configRules: List) : DiktatRule( FUNCTION_LITERAL -> return Lambda(parent) STRING_TEMPLATE, DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> { stringOrDot = parent - val parentIsBinExpOrValArgListOrWhenEntry = listOf(BINARY_EXPRESSION, VALUE_ARGUMENT_LIST, WHEN_CONDITION_WITH_EXPRESSION) + val parentIsBinExpOrValArgListOrWhenEntry = + listOf(BINARY_EXPRESSION, VALUE_ARGUMENT_LIST, WHEN_CONDITION_WITH_EXPRESSION) findParentNodeWithSpecificTypeMany(parent, parentIsBinExpOrValArgListOrWhenEntry)?.let { parent = it } ?: run { @@ -243,11 +247,11 @@ class LineLength(configRules: List) : DiktatRule( } private fun parserStringAndDot(node: ASTNode, configuration: LineLengthConfiguration) = - if (node.elementType == STRING_TEMPLATE) { - parserStringTemplate(node, configuration) - } else { - parserDotQualifiedExpression(node, configuration) - } + if (node.elementType == STRING_TEMPLATE) { + parserStringTemplate(node, configuration) + } else { + parserDotQualifiedExpression(node, configuration) + } /** * This class finds where the string can be split @@ -274,7 +278,8 @@ class LineLength(configRules: List) : DiktatRule( } else { positionByOffset(node.startOffset).second } - val delimiterIndex = node.text.substring(0, multiLineOffset + configuration.lineLength.toInt() - leftOffset).lastIndexOf(' ') + val delimiterIndex = + node.text.substring(0, multiLineOffset + configuration.lineLength.toInt() - leftOffset).lastIndexOf(' ') if (delimiterIndex == -1) { // we can't split this string, however may be we can move it entirely: // case when new line should be inserted after `+`. Example: "first" + "second" @@ -291,7 +296,8 @@ class LineLength(configRules: List) : DiktatRule( return None() } // minus 2 here as we are inserting ` +` and we don't want it to exceed line length - val shouldAddTwoSpaces = (multiLineOffset == 0) && (leftOffset + delimiterIndex > configuration.lineLength.toInt() - 2) + val shouldAddTwoSpaces = + (multiLineOffset == 0) && (leftOffset + delimiterIndex > configuration.lineLength.toInt() - 2) val correcterDelimiter = if (shouldAddTwoSpaces) { node.text.substring(0, delimiterIndex - 2).lastIndexOf(' ') } else { @@ -303,7 +309,10 @@ class LineLength(configRules: List) : DiktatRule( return StringTemplate(node, correcterDelimiter, multiLineOffset == 0) } - private fun parserDotQualifiedExpression(wrongNode: ASTNode, configuration: LineLengthConfiguration): LongLineFixableCases { + private fun parserDotQualifiedExpression( + wrongNode: ASTNode, + configuration: LineLengthConfiguration + ): LongLineFixableCases { val nodeDot = searchRightSplitBeforeDotOrSafeAccess(wrongNode, configuration, DOT) val nodeSafeAccess = searchRightSplitBeforeDotOrSafeAccess(wrongNode, configuration, SAFE_ACCESS) return nodeDot?.let { @@ -314,7 +323,7 @@ class LineLength(configRules: List) : DiktatRule( } private fun checkFunAndProperty(wrongNode: ASTNode) = - if (wrongNode.hasChildOfType(EQ)) FunAndProperty(wrongNode) else None() + if (wrongNode.hasChildOfType(EQ)) FunAndProperty(wrongNode) else None() private fun checkComment(wrongNode: ASTNode, configuration: LineLengthConfiguration): LongLineFixableCases { val leftOffset = positionByOffset(wrongNode.startOffset).second @@ -322,8 +331,12 @@ class LineLength(configRules: List) : DiktatRule( if (stringBeforeCommentContent.length >= configuration.lineLength.toInt() - leftOffset) { return None() } - val indexLastSpace = wrongNode.text.substring(stringBeforeCommentContent.length, configuration.lineLength.toInt() - leftOffset).lastIndexOf(' ') - val isNewLine = wrongNode.treePrev?.isWhiteSpaceWithNewline() ?: wrongNode.treeParent?.treePrev?.isWhiteSpaceWithNewline() ?: false + val indexLastSpace = + wrongNode.text.substring(stringBeforeCommentContent.length, configuration.lineLength.toInt() - leftOffset) + .lastIndexOf(' ') + val isNewLine = + wrongNode.treePrev?.isWhiteSpaceWithNewline() ?: wrongNode.treeParent?.treePrev?.isWhiteSpaceWithNewline() + ?: false if (isNewLine && indexLastSpace == -1) { return None() } @@ -355,7 +368,10 @@ class LineLength(configRules: List) : DiktatRule( @Suppress("UnsafeCallOnNullableType", "WHEN_WITHOUT_ELSE") private fun fixError(fixableType: LongLineFixableCases) { when (fixableType) { - is FunAndProperty -> fixableType.node.appendNewlineMergingWhiteSpace(null, fixableType.node.findChildByType(EQ)!!.treeNext) + is FunAndProperty -> fixableType.node.appendNewlineMergingWhiteSpace( + null, + fixableType.node.findChildByType(EQ)!!.treeNext + ) is Comment -> fixComment(fixableType) is LongBinaryExpression -> fixLongBinaryExpression(fixableType) is BinaryExpression -> fixBinaryExpression(fixableType.node) @@ -395,12 +411,18 @@ class LineLength(configRules: List) : DiktatRule( var startOffset = 0 node.getFirstChildWithType(COMMA)?.let { if (positionByOffset(it.startOffset).second > lineLength) { - node.appendNewlineMergingWhiteSpace(node.findChildByType(LPAR)!!.treeNext, node.findChildByType(LPAR)!!.treeNext) + node.appendNewlineMergingWhiteSpace( + node.findChildByType(LPAR)!!.treeNext, + node.findChildByType(LPAR)!!.treeNext + ) node.appendNewlineMergingWhiteSpace(node.findChildByType(RPAR), node.findChildByType(RPAR)) startOffset = wrongArgumentList.maximumLineLength.lineLength.toInt() } } ?: node.getFirstChildWithType(RPAR)?.let { - node.appendNewlineMergingWhiteSpace(node.findChildByType(LPAR)!!.treeNext, node.findChildByType(LPAR)!!.treeNext) + node.appendNewlineMergingWhiteSpace( + node.findChildByType(LPAR)!!.treeNext, + node.findChildByType(LPAR)!!.treeNext + ) node.appendNewlineMergingWhiteSpace(node.findChildByType(RPAR), node.findChildByType(RPAR)) startOffset = wrongArgumentList.maximumLineLength.lineLength.toInt() } @@ -462,7 +484,10 @@ class LineLength(configRules: List) : DiktatRule( val parent = wrongNode.treeParent parent.removeChild(wrongNode) newLineNodeOnPreviousLine.treeParent.addChild(wrongNode, newLineNodeOnPreviousLine.treeNext) - newLineNodeOnPreviousLine.treeParent.addChild(PsiWhiteSpaceImpl("\n"), newLineNodeOnPreviousLine.treeNext.treeNext) + newLineNodeOnPreviousLine.treeParent.addChild( + PsiWhiteSpaceImpl("\n"), + newLineNodeOnPreviousLine.treeNext.treeNext + ) } } } @@ -492,8 +517,14 @@ class LineLength(configRules: List) : DiktatRule( */ @Suppress("UnsafeCallOnNullableType") private fun fixLambda(node: ASTNode) { - node.appendNewlineMergingWhiteSpace(node.findChildByType(LBRACE)!!.treeNext, node.findChildByType(LBRACE)!!.treeNext) - node.appendNewlineMergingWhiteSpace(node.findChildByType(RBRACE)!!.treePrev, node.findChildByType(RBRACE)!!.treePrev) + node.appendNewlineMergingWhiteSpace( + node.findChildByType(LBRACE)!!.treeNext, + node.findChildByType(LBRACE)!!.treeNext + ) + node.appendNewlineMergingWhiteSpace( + node.findChildByType(RBRACE)!!.treePrev, + node.findChildByType(RBRACE)!!.treePrev + ) } @Suppress("UnsafeCallOnNullableType", "COMMENT_WHITE_SPACE") @@ -502,11 +533,11 @@ class LineLength(configRules: List) : DiktatRule( val firstPart = incorrectText.substring(0, wrongStringTemplate.delimiterIndex) val secondPart = incorrectText.substring(wrongStringTemplate.delimiterIndex, incorrectText.length) val textBetweenParts = - if (wrongStringTemplate.isOneLineString) { - "\" +\n\"" - } else { - "\n" - } + if (wrongStringTemplate.isOneLineString) { + "\" +\n\"" + } else { + "\n" + } val correctNode = KotlinParser().createNode("$firstPart$textBetweenParts$secondPart") wrongStringTemplate.node.treeParent.replaceChild(wrongStringTemplate.node, correctNode) } @@ -516,7 +547,8 @@ class LineLength(configRules: List) : DiktatRule( */ @Suppress("UnsafeCallOnNullableType") private fun fixLongBinaryExpression(wrongBinaryExpression: LongBinaryExpression) { - val anySplitNode = searchSomeSplitInBinaryExpression(wrongBinaryExpression.node, wrongBinaryExpression.maximumLineLength) + val anySplitNode = + searchSomeSplitInBinaryExpression(wrongBinaryExpression.node, wrongBinaryExpression.maximumLineLength) val rigthSplitnode = anySplitNode[0] ?: anySplitNode[1] ?: anySplitNode[2] val nodeOperationReference = rigthSplitnode?.first?.getFirstChildWithType(OPERATION_REFERENCE) rigthSplitnode?.let { @@ -544,7 +576,8 @@ class LineLength(configRules: List) : DiktatRule( */ private fun searchBinaryExpression(node: ASTNode, binList: MutableList) { if (node.hasChildOfType(BINARY_EXPRESSION) || node.hasChildOfType(PARENTHESIZED) || - node.hasChildOfType(POSTFIX_EXPRESSION)) { + node.hasChildOfType(POSTFIX_EXPRESSION) + ) { node.getChildren(null) .filter { it.elementType == BINARY_EXPRESSION || it.elementType == PARENTHESIZED || @@ -560,6 +593,9 @@ class LineLength(configRules: List) : DiktatRule( } } + private fun isTypeDotQuaOrSafeAccessOrPostfixExpression(node: ASTNode):Boolean = + node.elementType == DOT_QUALIFIED_EXPRESSION || node.elementType == SAFE_ACCESS_EXPRESSION || node.elementType == POSTFIX_EXPRESSION + /** * This method uses recursion to store dot qualified expression node in the order in which they are located * Also dotList contains nodes with PREFIX_EXPRESSION element type ( !isFoo(), !isValid)) @@ -568,10 +604,10 @@ class LineLength(configRules: List) : DiktatRule( *@param dotList mutable list of ASTNode to store nodes */ private fun searchDotOrSafeAccess(node: ASTNode, dotList: MutableList) { - if (node.elementType == DOT_QUALIFIED_EXPRESSION || node.elementType == SAFE_ACCESS_EXPRESSION || node.elementType == POSTFIX_EXPRESSION) { + if (isTypeDotQuaOrSafeAccessOrPostfixExpression(node)) { node.getChildren(null) .filter { - it.elementType == DOT_QUALIFIED_EXPRESSION || it.elementType == SAFE_ACCESS_EXPRESSION || it.elementType == POSTFIX_EXPRESSION + isTypeDotQuaOrSafeAccessOrPostfixExpression(it) } .forEach { searchDotOrSafeAccess(it, dotList) @@ -662,7 +698,8 @@ class LineLength(configRules: List) : DiktatRule( val list: MutableList = mutableListOf() searchDotOrSafeAccess(parent, list) val offsetFromMaximum = 10 - return list.map { + return list.asSequence() + .map { val offset = it.getFirstChildWithType(type)?.run { positionByOffset(this.startOffset).second } ?: run { @@ -671,8 +708,7 @@ class LineLength(configRules: List) : DiktatRule( it to offset } .sortedBy { it.second } - .reversed() - .firstOrNull { (it, offset) -> + .lastOrNull { (it, offset) -> offset <= configuration.lineLength + 1 } }