.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / template-curly-spacing.js
1 /**
2  * @fileoverview Rule to enforce spacing around embedded expressions of template strings
3  * @author Toru Nagashima
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Rule Definition
16 //------------------------------------------------------------------------------
17
18 module.exports = {
19     meta: {
20         type: "layout",
21
22         docs: {
23             description: "require or disallow spacing around embedded expressions of template strings",
24             category: "ECMAScript 6",
25             recommended: false,
26             url: "https://eslint.org/docs/rules/template-curly-spacing"
27         },
28
29         fixable: "whitespace",
30
31         schema: [
32             { enum: ["always", "never"] }
33         ],
34         messages: {
35             expectedBefore: "Expected space(s) before '}'.",
36             expectedAfter: "Expected space(s) after '${'.",
37             unexpectedBefore: "Unexpected space(s) before '}'.",
38             unexpectedAfter: "Unexpected space(s) after '${'."
39         }
40     },
41
42     create(context) {
43         const sourceCode = context.getSourceCode();
44         const always = context.options[0] === "always";
45
46         /**
47          * Checks spacing before `}` of a given token.
48          * @param {Token} token A token to check. This is a Template token.
49          * @returns {void}
50          */
51         function checkSpacingBefore(token) {
52             if (!token.value.startsWith("}")) {
53                 return; // starts with a backtick, this is the first template element in the template literal
54             }
55
56             const prevToken = sourceCode.getTokenBefore(token, { includeComments: true }),
57                 hasSpace = sourceCode.isSpaceBetween(prevToken, token);
58
59             if (!astUtils.isTokenOnSameLine(prevToken, token)) {
60                 return;
61             }
62
63             if (always && !hasSpace) {
64                 context.report({
65                     loc: {
66                         start: token.loc.start,
67                         end: {
68                             line: token.loc.start.line,
69                             column: token.loc.start.column + 1
70                         }
71                     },
72                     messageId: "expectedBefore",
73                     fix: fixer => fixer.insertTextBefore(token, " ")
74                 });
75             }
76
77             if (!always && hasSpace) {
78                 context.report({
79                     loc: {
80                         start: prevToken.loc.end,
81                         end: token.loc.start
82                     },
83                     messageId: "unexpectedBefore",
84                     fix: fixer => fixer.removeRange([prevToken.range[1], token.range[0]])
85                 });
86             }
87         }
88
89         /**
90          * Checks spacing after `${` of a given token.
91          * @param {Token} token A token to check. This is a Template token.
92          * @returns {void}
93          */
94         function checkSpacingAfter(token) {
95             if (!token.value.endsWith("${")) {
96                 return; // ends with a backtick, this is the last template element in the template literal
97             }
98
99             const nextToken = sourceCode.getTokenAfter(token, { includeComments: true }),
100                 hasSpace = sourceCode.isSpaceBetween(token, nextToken);
101
102             if (!astUtils.isTokenOnSameLine(token, nextToken)) {
103                 return;
104             }
105
106             if (always && !hasSpace) {
107                 context.report({
108                     loc: {
109                         start: {
110                             line: token.loc.end.line,
111                             column: token.loc.end.column - 2
112                         },
113                         end: token.loc.end
114                     },
115                     messageId: "expectedAfter",
116                     fix: fixer => fixer.insertTextAfter(token, " ")
117                 });
118             }
119
120             if (!always && hasSpace) {
121                 context.report({
122                     loc: {
123                         start: token.loc.end,
124                         end: nextToken.loc.start
125                     },
126                     messageId: "unexpectedAfter",
127                     fix: fixer => fixer.removeRange([token.range[1], nextToken.range[0]])
128                 });
129             }
130         }
131
132         return {
133             TemplateElement(node) {
134                 const token = sourceCode.getFirstToken(node);
135
136                 checkSpacingBefore(token);
137                 checkSpacingAfter(token);
138             }
139         };
140     }
141 };