Skip to content

Commit

Permalink
Merge branch 'master' into feature/gradle-pluin-inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
petertrr committed Nov 17, 2021
2 parents b86417b + 0451db5 commit 6266f96
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import org.cqfn.diktat.ruleset.rules.DiktatRule
import org.cqfn.diktat.ruleset.utils.KotlinParser
import org.cqfn.diktat.ruleset.utils.appendNewlineMergingWhiteSpace
import org.cqfn.diktat.ruleset.utils.calculateLineColByOffset
import org.cqfn.diktat.ruleset.utils.findAllNodesWithConditionOnLine
import org.cqfn.diktat.ruleset.utils.findParentNodeWithSpecificType
import org.cqfn.diktat.ruleset.utils.getLineNumber
import org.cqfn.diktat.ruleset.utils.hasChildOfType

import com.pinterest.ktlint.core.ast.ElementType.ANNOTATION_ENTRY
Expand Down Expand Up @@ -290,14 +292,19 @@ class LineLength(configRules: List<RulesConfig>) : DiktatRule(
removeChild(wrongNode)
}
} else {
wrongNode.treeParent.treeParent?.let {
if (wrongNode.treePrev.isWhiteSpace()) {
wrongNode.treeParent.removeChild(wrongNode.treePrev)
}

val newLineNodeOnPreviousLine = wrongNode.findAllNodesWithConditionOnLine(wrongNode.getLineNumber() - 1) {
it.elementType == WHITE_SPACE && it.textContains('\n')
}?.lastOrNull()

newLineNodeOnPreviousLine?.let {
val parent = wrongNode.treeParent
if (wrongNode.treePrev.isWhiteSpace()) {
parent.removeChild(wrongNode.treePrev)
}
parent.removeChild(wrongNode)
it.addChild(wrongNode, parent)
it.addChild(PsiWhiteSpaceImpl("\n"), parent)
newLineNodeOnPreviousLine.treeParent.addChild(wrongNode, newLineNodeOnPreviousLine.treeNext)
newLineNodeOnPreviousLine.treeParent.addChild(PsiWhiteSpaceImpl("\n"), newLineNodeOnPreviousLine.treeNext.treeNext)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,41 @@ fun ASTNode.lastLineNumber() = getLineNumber() + text.count { it == '\n' }
*/
fun ASTNode.calculateLineColByOffset() = buildPositionInTextLocator(text)

/**
* Return all nodes located at the specific line
*
* @param line
* @return corresponding list of nodes
*/
fun ASTNode.findAllNodesOnLine(
line: Int
): List<ASTNode>? {
val rootNode = this.getRootNode()
val fileLines = rootNode.text.lines()

if (line <= 0 || line > fileLines.size) {
return null
}

val positionByOffset = rootNode.calculateLineColByOffset()

val lineOffset = this.findOffsetByLine(line, positionByOffset)

return this.getAllNodesOnLine(lineOffset, line, positionByOffset).toList()
}

/**
* Return all nodes located at the specific line satisfying [condition]
*
* @param line
* @param condition
* @return corresponding list of nodes
*/
fun ASTNode.findAllNodesWithConditionOnLine(
line: Int,
condition: (ASTNode) -> Boolean
): List<ASTNode>? = this.findAllNodesOnLine(line)?.filter(condition)

/**
* Retrieves file name from user data of this node
*
Expand Down Expand Up @@ -767,6 +802,66 @@ fun ASTNode.hasEqBinaryExpression(): Boolean =
fun ASTNode.getLineNumber(): Int =
calculateLineNumber()

private fun ASTNode.findOffsetByLine(line: Int, positionByOffset: (Int) -> Pair<Int, Int>): Int {
val currentLine = this.getLineNumber()
val currentOffset = this.startOffset

var forwardDirection = true
// We additionaly consider the offset and line for current node in aim to speed up the search
// and not start any time from beginning of file, if possible
//
// If current line is closer to the requested line, start search from it
// otherwise search from the beginning of file
var lineOffset = if (line < currentLine) {
if ((currentLine - line) < line) {
forwardDirection = false
currentOffset
} else {
0
}
} else {
currentOffset
}

while (positionByOffset(lineOffset).first != line) {
if (forwardDirection) {
lineOffset++
} else {
lineOffset--
}
}
return lineOffset
}

@Suppress("UnsafeCallOnNullableType")
private fun ASTNode.getAllNodesOnLine(
lineOffset: Int,
line: Int,
positionByOffset: (Int) -> Pair<Int, Int>
): MutableSet<ASTNode> {
val rootNode = this.getRootNode()
var beginningOfLineOffset = lineOffset
var endOfLineOffset = lineOffset

while (beginningOfLineOffset > 0 && positionByOffset(beginningOfLineOffset - 1).first == line) {
beginningOfLineOffset--
}

while (endOfLineOffset < rootNode.text.length && positionByOffset(endOfLineOffset + 1).first == line) {
endOfLineOffset++
}

val nodesSet: MutableSet<ASTNode> = mutableSetOf()

var currentOffset = beginningOfLineOffset
while (currentOffset <= endOfLineOffset) {
nodesSet.add(rootNode.psi.findElementAt(currentOffset)!!.node)
currentOffset++
}

return nodesSet
}

/**
* This function calculates line number instead of using cached values.
* It should be used when AST could be previously mutated by auto fixers.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class LineLengthFixTest : FixTestBase("test/paragraph3/long_line", ::LineLength)
fixAndCompare("LongLineCommentExpected.kt", "LongLineCommentTest.kt", rulesConfigListLineLength)
}

@Test
fun `should fix long inline comments`() {
fixAndCompare("LongInlineCommentsExpected.kt", "LongInlineCommentsTest.kt", rulesConfigListLineLength)
}

@Test
fun `should not fix long comment which located on the line length limit`() {
fixAndCompare("LongLineCommentExpected2.kt", "LongLineCommentTest2.kt", rulesConfigListDefaultLineLength)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package test.paragraph3.long_line

fun foobar() {
foo(
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
bar()
)
}

fun foobar() {
foo(
//ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
bar()
)
}

fun foobar() {
foo(
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
bar(),
// uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
baz()
)
}

fun foobar() {
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
bar()
// uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
baz()
}

enum class SomeEnum {
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
FOO,
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
BAR,
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
BAZ,
};

fun foo() {
when (node.elementType) {
ElementType.CLASS, ElementType.FUN, ElementType.PROPERTY -> checkBlankLineAfterKdoc(node)
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ElementType.IF -> handleIfElse(node)
ElementType.EOL_COMMENT, ElementType.BLOCK_COMMENT -> handleEolAndBlockComments(node, configuration)
ElementType.KDOC -> handleKdocComments(node, configuration)
// ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
else -> {
// this is a generated else block
}
}
}

// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
fun foo() {
// bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
if (a) {
// cccccccccccccccccccccccccccccccccccccccccc
a()
// dddddddddddddddddddddddddddddddddddddddddd
} else {
// eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
b()
// ffffffffffffffffffffffffffffffffffffffffff
}
// gggggggggggggggggggggggggggggggggggggggggggggggggggg
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package test.paragraph3.long_line

fun foobar() {
foo(
bar() // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}

fun foobar() {
foo(
bar()//ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
)
}

fun foobar() {
foo(
bar(), // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
baz() // uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
)
}

fun foobar() {
bar() // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
baz() // uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
}

enum class SomeEnum {
FOO, // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
BAR, // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
BAZ, // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
};

fun foo() {
when (node.elementType) {
ElementType.CLASS, ElementType.FUN, ElementType.PROPERTY -> checkBlankLineAfterKdoc(node)
ElementType.IF -> handleIfElse(node) // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ElementType.EOL_COMMENT, ElementType.BLOCK_COMMENT -> handleEolAndBlockComments(node, configuration)
ElementType.KDOC -> handleKdocComments(node, configuration)
else -> { // ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// this is a generated else block
}
}
}

fun foo() { // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
if (a) { // bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
a() // cccccccccccccccccccccccccccccccccccccccccc
} else { // dddddddddddddddddddddddddddddddddddddddddd
b() // eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
} // ffffffffffffffffffffffffffffffffffffffffff
} // gggggggggggggggggggggggggggggggggggggggggggggggggggg

0 comments on commit 6266f96

Please sign in to comment.