Skip to content

Commit

Permalink
Fix false positives for comments in yml/indent rule
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed Jan 5, 2021
1 parent 5b42841 commit ebc779e
Show file tree
Hide file tree
Showing 25 changed files with 331 additions and 27 deletions.
155 changes: 134 additions & 21 deletions src/rules/indent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,35 +521,36 @@ export default createRule("indent", {
lineIndents: (LineIndentStep1 | undefined)[],
) {
const results: (LineIndentStep2 | undefined)[] = []
let nextIndent: LineIndentStep2 | null = null
for (let line = sourceCode.lines.length; line >= 0; line--) {
const lineIndent = lineIndents[line]
const commentLines: {
range: [number, number]
commentLineIndents: LineIndentStep1[]
}[] = []
for (const lineIndent of lineIndents) {
if (!lineIndent) {
continue
}
if (lineIndent.expectedIndent == null) {
if (lineIndent.firstToken.type === "Block") {
const expectedIndent: number | null =
nextIndent != null
? nextIndent.expectedIndent
: null
if (expectedIndent != null) {
nextIndent = results[line] = {
line,
expectedIndent,
actualIndent: lineIndent.actualIndent,
markData: lineIndent.markData,
}
}
const line = lineIndent.line
if (lineIndent.firstToken.type === "Block") {
const last = commentLines[commentLines.length - 1]
if (last && last.range[1] === line - 1) {
last.range[1] = line
last.commentLineIndents.push(lineIndent)
} else {
commentLines.push({
range: [line, line],
commentLineIndents: [lineIndent],
})
}
} else {
const indent = (results[line] = {
} else if (lineIndent.expectedIndent != null) {
const indent = {
line,
expectedIndent: lineIndent.expectedIndent,
actualIndent: lineIndent.actualIndent,
markData: lineIndent.markData,
})
nextIndent = indent
}
if (!results[line]) {
results[line] = indent
}
if (lineIndent.lastScalar) {
const scalarNode = lineIndent.lastScalar.node
if (
Expand Down Expand Up @@ -577,8 +578,120 @@ export default createRule("indent", {
}
}

processComments(commentLines, lineIndents)

return results

/**
* Process comments.
*/
function processComments(
commentLines: {
range: [number, number]
commentLineIndents: LineIndentStep1[]
}[],
lineIndents: (LineIndentStep1 | undefined)[],
) {
for (const { range, commentLineIndents } of commentLines) {
let prev: LineIndentStep2 | undefined = results
.slice(0, range[0])
.filter((data) => data)
.pop()
const next: LineIndentStep2 | undefined = results
.slice(range[1] + 1)
.filter((data) => data)
.shift()

if (isBlockLiteral(prev)) {
prev = undefined
}

const expectedIndents: number[] = []
let either: LineIndentStep2 | undefined
if (prev && next) {
expectedIndents.unshift(next.expectedIndent)
if (next.expectedIndent < prev.expectedIndent) {
let indent = next.expectedIndent + numOfIndent
while (indent <= prev.expectedIndent) {
expectedIndents.unshift(indent)
indent += numOfIndent
}
}
} else if ((either = prev || next)) {
expectedIndents.unshift(either.expectedIndent)
if (!next) {
let indent = either.expectedIndent - numOfIndent
while (indent >= 0) {
expectedIndents.push(indent)
indent -= numOfIndent
}
}
}
if (!expectedIndents.length) {
continue
}

let expectedIndent = expectedIndents[0]
for (const commentLineIndent of commentLineIndents) {
if (results[commentLineIndent.line]) {
continue
}
expectedIndent = Math.min(
expectedIndents.find((indent, index) => {
if (indent <= commentLineIndent.actualIndent) {
return true
}
const prev = expectedIndents[index + 1] ?? -1
return (
prev < commentLineIndent.actualIndent &&
commentLineIndent.actualIndent < indent
)
}) ?? expectedIndent,
expectedIndent,
)
results[commentLineIndent.line] = {
line: commentLineIndent.line,
expectedIndent,
actualIndent: commentLineIndent.actualIndent,
markData: commentLineIndent.markData,
}
}
}

/**
* Checks whether given prev data is block literal
*/
function isBlockLiteral(
prev: LineIndentStep2 | undefined,
): boolean {
if (!prev) {
return false
}
for (let prevLine = prev.line; prevLine >= 0; prevLine--) {
const prevLineIndent = lineIndents[prev.line]
if (!prevLineIndent) {
continue
}
if (prevLineIndent.lastScalar) {
const scalarNode = prevLineIndent.lastScalar.node
if (
scalarNode.style === "literal" ||
scalarNode.style === "folded"
) {
if (
scalarNode.loc.start.line <= prev.line &&
prev.line <= scalarNode.loc.end.line
) {
return true
}
}
}
return false
}
return false
}
}

/**
* Process block literal
*/
Expand Down
17 changes: 17 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments01-errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{
"message": "Expected indentation of 4 spaces but found 6 spaces.",
"line": 5,
"column": 1
},
{
"message": "Expected indentation of 4 spaces but found 2 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 4 spaces but found 6 spaces.",
"line": 13,
"column": 1
}
]
13 changes: 13 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments01-input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# {"options":[2]}
a:
b:
c: 1
# d: 2
e:
f:
# g: 1
h: 2
i:
j:
k: 1
# l: 2
13 changes: 13 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments01-output.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# indent/invalid/comments01-input.yml
a:
b:
c: 1
# d: 2
e:
f:
# g: 1
h: 2
i:
j:
k: 1
# l: 2
12 changes: 12 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments02-errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"message": "Expected indentation of 4 spaces but found 6 spaces.",
"line": 10,
"column": 1
},
{
"message": "Expected indentation of 2 spaces but found 0 spaces.",
"line": 15,
"column": 1
}
]
16 changes: 16 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments02-input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# {"options":[2]}
a:
b:
c: 1
# d: 2
e: 3
f:
g:
h: 1
# i: 2
j: 3
k:
l:
m: 1
# n: 2
o: 3
16 changes: 16 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments02-output.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# indent/invalid/comments02-input.yml
a:
b:
c: 1
# d: 2
e: 3
f:
g:
h: 1
# i: 2
j: 3
k:
l:
m: 1
# n: 2
o: 3
7 changes: 7 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments03-errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "Expected indentation of 2 spaces but found 4 spaces.",
"line": 8,
"column": 1
}
]
13 changes: 13 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments03-input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# {"options":[2]}
a:
b:
c: 1
d: 2
# e: 3
# f:
# g:
# h: 1
# i: 2
k:
l:
m: 1
13 changes: 13 additions & 0 deletions tests/fixtures/rules/indent/invalid/comments03-output.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# indent/invalid/comments03-input.yml
a:
b:
c: 1
d: 2
# e: 3
# f:
# g:
# h: 1
# i: 2
k:
l:
m: 1
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"message": "Expected indentation of 8 spaces but found 1 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 8 spaces but found 1 spaces.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

text

# Comment
# Comment
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"message": "Expected indentation of 8 spaces but found 1 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 8 spaces but found 1 spaces.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

text

# Comment
# Comment
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"message": "Expected indentation of 4 spaces but found 1 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 4 spaces but found 1 spaces.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

text

# Comment
# Comment
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"message": "Expected indentation of 4 spaces but found 1 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 4 spaces but found 1 spaces.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

text

# Comment
# Comment
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"message": "Expected indentation of 2 spaces but found 1 spaces.",
"line": 8,
"column": 1
},
{
"message": "Expected indentation of 2 spaces but found 1 spaces.",
"line": 10,
"column": 1
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

text

# Comment
# Comment
Loading

0 comments on commit ebc779e

Please sign in to comment.