Skip to content

Commit

Permalink
### Whats added:
Browse files Browse the repository at this point in the history
 * corrected logic fix and warn String Template in LineLength rule
 * added logic fix and warn long Dot Qualified Expression and Safe Access Expression in LineLength rule
 * added logic fix and warn Value Arguments List in LineLength rule
 * added and corrected fix and warn tests in LineLength rule
 * fix code with diktat:fix@diktat
 * added comments to classes and functions
 * correct code with running detect

 ### Issue (#1243)
  • Loading branch information
Arrgentum committed Jun 1, 2022
1 parent 2bcc2f8 commit 3a37ead
Showing 1 changed file with 70 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,12 @@ class LineLength(configRules: List<RulesConfig>) : 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
) {
Expand Down Expand Up @@ -136,13 +137,15 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
do {
when (parent.elementType) {
BINARY_EXPRESSION, PARENTHESIZED -> {
val parentIsValArgListOrFunLitOrWhenEntry = listOf<IElementType>(VALUE_ARGUMENT_LIST, FUNCTION_LITERAL, WHEN_CONDITION_WITH_EXPRESSION)
val parentIsValArgListOrFunLitOrWhenEntry =
listOf<IElementType>(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
Expand Down Expand Up @@ -172,7 +175,8 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
FUNCTION_LITERAL -> return Lambda(parent)
STRING_TEMPLATE, DOT_QUALIFIED_EXPRESSION, SAFE_ACCESS_EXPRESSION -> {
stringOrDot = parent
val parentIsBinExpOrValArgListOrWhenEntry = listOf<IElementType>(BINARY_EXPRESSION, VALUE_ARGUMENT_LIST, WHEN_CONDITION_WITH_EXPRESSION)
val parentIsBinExpOrValArgListOrWhenEntry =
listOf<IElementType>(BINARY_EXPRESSION, VALUE_ARGUMENT_LIST, WHEN_CONDITION_WITH_EXPRESSION)
findParentNodeWithSpecificTypeMany(parent, parentIsBinExpOrValArgListOrWhenEntry)?.let {
parent = it
} ?: run {
Expand Down Expand Up @@ -243,11 +247,11 @@ class LineLength(configRules: List<RulesConfig>) : 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
Expand All @@ -274,7 +278,8 @@ class LineLength(configRules: List<RulesConfig>) : 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"
Expand All @@ -291,7 +296,8 @@ class LineLength(configRules: List<RulesConfig>) : 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 {
Expand All @@ -303,7 +309,10 @@ class LineLength(configRules: List<RulesConfig>) : 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 {
Expand All @@ -314,16 +323,20 @@ class LineLength(configRules: List<RulesConfig>) : 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
val stringBeforeCommentContent = wrongNode.text.takeWhile { it == ' ' || it == '/' }
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()
}
Expand Down Expand Up @@ -355,7 +368,10 @@ class LineLength(configRules: List<RulesConfig>) : 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)
Expand Down Expand Up @@ -395,12 +411,18 @@ class LineLength(configRules: List<RulesConfig>) : 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()
}
Expand Down Expand Up @@ -462,7 +484,10 @@ class LineLength(configRules: List<RulesConfig>) : 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
)
}
}
}
Expand Down Expand Up @@ -492,8 +517,14 @@ class LineLength(configRules: List<RulesConfig>) : 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")
Expand All @@ -502,11 +533,11 @@ class LineLength(configRules: List<RulesConfig>) : 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)
}
Expand All @@ -516,7 +547,8 @@ class LineLength(configRules: List<RulesConfig>) : 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 {
Expand Down Expand Up @@ -544,7 +576,8 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
*/
private fun searchBinaryExpression(node: ASTNode, binList: MutableList<ASTNode>) {
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 ||
Expand All @@ -560,6 +593,9 @@ class LineLength(configRules: List<RulesConfig>) : 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))
Expand All @@ -568,10 +604,10 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
*@param dotList mutable list of ASTNode to store nodes
*/
private fun searchDotOrSafeAccess(node: ASTNode, dotList: MutableList<ASTNode>) {
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)
Expand Down Expand Up @@ -662,7 +698,8 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
val list: MutableList<ASTNode> = 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 {
Expand All @@ -671,8 +708,7 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
it to offset
}
.sortedBy { it.second }
.reversed()
.firstOrNull { (it, offset) ->
.lastOrNull { (it, offset) ->
offset <= configuration.lineLength + 1
}
}
Expand Down

0 comments on commit 3a37ead

Please sign in to comment.