minor adjustment to readme
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-trailing-spaces.js
1 /**
2  * @fileoverview Disallow trailing spaces at the end of lines.
3  * @author Nodeca Team <https://github.com/nodeca>
4  */
5 "use strict";
6
7 //------------------------------------------------------------------------------
8 // Requirements
9 //------------------------------------------------------------------------------
10
11 const astUtils = require("./utils/ast-utils");
12
13 //------------------------------------------------------------------------------
14 // Rule Definition
15 //------------------------------------------------------------------------------
16
17 module.exports = {
18     meta: {
19         type: "layout",
20
21         docs: {
22             description: "disallow trailing whitespace at the end of lines",
23             category: "Stylistic Issues",
24             recommended: false,
25             url: "https://eslint.org/docs/rules/no-trailing-spaces"
26         },
27
28         fixable: "whitespace",
29
30         schema: [
31             {
32                 type: "object",
33                 properties: {
34                     skipBlankLines: {
35                         type: "boolean",
36                         default: false
37                     },
38                     ignoreComments: {
39                         type: "boolean",
40                         default: false
41                     }
42                 },
43                 additionalProperties: false
44             }
45         ]
46     },
47
48     create(context) {
49         const sourceCode = context.getSourceCode();
50
51         const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u3000]",
52             SKIP_BLANK = `^${BLANK_CLASS}*$`,
53             NONBLANK = `${BLANK_CLASS}+$`;
54
55         const options = context.options[0] || {},
56             skipBlankLines = options.skipBlankLines || false,
57             ignoreComments = options.ignoreComments || false;
58
59         /**
60          * Report the error message
61          * @param {ASTNode} node node to report
62          * @param {int[]} location range information
63          * @param {int[]} fixRange Range based on the whole program
64          * @returns {void}
65          */
66         function report(node, location, fixRange) {
67
68             /*
69              * Passing node is a bit dirty, because message data will contain big
70              * text in `source`. But... who cares :) ?
71              * One more kludge will not make worse the bloody wizardry of this
72              * plugin.
73              */
74             context.report({
75                 node,
76                 loc: location,
77                 message: "Trailing spaces not allowed.",
78                 fix(fixer) {
79                     return fixer.removeRange(fixRange);
80                 }
81             });
82         }
83
84         /**
85          * Given a list of comment nodes, return the line numbers for those comments.
86          * @param {Array} comments An array of comment nodes.
87          * @returns {number[]} An array of line numbers containing comments.
88          */
89         function getCommentLineNumbers(comments) {
90             const lines = new Set();
91
92             comments.forEach(comment => {
93                 const endLine = comment.type === "Block"
94                     ? comment.loc.end.line - 1
95                     : comment.loc.end.line;
96
97                 for (let i = comment.loc.start.line; i <= endLine; i++) {
98                     lines.add(i);
99                 }
100             });
101
102             return lines;
103         }
104
105         //--------------------------------------------------------------------------
106         // Public
107         //--------------------------------------------------------------------------
108
109         return {
110
111             Program: function checkTrailingSpaces(node) {
112
113                 /*
114                  * Let's hack. Since Espree does not return whitespace nodes,
115                  * fetch the source code and do matching via regexps.
116                  */
117
118                 const re = new RegExp(NONBLANK, "u"),
119                     skipMatch = new RegExp(SKIP_BLANK, "u"),
120                     lines = sourceCode.lines,
121                     linebreaks = sourceCode.getText().match(astUtils.createGlobalLinebreakMatcher()),
122                     comments = sourceCode.getAllComments(),
123                     commentLineNumbers = getCommentLineNumbers(comments);
124
125                 let totalLength = 0,
126                     fixRange = [];
127
128                 for (let i = 0, ii = lines.length; i < ii; i++) {
129                     const lineNumber = i + 1;
130
131                     /*
132                      * Always add linebreak length to line length to accommodate for line break (\n or \r\n)
133                      * Because during the fix time they also reserve one spot in the array.
134                      * Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF)
135                      */
136                     const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
137                     const lineLength = lines[i].length + linebreakLength;
138
139                     const matches = re.exec(lines[i]);
140
141                     if (matches) {
142                         const location = {
143                             start: {
144                                 line: lineNumber,
145                                 column: matches.index
146                             },
147                             end: {
148                                 line: lineNumber,
149                                 column: lineLength - linebreakLength
150                             }
151                         };
152
153                         const rangeStart = totalLength + location.start.column;
154                         const rangeEnd = totalLength + location.end.column;
155                         const containingNode = sourceCode.getNodeByRangeIndex(rangeStart);
156
157                         if (containingNode && containingNode.type === "TemplateElement" &&
158                           rangeStart > containingNode.parent.range[0] &&
159                           rangeEnd < containingNode.parent.range[1]) {
160                             totalLength += lineLength;
161                             continue;
162                         }
163
164                         /*
165                          * If the line has only whitespace, and skipBlankLines
166                          * is true, don't report it
167                          */
168                         if (skipBlankLines && skipMatch.test(lines[i])) {
169                             totalLength += lineLength;
170                             continue;
171                         }
172
173                         fixRange = [rangeStart, rangeEnd];
174
175                         if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
176                             report(node, location, fixRange);
177                         }
178                     }
179
180                     totalLength += lineLength;
181                 }
182             }
183
184         };
185     }
186 };