|
5 | 5 | 'use strict'
|
6 | 6 |
|
7 | 7 | const utils = require('../utils')
|
| 8 | + |
| 9 | +/** |
| 10 | + * @param {Token} node |
| 11 | + */ |
| 12 | +function isComma(node) { |
| 13 | + return node.type === 'Punctuator' && node.value === ',' |
| 14 | +} |
| 15 | + |
| 16 | +/** |
| 17 | + * Check whether the between given nodes has empty line. |
| 18 | + * @param {SourceCode} sourceCode |
| 19 | + * @param {ASTNode} pre |
| 20 | + * @param {ASTNode} cur |
| 21 | + */ |
| 22 | +function* iterateBetweenTokens(sourceCode, pre, cur) { |
| 23 | + yield sourceCode.getLastToken(pre) |
| 24 | + yield* sourceCode.getTokensBetween(pre, cur, { |
| 25 | + includeComments: true |
| 26 | + }) |
| 27 | + yield sourceCode.getFirstToken(cur) |
| 28 | +} |
| 29 | + |
| 30 | +/** |
| 31 | + * Check whether the between given nodes has empty line. |
| 32 | + * @param {SourceCode} sourceCode |
| 33 | + * @param {ASTNode} pre |
| 34 | + * @param {ASTNode} cur |
| 35 | + */ |
| 36 | +function hasEmptyLine(sourceCode, pre, cur) { |
| 37 | + /** @type {Token|null} */ |
| 38 | + let preToken = null |
| 39 | + for (const token of iterateBetweenTokens(sourceCode, pre, cur)) { |
| 40 | + if (preToken && token.loc.start.line - preToken.loc.end.line >= 2) { |
| 41 | + return true |
| 42 | + } |
| 43 | + preToken = token |
| 44 | + } |
| 45 | + return false |
| 46 | +} |
| 47 | + |
8 | 48 | // ------------------------------------------------------------------------------
|
9 | 49 | // Rule Definition
|
10 | 50 | // ------------------------------------------------------------------------------
|
@@ -35,9 +75,6 @@ module.exports = {
|
35 | 75 |
|
36 | 76 | /** @param {RuleContext} context */
|
37 | 77 | create(context) {
|
38 |
| - // always insert one line |
39 |
| - const insertLine = 1 |
40 |
| - |
41 | 78 | let minLineOfMultilineProperty = 2
|
42 | 79 | if (
|
43 | 80 | context.options &&
|
@@ -71,42 +108,44 @@ module.exports = {
|
71 | 108 | const cur = properties[i]
|
72 | 109 | const pre = properties[i - 1]
|
73 | 110 |
|
74 |
| - const leadingComments = sourceCode |
75 |
| - .getTokensBetween(pre, cur, { includeComments: true }) |
76 |
| - .filter((token) => ['Line', 'Block'].includes(token.type)) |
77 | 111 | const lineCountOfPreProperty =
|
78 | 112 | pre.loc.end.line - pre.loc.start.line + 1
|
79 |
| - let curStartLine = cur.loc.start.line |
80 |
| - if (leadingComments.length) { |
81 |
| - curStartLine = leadingComments[0].loc.start.line |
| 113 | + if (lineCountOfPreProperty < minLineOfMultilineProperty) { |
| 114 | + continue |
| 115 | + } |
| 116 | + |
| 117 | + if (hasEmptyLine(sourceCode, pre, cur)) { |
| 118 | + continue |
82 | 119 | }
|
83 |
| - const lineCountBetweenCurAndPreProperty = |
84 |
| - curStartLine - pre.loc.end.line - 1 |
85 |
| - if ( |
86 |
| - lineCountOfPreProperty >= minLineOfMultilineProperty && |
87 |
| - lineCountBetweenCurAndPreProperty < insertLine |
88 |
| - ) { |
89 |
| - context.report({ |
90 |
| - node: pre, |
91 |
| - loc: pre.loc, |
92 |
| - message: |
93 |
| - 'Enforce new lines between multi-line properties in Vue components.', |
94 |
| - fix(fixer) { |
95 |
| - let firstPositionOfLine = cur.range[0] - cur.loc.start.column |
96 |
| - if (leadingComments.length) { |
97 |
| - const firstComment = leadingComments[0] |
98 |
| - firstPositionOfLine = |
99 |
| - firstComment.range[0] - firstComment.loc.start.column |
| 120 | + |
| 121 | + context.report({ |
| 122 | + node: pre, |
| 123 | + loc: { |
| 124 | + start: pre.loc.end, |
| 125 | + end: cur.loc.start |
| 126 | + }, |
| 127 | + message: |
| 128 | + 'Enforce new lines between multi-line properties in Vue components.', |
| 129 | + fix(fixer) { |
| 130 | + /** @type {Token|null} */ |
| 131 | + let preToken = null |
| 132 | + for (const token of iterateBetweenTokens( |
| 133 | + sourceCode, |
| 134 | + pre, |
| 135 | + cur |
| 136 | + )) { |
| 137 | + if ( |
| 138 | + preToken && |
| 139 | + preToken.loc.end.line < token.loc.start.line |
| 140 | + ) { |
| 141 | + return fixer.insertTextAfter(preToken, '\n') |
100 | 142 | }
|
101 |
| - // this action equal to insert number of line before node |
102 |
| - return fixer.insertTextAfterRange( |
103 |
| - [firstPositionOfLine, firstPositionOfLine], |
104 |
| - '\n' |
105 |
| - // to avoid conflict with no-multiple-empty-lines, only insert one newline |
106 |
| - ) |
| 143 | + preToken = token |
107 | 144 | }
|
108 |
| - }) |
109 |
| - } |
| 145 | + const commaToken = sourceCode.getTokenAfter(pre, isComma) |
| 146 | + return fixer.insertTextAfter(commaToken || pre, '\n\n') |
| 147 | + } |
| 148 | + }) |
110 | 149 | }
|
111 | 150 | }
|
112 | 151 | })
|
|
0 commit comments