|
1 | 1 | /**
|
2 |
| - * @author Barthy Bonhomme <[email protected]> <github.com/barthy-koeln> |
3 |
| - * @author Sergio Arbeo <[email protected]> |
4 |
| - * Adapted from https://github.com/DockYard/eslint-plugin-ember-suave/blob/master/lib/rules/lines-between-object-properties.js |
5 |
| - * |
| 2 | + * @author Barthy Bonhomme <[email protected]> (https://github.com/barthy-koeln) |
6 | 3 | * See LICENSE file in root directory for full license.
|
7 | 4 | */
|
8 | 5 | 'use strict'
|
|
11 | 8 | // Requirements
|
12 | 9 | // ------------------------------------------------------------------------------
|
13 | 10 |
|
14 |
| -const path = require('path') |
15 | 11 | const utils = require('../utils')
|
16 | 12 |
|
17 | 13 | // ------------------------------------------------------------------------------
|
@@ -52,126 +48,74 @@ module.exports = {
|
52 | 48 | const fixFunctions = {
|
53 | 49 | /**
|
54 | 50 | * Removes newlines between component options
|
| 51 | + * |
55 | 52 | * @param {RuleFixer} fixer
|
56 |
| - * @param {Token} currentLast |
57 |
| - * @param {Token} nextFirst |
| 53 | + * @param {number} endOfCurrent |
| 54 | + * @param {number} startOfNext |
58 | 55 | * @return {Fix}
|
59 | 56 | */
|
60 |
| - never(fixer, currentLast, nextFirst) { |
61 |
| - return fixer.replaceTextRange( |
62 |
| - [currentLast.range[1], nextFirst.range[0]], |
63 |
| - ',\n' |
64 |
| - ) |
| 57 | + never(fixer, endOfCurrent, startOfNext) { |
| 58 | + return fixer.replaceTextRange([endOfCurrent, startOfNext], '\n') |
65 | 59 | },
|
66 | 60 | /**
|
67 |
| - * Add newlines between component options |
| 61 | + * Add newlines between component options. |
| 62 | + * |
68 | 63 | * @param {RuleFixer} fixer
|
69 |
| - * @param {Token} currentLast |
| 64 | + * @param {number} endOfCurrent |
70 | 65 | * @return {Fix}
|
71 | 66 | */
|
72 |
| - always(fixer, currentLast /*, nextFirst*/) { |
73 |
| - const tokenAfterLastToken = sourceCode.getTokenAfter(currentLast) |
74 |
| - const tokenToLineBreakAfter = |
75 |
| - tokenAfterLastToken.value === ',' ? tokenAfterLastToken : currentLast |
76 |
| - |
77 |
| - return fixer.insertTextAfter(tokenToLineBreakAfter, '\n') |
78 |
| - } |
79 |
| - } |
80 |
| - |
81 |
| - /** |
82 |
| - * Checks if there is an empty line between two tokens |
83 |
| - * @param {Token} first The first token |
84 |
| - * @param {Token} second The second token |
85 |
| - * @returns {boolean} True if there is at least a line between the tokens |
86 |
| - */ |
87 |
| - function isPaddingBetweenTokens(first, second) { |
88 |
| - const comments = sourceCode.getCommentsBefore(second) |
89 |
| - const len = comments.length |
90 |
| - |
91 |
| - // If there is no comments |
92 |
| - if (len === 0) { |
93 |
| - const linesBetweenFstAndSnd = |
94 |
| - second.loc.start.line - first.loc.end.line - 1 |
95 |
| - |
96 |
| - return linesBetweenFstAndSnd >= 1 |
97 |
| - } |
98 |
| - |
99 |
| - // If there are comments |
100 |
| - let sumOfCommentLines = 0 // the numbers of lines of comments |
101 |
| - let prevCommentLineNum = -1 // line number of the end of the previous comment |
102 |
| - |
103 |
| - for (let i = 0; i < len; i++) { |
104 |
| - const commentLinesOfThisComment = |
105 |
| - comments[i].loc.end.line - comments[i].loc.start.line + 1 |
106 |
| - |
107 |
| - sumOfCommentLines += commentLinesOfThisComment |
108 |
| - |
109 |
| - /* |
110 |
| - * If this comment and the previous comment are in the same line, |
111 |
| - * the count of comment lines is duplicated. So decrement sumOfCommentLines. |
112 |
| - */ |
113 |
| - if (prevCommentLineNum === comments[i].loc.start.line) { |
114 |
| - sumOfCommentLines -= 1 |
115 |
| - } |
116 |
| - |
117 |
| - prevCommentLineNum = comments[i].loc.end.line |
118 |
| - } |
119 |
| - |
120 |
| - /* |
121 |
| - * If the first block and the first comment are in the same line, |
122 |
| - * the count of comment lines is duplicated. So decrement sumOfCommentLines. |
123 |
| - */ |
124 |
| - if (first.loc.end.line === comments[0].loc.start.line) { |
125 |
| - sumOfCommentLines -= 1 |
| 67 | + always(fixer, endOfCurrent /*, startOfNext*/) { |
| 68 | + return fixer.insertTextAfterRange([0, endOfCurrent], '\n') |
126 | 69 | }
|
127 |
| - |
128 |
| - /* |
129 |
| - * If the last comment and the second block are in the same line, |
130 |
| - * the count of comment lines is duplicated. So decrement sumOfCommentLines. |
131 |
| - */ |
132 |
| - if (comments[len - 1].loc.end.line === second.loc.start.line) { |
133 |
| - sumOfCommentLines -= 1 |
134 |
| - } |
135 |
| - |
136 |
| - const linesBetweenFstAndSnd = |
137 |
| - second.loc.start.line - first.loc.end.line - 1 |
138 |
| - |
139 |
| - return linesBetweenFstAndSnd - sumOfCommentLines >= 1 |
140 | 70 | }
|
141 | 71 |
|
142 | 72 | /**
|
143 |
| - * Report error based on configuration |
| 73 | + * Report error based on configuration. |
| 74 | + * |
144 | 75 | * @param {ASTNode} node Where to report errors
|
145 | 76 | * @param {boolean} isPadded True if the option is followed by an empty line
|
146 |
| - * @param {Token} currentLast End of checked token |
147 |
| - * @param {Token} nextFirst Start of next token |
| 77 | + * @param {number} endOfCurrent End of checked token |
| 78 | + * @param {number} startOfNext Start of next token |
148 | 79 | */
|
149 |
| - function reportError(node, isPadded, currentLast, nextFirst) { |
| 80 | + function reportError(node, isPadded, endOfCurrent, startOfNext) { |
150 | 81 | const key = isPadded ? 'never' : 'always'
|
151 | 82 | const fixFunction = fixFunctions[key]
|
152 | 83 |
|
153 | 84 | context.report({
|
154 | 85 | node,
|
155 | 86 | messageId: key,
|
156 |
| - fix: (fixer) => fixFunction(fixer, currentLast, nextFirst) |
| 87 | + fix: (fixer) => fixFunction(fixer, endOfCurrent, startOfNext) |
157 | 88 | })
|
158 | 89 | }
|
159 | 90 |
|
160 | 91 | /**
|
161 |
| - * Compares options and decides what to do |
162 |
| - * @param {ASTNode} option current option to check |
163 |
| - * @param {ASTNode} nextNode next node to check against |
| 92 | + * Compares options and decides what to do. |
| 93 | + * This takes into account comments before options, but not empty lines between multiple comments. |
| 94 | + * |
| 95 | + * @param {ASTNode} current current option to check |
| 96 | + * @param {ASTNode} next next node to check against |
164 | 97 | */
|
165 |
| - function checkOption(option, nextNode) { |
166 |
| - const currentLast = sourceCode.getLastToken(option) |
167 |
| - const nextFirst = sourceCode.getFirstToken(nextNode) |
168 |
| - const isPadded = isPaddingBetweenTokens(currentLast, nextFirst) |
| 98 | + function checkOption(current, next) { |
| 99 | + const endOfCurrent = |
| 100 | + sourceCode.getIndexFromLoc({ |
| 101 | + line: current.loc.end.line + 1, |
| 102 | + column: 0 |
| 103 | + }) - 1 /* start of next line, -1 for previous line */ |
| 104 | + |
| 105 | + const comments = sourceCode.getCommentsBefore(next) |
| 106 | + const nextNode = comments.length ? comments[0] : next |
| 107 | + |
| 108 | + const startOfNext = sourceCode.getIndexFromLoc({ |
| 109 | + line: nextNode.loc.start.line, |
| 110 | + column: 0 |
| 111 | + }) |
169 | 112 |
|
| 113 | + const isPadded = startOfNext !== endOfCurrent + 1 |
170 | 114 | if (shouldPad === isPadded) {
|
171 | 115 | return
|
172 | 116 | }
|
173 | 117 |
|
174 |
| - reportError(nextNode, isPadded, currentLast, nextFirst) |
| 118 | + reportError(next, isPadded, endOfCurrent, startOfNext) |
175 | 119 | }
|
176 | 120 |
|
177 | 121 | return {
|
|
0 commit comments