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