Skip to content

Commit

Permalink
Fixed wrong autofix when properties on the same line in new-line-betw…
Browse files Browse the repository at this point in the history
…een-multi-line-property. (#1378)

I also improved the position of the report.
  • Loading branch information
ota-meshi committed Dec 16, 2020
1 parent 96425c6 commit 1b8beb0
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 47 deletions.
107 changes: 73 additions & 34 deletions lib/rules/new-line-between-multi-line-property.js
Expand Up @@ -5,6 +5,46 @@
'use strict'

const utils = require('../utils')

/**
* @param {Token} node
*/
function isComma(node) {
return node.type === 'Punctuator' && node.value === ','
}

/**
* Check whether the between given nodes has empty line.
* @param {SourceCode} sourceCode
* @param {ASTNode} pre
* @param {ASTNode} cur
*/
function* iterateBetweenTokens(sourceCode, pre, cur) {
yield sourceCode.getLastToken(pre)
yield* sourceCode.getTokensBetween(pre, cur, {
includeComments: true
})
yield sourceCode.getFirstToken(cur)
}

/**
* Check whether the between given nodes has empty line.
* @param {SourceCode} sourceCode
* @param {ASTNode} pre
* @param {ASTNode} cur
*/
function hasEmptyLine(sourceCode, pre, cur) {
/** @type {Token|null} */
let preToken = null
for (const token of iterateBetweenTokens(sourceCode, pre, cur)) {
if (preToken && token.loc.start.line - preToken.loc.end.line >= 2) {
return true
}
preToken = token
}
return false
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -35,9 +75,6 @@ module.exports = {

/** @param {RuleContext} context */
create(context) {
// always insert one line
const insertLine = 1

let minLineOfMultilineProperty = 2
if (
context.options &&
Expand Down Expand Up @@ -71,42 +108,44 @@ module.exports = {
const cur = properties[i]
const pre = properties[i - 1]

const leadingComments = sourceCode
.getTokensBetween(pre, cur, { includeComments: true })
.filter((token) => ['Line', 'Block'].includes(token.type))
const lineCountOfPreProperty =
pre.loc.end.line - pre.loc.start.line + 1
let curStartLine = cur.loc.start.line
if (leadingComments.length) {
curStartLine = leadingComments[0].loc.start.line
if (lineCountOfPreProperty < minLineOfMultilineProperty) {
continue
}

if (hasEmptyLine(sourceCode, pre, cur)) {
continue
}
const lineCountBetweenCurAndPreProperty =
curStartLine - pre.loc.end.line - 1
if (
lineCountOfPreProperty >= minLineOfMultilineProperty &&
lineCountBetweenCurAndPreProperty < insertLine
) {
context.report({
node: pre,
loc: pre.loc,
message:
'Enforce new lines between multi-line properties in Vue components.',
fix(fixer) {
let firstPositionOfLine = cur.range[0] - cur.loc.start.column
if (leadingComments.length) {
const firstComment = leadingComments[0]
firstPositionOfLine =
firstComment.range[0] - firstComment.loc.start.column

context.report({
node: pre,
loc: {
start: pre.loc.end,
end: cur.loc.start
},
message:
'Enforce new lines between multi-line properties in Vue components.',
fix(fixer) {
/** @type {Token|null} */
let preToken = null
for (const token of iterateBetweenTokens(
sourceCode,
pre,
cur
)) {
if (
preToken &&
preToken.loc.end.line < token.loc.start.line
) {
return fixer.insertTextAfter(preToken, '\n')
}
// this action equal to insert number of line before node
return fixer.insertTextAfterRange(
[firstPositionOfLine, firstPositionOfLine],
'\n'
// to avoid conflict with no-multiple-empty-lines, only insert one newline
)
preToken = token
}
})
}
const commaToken = sourceCode.getTokenAfter(pre, isComma)
return fixer.insertTextAfter(commaToken || pre, '\n\n')
}
})
}
}
})
Expand Down

0 comments on commit 1b8beb0

Please sign in to comment.