]> git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/no-multi-spaces.js
import 8.3.0 source
[pve-eslint.git] / eslint / lib / rules / no-multi-spaces.js
1 /**
2 * @fileoverview Disallow use of multiple spaces.
3 * @author Nicholas C. Zakas
4 */
5
6 "use strict";
7
8 const astUtils = require("./utils/ast-utils");
9
10 //------------------------------------------------------------------------------
11 // Rule Definition
12 //------------------------------------------------------------------------------
13
14 module.exports = {
15 meta: {
16 type: "layout",
17
18 docs: {
19 description: "disallow multiple spaces",
20 recommended: false,
21 url: "https://eslint.org/docs/rules/no-multi-spaces"
22 },
23
24 fixable: "whitespace",
25
26 schema: [
27 {
28 type: "object",
29 properties: {
30 exceptions: {
31 type: "object",
32 patternProperties: {
33 "^([A-Z][a-z]*)+$": {
34 type: "boolean"
35 }
36 },
37 additionalProperties: false
38 },
39 ignoreEOLComments: {
40 type: "boolean",
41 default: false
42 }
43 },
44 additionalProperties: false
45 }
46 ],
47
48 messages: {
49 multipleSpaces: "Multiple spaces found before '{{displayValue}}'."
50 }
51 },
52
53 create(context) {
54 const sourceCode = context.getSourceCode();
55 const options = context.options[0] || {};
56 const ignoreEOLComments = options.ignoreEOLComments;
57 const exceptions = Object.assign({ Property: true }, options.exceptions);
58 const hasExceptions = Object.keys(exceptions).filter(key => exceptions[key]).length > 0;
59
60 /**
61 * Formats value of given comment token for error message by truncating its length.
62 * @param {Token} token comment token
63 * @returns {string} formatted value
64 * @private
65 */
66 function formatReportedCommentValue(token) {
67 const valueLines = token.value.split("\n");
68 const value = valueLines[0];
69 const formattedValue = `${value.slice(0, 12)}...`;
70
71 return valueLines.length === 1 && value.length <= 12 ? value : formattedValue;
72 }
73
74 //--------------------------------------------------------------------------
75 // Public
76 //--------------------------------------------------------------------------
77
78 return {
79 Program() {
80 sourceCode.tokensAndComments.forEach((leftToken, leftIndex, tokensAndComments) => {
81 if (leftIndex === tokensAndComments.length - 1) {
82 return;
83 }
84 const rightToken = tokensAndComments[leftIndex + 1];
85
86 // Ignore tokens that don't have 2 spaces between them or are on different lines
87 if (
88 !sourceCode.text.slice(leftToken.range[1], rightToken.range[0]).includes(" ") ||
89 leftToken.loc.end.line < rightToken.loc.start.line
90 ) {
91 return;
92 }
93
94 // Ignore comments that are the last token on their line if `ignoreEOLComments` is active.
95 if (
96 ignoreEOLComments &&
97 astUtils.isCommentToken(rightToken) &&
98 (
99 leftIndex === tokensAndComments.length - 2 ||
100 rightToken.loc.end.line < tokensAndComments[leftIndex + 2].loc.start.line
101 )
102 ) {
103 return;
104 }
105
106 // Ignore tokens that are in a node in the "exceptions" object
107 if (hasExceptions) {
108 const parentNode = sourceCode.getNodeByRangeIndex(rightToken.range[0] - 1);
109
110 if (parentNode && exceptions[parentNode.type]) {
111 return;
112 }
113 }
114
115 let displayValue;
116
117 if (rightToken.type === "Block") {
118 displayValue = `/*${formatReportedCommentValue(rightToken)}*/`;
119 } else if (rightToken.type === "Line") {
120 displayValue = `//${formatReportedCommentValue(rightToken)}`;
121 } else {
122 displayValue = rightToken.value;
123 }
124
125 context.report({
126 node: rightToken,
127 loc: { start: leftToken.loc.end, end: rightToken.loc.start },
128 messageId: "multipleSpaces",
129 data: { displayValue },
130 fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
131 });
132 });
133 }
134 };
135
136 }
137 };