source: imaps-frontend/node_modules/eslint/lib/rules/no-irregular-whitespace.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/**
2 * @fileoverview Rule to disallow whitespace that is not a tab or space, whitespace inside strings and comments are allowed
3 * @author Jonathan Kingston
4 * @author Christophe Porteneuve
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Requirements
11//------------------------------------------------------------------------------
12
13const astUtils = require("./utils/ast-utils");
14
15//------------------------------------------------------------------------------
16// Constants
17//------------------------------------------------------------------------------
18
19const ALL_IRREGULARS = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/u;
20const IRREGULAR_WHITESPACE = /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mgu;
21const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mgu;
22const LINE_BREAK = astUtils.createGlobalLinebreakMatcher();
23
24//------------------------------------------------------------------------------
25// Rule Definition
26//------------------------------------------------------------------------------
27
28/** @type {import('../shared/types').Rule} */
29module.exports = {
30 meta: {
31 type: "problem",
32
33 docs: {
34 description: "Disallow irregular whitespace",
35 recommended: true,
36 url: "https://eslint.org/docs/latest/rules/no-irregular-whitespace"
37 },
38
39 schema: [
40 {
41 type: "object",
42 properties: {
43 skipComments: {
44 type: "boolean",
45 default: false
46 },
47 skipStrings: {
48 type: "boolean",
49 default: true
50 },
51 skipTemplates: {
52 type: "boolean",
53 default: false
54 },
55 skipRegExps: {
56 type: "boolean",
57 default: false
58 },
59 skipJSXText: {
60 type: "boolean",
61 default: false
62 }
63 },
64 additionalProperties: false
65 }
66 ],
67
68 messages: {
69 noIrregularWhitespace: "Irregular whitespace not allowed."
70 }
71 },
72
73 create(context) {
74
75 // Module store of errors that we have found
76 let errors = [];
77
78 // Lookup the `skipComments` option, which defaults to `false`.
79 const options = context.options[0] || {};
80 const skipComments = !!options.skipComments;
81 const skipStrings = options.skipStrings !== false;
82 const skipRegExps = !!options.skipRegExps;
83 const skipTemplates = !!options.skipTemplates;
84 const skipJSXText = !!options.skipJSXText;
85
86 const sourceCode = context.sourceCode;
87 const commentNodes = sourceCode.getAllComments();
88
89 /**
90 * Removes errors that occur inside the given node
91 * @param {ASTNode} node to check for matching errors.
92 * @returns {void}
93 * @private
94 */
95 function removeWhitespaceError(node) {
96 const locStart = node.loc.start;
97 const locEnd = node.loc.end;
98
99 errors = errors.filter(({ loc: { start: errorLocStart } }) => (
100 errorLocStart.line < locStart.line ||
101 errorLocStart.line === locStart.line && errorLocStart.column < locStart.column ||
102 errorLocStart.line === locEnd.line && errorLocStart.column >= locEnd.column ||
103 errorLocStart.line > locEnd.line
104 ));
105 }
106
107 /**
108 * Checks literal nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors
109 * @param {ASTNode} node to check for matching errors.
110 * @returns {void}
111 * @private
112 */
113 function removeInvalidNodeErrorsInLiteral(node) {
114 const shouldCheckStrings = skipStrings && (typeof node.value === "string");
115 const shouldCheckRegExps = skipRegExps && Boolean(node.regex);
116
117 if (shouldCheckStrings || shouldCheckRegExps) {
118
119 // If we have irregular characters remove them from the errors list
120 if (ALL_IRREGULARS.test(node.raw)) {
121 removeWhitespaceError(node);
122 }
123 }
124 }
125
126 /**
127 * Checks template string literal nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors
128 * @param {ASTNode} node to check for matching errors.
129 * @returns {void}
130 * @private
131 */
132 function removeInvalidNodeErrorsInTemplateLiteral(node) {
133 if (typeof node.value.raw === "string") {
134 if (ALL_IRREGULARS.test(node.value.raw)) {
135 removeWhitespaceError(node);
136 }
137 }
138 }
139
140 /**
141 * Checks comment nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors
142 * @param {ASTNode} node to check for matching errors.
143 * @returns {void}
144 * @private
145 */
146 function removeInvalidNodeErrorsInComment(node) {
147 if (ALL_IRREGULARS.test(node.value)) {
148 removeWhitespaceError(node);
149 }
150 }
151
152 /**
153 * Checks JSX nodes for errors that we are choosing to ignore and calls the relevant methods to remove the errors
154 * @param {ASTNode} node to check for matching errors.
155 * @returns {void}
156 * @private
157 */
158 function removeInvalidNodeErrorsInJSXText(node) {
159 if (ALL_IRREGULARS.test(node.raw)) {
160 removeWhitespaceError(node);
161 }
162 }
163
164 /**
165 * Checks the program source for irregular whitespace
166 * @param {ASTNode} node The program node
167 * @returns {void}
168 * @private
169 */
170 function checkForIrregularWhitespace(node) {
171 const sourceLines = sourceCode.lines;
172
173 sourceLines.forEach((sourceLine, lineIndex) => {
174 const lineNumber = lineIndex + 1;
175 let match;
176
177 while ((match = IRREGULAR_WHITESPACE.exec(sourceLine)) !== null) {
178 errors.push({
179 node,
180 messageId: "noIrregularWhitespace",
181 loc: {
182 start: {
183 line: lineNumber,
184 column: match.index
185 },
186 end: {
187 line: lineNumber,
188 column: match.index + match[0].length
189 }
190 }
191 });
192 }
193 });
194 }
195
196 /**
197 * Checks the program source for irregular line terminators
198 * @param {ASTNode} node The program node
199 * @returns {void}
200 * @private
201 */
202 function checkForIrregularLineTerminators(node) {
203 const source = sourceCode.getText(),
204 sourceLines = sourceCode.lines,
205 linebreaks = source.match(LINE_BREAK);
206 let lastLineIndex = -1,
207 match;
208
209 while ((match = IRREGULAR_LINE_TERMINATORS.exec(source)) !== null) {
210 const lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0;
211
212 errors.push({
213 node,
214 messageId: "noIrregularWhitespace",
215 loc: {
216 start: {
217 line: lineIndex + 1,
218 column: sourceLines[lineIndex].length
219 },
220 end: {
221 line: lineIndex + 2,
222 column: 0
223 }
224 }
225 });
226
227 lastLineIndex = lineIndex;
228 }
229 }
230
231 /**
232 * A no-op function to act as placeholder for comment accumulation when the `skipComments` option is `false`.
233 * @returns {void}
234 * @private
235 */
236 function noop() {}
237
238 const nodes = {};
239
240 if (ALL_IRREGULARS.test(sourceCode.getText())) {
241 nodes.Program = function(node) {
242
243 /*
244 * As we can easily fire warnings for all white space issues with
245 * all the source its simpler to fire them here.
246 * This means we can check all the application code without having
247 * to worry about issues caused in the parser tokens.
248 * When writing this code also evaluating per node was missing out
249 * connecting tokens in some cases.
250 * We can later filter the errors when they are found to be not an
251 * issue in nodes we don't care about.
252 */
253 checkForIrregularWhitespace(node);
254 checkForIrregularLineTerminators(node);
255 };
256
257 nodes.Literal = removeInvalidNodeErrorsInLiteral;
258 nodes.TemplateElement = skipTemplates ? removeInvalidNodeErrorsInTemplateLiteral : noop;
259 nodes.JSXText = skipJSXText ? removeInvalidNodeErrorsInJSXText : noop;
260 nodes["Program:exit"] = function() {
261 if (skipComments) {
262
263 // First strip errors occurring in comment nodes.
264 commentNodes.forEach(removeInvalidNodeErrorsInComment);
265 }
266
267 // If we have any errors remaining report on them
268 errors.forEach(error => context.report(error));
269 };
270 } else {
271 nodes.Program = noop;
272 }
273
274 return nodes;
275 }
276};
Note: See TracBrowser for help on using the repository browser.