eslint-plugin-toml 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/meta.d.ts +1 -1
- package/lib/meta.js +1 -1
- package/lib/rules/array-bracket-newline.js +159 -16
- package/lib/rules/array-bracket-spacing.js +163 -15
- package/lib/rules/array-element-newline.js +186 -14
- package/lib/rules/comma-style.js +145 -16
- package/lib/rules/inline-table-curly-spacing.js +162 -16
- package/lib/types.d.ts +2 -2
- package/lib/utils/ast-utils.d.ts +7 -0
- package/lib/utils/ast-utils.js +27 -1
- package/lib/utils/index.d.ts +1 -16
- package/lib/utils/index.js +1 -95
- package/package.json +6 -6
package/lib/meta.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const name: "eslint-plugin-toml";
|
|
2
|
-
export declare const version: "0.
|
|
2
|
+
export declare const version: "0.8.0";
|
package/lib/meta.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
|
-
const
|
|
4
|
+
const compat_1 = require("../utils/compat");
|
|
5
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
5
6
|
exports.default = (0, utils_1.createRule)("array-bracket-newline", {
|
|
6
7
|
meta: {
|
|
7
8
|
docs: {
|
|
@@ -9,22 +10,164 @@ exports.default = (0, utils_1.createRule)("array-bracket-newline", {
|
|
|
9
10
|
categories: ["standard"],
|
|
10
11
|
extensionRule: "array-bracket-newline",
|
|
11
12
|
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
schema:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
type: "layout",
|
|
14
|
+
fixable: "whitespace",
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
oneOf: [
|
|
18
|
+
{
|
|
19
|
+
type: "string",
|
|
20
|
+
enum: ["always", "never", "consistent"],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
multiline: {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
},
|
|
28
|
+
minItems: {
|
|
29
|
+
type: ["integer", "null"],
|
|
30
|
+
minimum: 0,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
additionalProperties: false,
|
|
25
34
|
},
|
|
26
|
-
|
|
35
|
+
],
|
|
27
36
|
},
|
|
28
|
-
|
|
37
|
+
],
|
|
38
|
+
messages: {
|
|
39
|
+
unexpectedOpeningLinebreak: "There should be no linebreak after '['.",
|
|
40
|
+
unexpectedClosingLinebreak: "There should be no linebreak before ']'.",
|
|
41
|
+
missingOpeningLinebreak: "A linebreak is required after '['.",
|
|
42
|
+
missingClosingLinebreak: "A linebreak is required before ']'.",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
create(context) {
|
|
46
|
+
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
47
|
+
if (!sourceCode.parserServices.isTOML) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
function normalizeOptionValue(option) {
|
|
51
|
+
let consistent = false;
|
|
52
|
+
let multiline = false;
|
|
53
|
+
let minItems = 0;
|
|
54
|
+
if (option) {
|
|
55
|
+
if (option === "consistent") {
|
|
56
|
+
consistent = true;
|
|
57
|
+
minItems = Number.POSITIVE_INFINITY;
|
|
58
|
+
}
|
|
59
|
+
else if (option === "always" ||
|
|
60
|
+
(typeof option !== "string" && option.minItems === 0)) {
|
|
61
|
+
minItems = 0;
|
|
62
|
+
}
|
|
63
|
+
else if (option === "never") {
|
|
64
|
+
minItems = Number.POSITIVE_INFINITY;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
multiline = Boolean(option.multiline);
|
|
68
|
+
minItems = option.minItems || Number.POSITIVE_INFINITY;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
consistent = false;
|
|
73
|
+
multiline = true;
|
|
74
|
+
minItems = Number.POSITIVE_INFINITY;
|
|
75
|
+
}
|
|
76
|
+
return { consistent, multiline, minItems };
|
|
77
|
+
}
|
|
78
|
+
function normalizeOptions(options) {
|
|
79
|
+
const value = normalizeOptionValue(options);
|
|
80
|
+
return { TOMLArray: value };
|
|
81
|
+
}
|
|
82
|
+
function reportNoBeginningLinebreak(node, token) {
|
|
83
|
+
context.report({
|
|
84
|
+
node,
|
|
85
|
+
loc: token.loc,
|
|
86
|
+
messageId: "unexpectedOpeningLinebreak",
|
|
87
|
+
fix(fixer) {
|
|
88
|
+
const nextToken = sourceCode.getTokenAfter(token, {
|
|
89
|
+
includeComments: true,
|
|
90
|
+
});
|
|
91
|
+
if (!nextToken || (0, ast_utils_1.isCommentToken)(nextToken))
|
|
92
|
+
return null;
|
|
93
|
+
return fixer.removeRange([token.range[1], nextToken.range[0]]);
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function reportNoEndingLinebreak(node, token) {
|
|
98
|
+
context.report({
|
|
99
|
+
node,
|
|
100
|
+
loc: token.loc,
|
|
101
|
+
messageId: "unexpectedClosingLinebreak",
|
|
102
|
+
fix(fixer) {
|
|
103
|
+
const previousToken = sourceCode.getTokenBefore(token, {
|
|
104
|
+
includeComments: true,
|
|
105
|
+
});
|
|
106
|
+
if (!previousToken || (0, ast_utils_1.isCommentToken)(previousToken))
|
|
107
|
+
return null;
|
|
108
|
+
return fixer.removeRange([previousToken.range[1], token.range[0]]);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function reportRequiredBeginningLinebreak(node, token) {
|
|
113
|
+
context.report({
|
|
114
|
+
node,
|
|
115
|
+
loc: token.loc,
|
|
116
|
+
messageId: "missingOpeningLinebreak",
|
|
117
|
+
fix(fixer) {
|
|
118
|
+
return fixer.insertTextAfter(token, "\n");
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function reportRequiredEndingLinebreak(node, token) {
|
|
123
|
+
context.report({
|
|
124
|
+
node,
|
|
125
|
+
loc: token.loc,
|
|
126
|
+
messageId: "missingClosingLinebreak",
|
|
127
|
+
fix(fixer) {
|
|
128
|
+
return fixer.insertTextBefore(token, "\n");
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function check(node) {
|
|
133
|
+
const elements = node.elements;
|
|
134
|
+
const normalizedOptions = normalizeOptions(context.options[0]);
|
|
135
|
+
const options = normalizedOptions[node.type];
|
|
136
|
+
const openBracket = sourceCode.getFirstToken(node);
|
|
137
|
+
const closeBracket = sourceCode.getLastToken(node);
|
|
138
|
+
const firstIncComment = sourceCode.getTokenAfter(openBracket, {
|
|
139
|
+
includeComments: true,
|
|
140
|
+
});
|
|
141
|
+
const lastIncComment = sourceCode.getTokenBefore(closeBracket, {
|
|
142
|
+
includeComments: true,
|
|
143
|
+
});
|
|
144
|
+
const first = sourceCode.getTokenAfter(openBracket);
|
|
145
|
+
const last = sourceCode.getTokenBefore(closeBracket);
|
|
146
|
+
const needsLinebreaks = elements.length >= options.minItems ||
|
|
147
|
+
(options.multiline &&
|
|
148
|
+
elements.length > 0 &&
|
|
149
|
+
firstIncComment.loc.start.line !== lastIncComment.loc.end.line) ||
|
|
150
|
+
(elements.length === 0 &&
|
|
151
|
+
firstIncComment.type === "Block" &&
|
|
152
|
+
firstIncComment.loc.start.line !== lastIncComment.loc.end.line &&
|
|
153
|
+
firstIncComment === lastIncComment) ||
|
|
154
|
+
(options.consistent &&
|
|
155
|
+
openBracket.loc.end.line !== first.loc.start.line);
|
|
156
|
+
if (needsLinebreaks) {
|
|
157
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(openBracket, first))
|
|
158
|
+
reportRequiredBeginningLinebreak(node, openBracket);
|
|
159
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(last, closeBracket))
|
|
160
|
+
reportRequiredEndingLinebreak(node, closeBracket);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
if (!(0, ast_utils_1.isTokenOnSameLine)(openBracket, first))
|
|
164
|
+
reportNoBeginningLinebreak(node, openBracket);
|
|
165
|
+
if (!(0, ast_utils_1.isTokenOnSameLine)(last, closeBracket))
|
|
166
|
+
reportNoEndingLinebreak(node, closeBracket);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
TOMLArray: check,
|
|
171
|
+
};
|
|
29
172
|
},
|
|
30
173
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
|
-
const
|
|
4
|
+
const compat_1 = require("../utils/compat");
|
|
5
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
5
6
|
exports.default = (0, utils_1.createRule)("array-bracket-spacing", {
|
|
6
7
|
meta: {
|
|
7
8
|
docs: {
|
|
@@ -9,22 +10,169 @@ exports.default = (0, utils_1.createRule)("array-bracket-spacing", {
|
|
|
9
10
|
categories: ["standard"],
|
|
10
11
|
extensionRule: "array-bracket-spacing",
|
|
11
12
|
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
schema:
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
type: "layout",
|
|
14
|
+
fixable: "whitespace",
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: "string",
|
|
18
|
+
enum: ["always", "never"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
singleValue: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
},
|
|
26
|
+
objectsInArrays: {
|
|
27
|
+
type: "boolean",
|
|
28
|
+
},
|
|
29
|
+
arraysInArrays: {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
messages: {
|
|
37
|
+
unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.",
|
|
38
|
+
unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.",
|
|
39
|
+
missingSpaceAfter: "A space is required after '{{tokenValue}}'.",
|
|
40
|
+
missingSpaceBefore: "A space is required before '{{tokenValue}}'.",
|
|
41
|
+
},
|
|
17
42
|
},
|
|
18
43
|
create(context) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
44
|
+
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
45
|
+
if (!sourceCode.parserServices.isTOML) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
const spaced = (context.options[0] || "always") === "always";
|
|
49
|
+
function isOptionSet(option) {
|
|
50
|
+
return context.options[1]
|
|
51
|
+
? context.options[1][option] === !spaced
|
|
52
|
+
: false;
|
|
53
|
+
}
|
|
54
|
+
const options = {
|
|
55
|
+
spaced,
|
|
56
|
+
singleElementException: isOptionSet("singleValue"),
|
|
57
|
+
objectsInArraysException: isOptionSet("objectsInArrays"),
|
|
58
|
+
arraysInArraysException: isOptionSet("arraysInArrays"),
|
|
59
|
+
isOpeningBracketMustBeSpaced(node) {
|
|
60
|
+
if (options.singleElementException && node.elements.length === 1) {
|
|
61
|
+
return !options.spaced;
|
|
62
|
+
}
|
|
63
|
+
const firstElement = node.elements[0];
|
|
64
|
+
return firstElement &&
|
|
65
|
+
((options.objectsInArraysException && isObjectType(firstElement)) ||
|
|
66
|
+
(options.arraysInArraysException && isArrayType(firstElement)))
|
|
67
|
+
? !options.spaced
|
|
68
|
+
: options.spaced;
|
|
69
|
+
},
|
|
70
|
+
isClosingBracketMustBeSpaced(node) {
|
|
71
|
+
if (options.singleElementException && node.elements.length === 1) {
|
|
72
|
+
return !options.spaced;
|
|
73
|
+
}
|
|
74
|
+
const lastElement = node.elements[node.elements.length - 1];
|
|
75
|
+
return lastElement &&
|
|
76
|
+
((options.objectsInArraysException && isObjectType(lastElement)) ||
|
|
77
|
+
(options.arraysInArraysException && isArrayType(lastElement)))
|
|
78
|
+
? !options.spaced
|
|
79
|
+
: options.spaced;
|
|
27
80
|
},
|
|
28
|
-
}
|
|
81
|
+
};
|
|
82
|
+
function reportNoBeginningSpace(node, token) {
|
|
83
|
+
const nextToken = sourceCode.getTokenAfter(token);
|
|
84
|
+
context.report({
|
|
85
|
+
node,
|
|
86
|
+
loc: { start: token.loc.end, end: nextToken.loc.start },
|
|
87
|
+
messageId: "unexpectedSpaceAfter",
|
|
88
|
+
data: {
|
|
89
|
+
tokenValue: token.value,
|
|
90
|
+
},
|
|
91
|
+
fix(fixer) {
|
|
92
|
+
return fixer.removeRange([token.range[1], nextToken.range[0]]);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function reportNoEndingSpace(node, token) {
|
|
97
|
+
const previousToken = sourceCode.getTokenBefore(token);
|
|
98
|
+
context.report({
|
|
99
|
+
node,
|
|
100
|
+
loc: { start: previousToken.loc.end, end: token.loc.start },
|
|
101
|
+
messageId: "unexpectedSpaceBefore",
|
|
102
|
+
data: {
|
|
103
|
+
tokenValue: token.value,
|
|
104
|
+
},
|
|
105
|
+
fix(fixer) {
|
|
106
|
+
return fixer.removeRange([previousToken.range[1], token.range[0]]);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function reportRequiredBeginningSpace(node, token) {
|
|
111
|
+
context.report({
|
|
112
|
+
node,
|
|
113
|
+
loc: token.loc,
|
|
114
|
+
messageId: "missingSpaceAfter",
|
|
115
|
+
data: {
|
|
116
|
+
tokenValue: token.value,
|
|
117
|
+
},
|
|
118
|
+
fix(fixer) {
|
|
119
|
+
return fixer.insertTextAfter(token, " ");
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function reportRequiredEndingSpace(node, token) {
|
|
124
|
+
context.report({
|
|
125
|
+
node,
|
|
126
|
+
loc: token.loc,
|
|
127
|
+
messageId: "missingSpaceBefore",
|
|
128
|
+
data: {
|
|
129
|
+
tokenValue: token.value,
|
|
130
|
+
},
|
|
131
|
+
fix(fixer) {
|
|
132
|
+
return fixer.insertTextBefore(token, " ");
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function isObjectType(node) {
|
|
137
|
+
return node && node.type === "TOMLInlineTable";
|
|
138
|
+
}
|
|
139
|
+
function isArrayType(node) {
|
|
140
|
+
return node && node.type === "TOMLArray";
|
|
141
|
+
}
|
|
142
|
+
function validateArraySpacing(node) {
|
|
143
|
+
if (options.spaced && node.elements.length === 0)
|
|
144
|
+
return;
|
|
145
|
+
const first = sourceCode.getFirstToken(node);
|
|
146
|
+
const last = sourceCode.getLastToken(node);
|
|
147
|
+
const second = sourceCode.getTokenAfter(first, {
|
|
148
|
+
includeComments: true,
|
|
149
|
+
});
|
|
150
|
+
const penultimate = sourceCode.getTokenBefore(last, {
|
|
151
|
+
includeComments: true,
|
|
152
|
+
});
|
|
153
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(first, second)) {
|
|
154
|
+
if (options.isOpeningBracketMustBeSpaced(node)) {
|
|
155
|
+
if (!sourceCode.isSpaceBetweenTokens(first, second))
|
|
156
|
+
reportRequiredBeginningSpace(node, first);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
if (sourceCode.isSpaceBetweenTokens(first, second))
|
|
160
|
+
reportNoBeginningSpace(node, first);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (first !== penultimate && (0, ast_utils_1.isTokenOnSameLine)(penultimate, last)) {
|
|
164
|
+
if (options.isClosingBracketMustBeSpaced(node)) {
|
|
165
|
+
if (!sourceCode.isSpaceBetweenTokens(penultimate, last))
|
|
166
|
+
reportRequiredEndingSpace(node, last);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
if (sourceCode.isSpaceBetweenTokens(penultimate, last))
|
|
170
|
+
reportNoEndingSpace(node, last);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
TOMLArray: validateArraySpacing,
|
|
176
|
+
};
|
|
29
177
|
},
|
|
30
178
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
|
-
const
|
|
4
|
+
const compat_1 = require("../utils/compat");
|
|
5
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
5
6
|
exports.default = (0, utils_1.createRule)("array-element-newline", {
|
|
6
7
|
meta: {
|
|
7
8
|
docs: {
|
|
@@ -9,22 +10,193 @@ exports.default = (0, utils_1.createRule)("array-element-newline", {
|
|
|
9
10
|
categories: ["standard"],
|
|
10
11
|
extensionRule: "array-element-newline",
|
|
11
12
|
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
schema:
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
type: "layout",
|
|
14
|
+
fixable: "whitespace",
|
|
15
|
+
schema: {
|
|
16
|
+
definitions: {
|
|
17
|
+
basicConfig: {
|
|
18
|
+
oneOf: [
|
|
19
|
+
{
|
|
20
|
+
type: "string",
|
|
21
|
+
enum: ["always", "never", "consistent"],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: {
|
|
26
|
+
multiline: {
|
|
27
|
+
type: "boolean",
|
|
28
|
+
},
|
|
29
|
+
minItems: {
|
|
30
|
+
type: ["integer", "null"],
|
|
31
|
+
minimum: 0,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
type: "array",
|
|
40
|
+
items: [
|
|
41
|
+
{
|
|
42
|
+
oneOf: [
|
|
43
|
+
{
|
|
44
|
+
$ref: "#/definitions/basicConfig",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
ArrayExpression: {
|
|
50
|
+
$ref: "#/definitions/basicConfig",
|
|
51
|
+
},
|
|
52
|
+
ArrayPattern: {
|
|
53
|
+
$ref: "#/definitions/basicConfig",
|
|
54
|
+
},
|
|
55
|
+
TOMLArray: {
|
|
56
|
+
$ref: "#/definitions/basicConfig",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
additionalProperties: false,
|
|
60
|
+
minProperties: 1,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
messages: {
|
|
67
|
+
unexpectedLineBreak: "There should be no linebreak here.",
|
|
68
|
+
missingLineBreak: "There should be a linebreak after this element.",
|
|
69
|
+
},
|
|
17
70
|
},
|
|
18
71
|
create(context) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
72
|
+
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
73
|
+
if (!sourceCode.parserServices.isTOML) {
|
|
74
|
+
return {};
|
|
75
|
+
}
|
|
76
|
+
function normalizeOptionValue(providedOption) {
|
|
77
|
+
let consistent = false;
|
|
78
|
+
let multiline = false;
|
|
79
|
+
let minItems;
|
|
80
|
+
const option = providedOption || "always";
|
|
81
|
+
if (!option ||
|
|
82
|
+
option === "always" ||
|
|
83
|
+
(typeof option === "object" && option.minItems === 0)) {
|
|
84
|
+
minItems = 0;
|
|
85
|
+
}
|
|
86
|
+
else if (option === "never") {
|
|
87
|
+
minItems = Number.POSITIVE_INFINITY;
|
|
88
|
+
}
|
|
89
|
+
else if (option === "consistent") {
|
|
90
|
+
consistent = true;
|
|
91
|
+
minItems = Number.POSITIVE_INFINITY;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
multiline = Boolean(option.multiline);
|
|
95
|
+
minItems = option.minItems || Number.POSITIVE_INFINITY;
|
|
96
|
+
}
|
|
97
|
+
return { consistent, multiline, minItems };
|
|
98
|
+
}
|
|
99
|
+
function normalizeOptions(options) {
|
|
100
|
+
if (options && (options.ArrayExpression || options.TOMLArray)) {
|
|
101
|
+
let expressionOptions;
|
|
102
|
+
if (options.ArrayExpression)
|
|
103
|
+
expressionOptions = normalizeOptionValue(options.ArrayExpression);
|
|
104
|
+
if (options.TOMLArray)
|
|
105
|
+
expressionOptions = normalizeOptionValue(options.TOMLArray);
|
|
22
106
|
return {
|
|
23
|
-
TOMLArray
|
|
24
|
-
listener.ArrayExpression((0, utils_1.convertESNode)(node));
|
|
25
|
-
},
|
|
107
|
+
TOMLArray: expressionOptions,
|
|
26
108
|
};
|
|
27
|
-
}
|
|
28
|
-
|
|
109
|
+
}
|
|
110
|
+
const value = normalizeOptionValue(options);
|
|
111
|
+
return { TOMLArray: value };
|
|
112
|
+
}
|
|
113
|
+
function reportNoLineBreak(token) {
|
|
114
|
+
const tokenBefore = sourceCode.getTokenBefore(token, {
|
|
115
|
+
includeComments: true,
|
|
116
|
+
});
|
|
117
|
+
context.report({
|
|
118
|
+
loc: {
|
|
119
|
+
start: tokenBefore.loc.end,
|
|
120
|
+
end: token.loc.start,
|
|
121
|
+
},
|
|
122
|
+
messageId: "unexpectedLineBreak",
|
|
123
|
+
fix(fixer) {
|
|
124
|
+
if ((0, ast_utils_1.isCommentToken)(tokenBefore))
|
|
125
|
+
return null;
|
|
126
|
+
if (!(0, ast_utils_1.isTokenOnSameLine)(tokenBefore, token))
|
|
127
|
+
return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ");
|
|
128
|
+
const twoTokensBefore = sourceCode.getTokenBefore(tokenBefore, {
|
|
129
|
+
includeComments: true,
|
|
130
|
+
});
|
|
131
|
+
if ((0, ast_utils_1.isCommentToken)(twoTokensBefore))
|
|
132
|
+
return null;
|
|
133
|
+
return fixer.replaceTextRange([twoTokensBefore.range[1], tokenBefore.range[0]], "");
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function reportRequiredLineBreak(token) {
|
|
138
|
+
const tokenBefore = sourceCode.getTokenBefore(token, {
|
|
139
|
+
includeComments: true,
|
|
140
|
+
});
|
|
141
|
+
context.report({
|
|
142
|
+
loc: {
|
|
143
|
+
start: tokenBefore.loc.end,
|
|
144
|
+
end: token.loc.start,
|
|
145
|
+
},
|
|
146
|
+
messageId: "missingLineBreak",
|
|
147
|
+
fix(fixer) {
|
|
148
|
+
return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n");
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function check(node) {
|
|
153
|
+
const elements = node.elements;
|
|
154
|
+
const normalizedOptions = normalizeOptions(context.options[0]);
|
|
155
|
+
const options = normalizedOptions[node.type];
|
|
156
|
+
if (!options)
|
|
157
|
+
return;
|
|
158
|
+
let elementBreak = false;
|
|
159
|
+
if (options.multiline) {
|
|
160
|
+
elementBreak = elements
|
|
161
|
+
.filter((element) => element !== null)
|
|
162
|
+
.some((element) => element.loc.start.line !== element.loc.end.line);
|
|
163
|
+
}
|
|
164
|
+
let linebreaksCount = 0;
|
|
165
|
+
for (let i = 0; i < node.elements.length; i++) {
|
|
166
|
+
const element = node.elements[i];
|
|
167
|
+
const previousElement = elements[i - 1];
|
|
168
|
+
if (i === 0 || element === null || previousElement === null)
|
|
169
|
+
continue;
|
|
170
|
+
const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, ast_utils_1.isCommaToken);
|
|
171
|
+
const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken);
|
|
172
|
+
const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken);
|
|
173
|
+
if (!(0, ast_utils_1.isTokenOnSameLine)(lastTokenOfPreviousElement, firstTokenOfCurrentElement))
|
|
174
|
+
linebreaksCount++;
|
|
175
|
+
}
|
|
176
|
+
const needsLinebreaks = elements.length >= options.minItems ||
|
|
177
|
+
(options.multiline && elementBreak) ||
|
|
178
|
+
(options.consistent &&
|
|
179
|
+
linebreaksCount > 0 &&
|
|
180
|
+
linebreaksCount < node.elements.length);
|
|
181
|
+
elements.forEach((element, i) => {
|
|
182
|
+
const previousElement = elements[i - 1];
|
|
183
|
+
if (i === 0 || element === null || previousElement === null)
|
|
184
|
+
return;
|
|
185
|
+
const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, ast_utils_1.isCommaToken);
|
|
186
|
+
const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken);
|
|
187
|
+
const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken);
|
|
188
|
+
if (needsLinebreaks) {
|
|
189
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(lastTokenOfPreviousElement, firstTokenOfCurrentElement))
|
|
190
|
+
reportRequiredLineBreak(firstTokenOfCurrentElement);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
if (!(0, ast_utils_1.isTokenOnSameLine)(lastTokenOfPreviousElement, firstTokenOfCurrentElement))
|
|
194
|
+
reportNoLineBreak(firstTokenOfCurrentElement);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
TOMLArray: check,
|
|
200
|
+
};
|
|
29
201
|
},
|
|
30
202
|
});
|
package/lib/rules/comma-style.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
4
|
const compat_1 = require("../utils/compat");
|
|
5
|
-
const
|
|
5
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
6
6
|
exports.default = (0, utils_1.createRule)("comma-style", {
|
|
7
7
|
meta: {
|
|
8
8
|
docs: {
|
|
@@ -10,26 +10,155 @@ exports.default = (0, utils_1.createRule)("comma-style", {
|
|
|
10
10
|
categories: ["standard"],
|
|
11
11
|
extensionRule: "comma-style",
|
|
12
12
|
},
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
schema:
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
type: "layout",
|
|
14
|
+
fixable: "code",
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: "string",
|
|
18
|
+
enum: ["first", "last"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
exceptions: {
|
|
24
|
+
type: "object",
|
|
25
|
+
additionalProperties: {
|
|
26
|
+
type: "boolean",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
messages: {
|
|
34
|
+
unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.",
|
|
35
|
+
expectedCommaFirst: "',' should be placed first.",
|
|
36
|
+
expectedCommaLast: "',' should be placed last.",
|
|
37
|
+
},
|
|
18
38
|
},
|
|
19
39
|
create(context) {
|
|
40
|
+
var _a;
|
|
41
|
+
var _b;
|
|
20
42
|
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
21
43
|
if (!sourceCode.parserServices.isTOML) {
|
|
22
44
|
return {};
|
|
23
45
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
46
|
+
const style = context.options[0] || "last";
|
|
47
|
+
const exceptions = {};
|
|
48
|
+
if (context.options.length === 2 &&
|
|
49
|
+
Object.prototype.hasOwnProperty.call(context.options[1], "exceptions")) {
|
|
50
|
+
(_a = (_b = context.options)[1]) !== null && _a !== void 0 ? _a : (_b[1] = { exceptions: {} });
|
|
51
|
+
const rawExceptions = context.options[1].exceptions;
|
|
52
|
+
const keys = Object.keys(rawExceptions);
|
|
53
|
+
for (let i = 0; i < keys.length; i++)
|
|
54
|
+
exceptions[keys[i]] = rawExceptions[keys[i]];
|
|
55
|
+
}
|
|
56
|
+
function getReplacedText(styleType, text) {
|
|
57
|
+
switch (styleType) {
|
|
58
|
+
case "between":
|
|
59
|
+
return `,${text.replace(ast_utils_1.LINEBREAK_MATCHER, "")}`;
|
|
60
|
+
case "first":
|
|
61
|
+
return `${text},`;
|
|
62
|
+
case "last":
|
|
63
|
+
return `,${text}`;
|
|
64
|
+
default:
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) {
|
|
69
|
+
const text = sourceCode.text.slice(previousItemToken.range[1], commaToken.range[0]) +
|
|
70
|
+
sourceCode.text.slice(commaToken.range[1], currentItemToken.range[0]);
|
|
71
|
+
const range = [
|
|
72
|
+
previousItemToken.range[1],
|
|
73
|
+
currentItemToken.range[0],
|
|
74
|
+
];
|
|
75
|
+
return function (fixer) {
|
|
76
|
+
return fixer.replaceTextRange(range, getReplacedText(styleType, text));
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem) {
|
|
80
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(commaToken, currentItemToken) &&
|
|
81
|
+
(0, ast_utils_1.isTokenOnSameLine)(previousItemToken, commaToken)) {
|
|
82
|
+
}
|
|
83
|
+
else if (!(0, ast_utils_1.isTokenOnSameLine)(commaToken, currentItemToken) &&
|
|
84
|
+
!(0, ast_utils_1.isTokenOnSameLine)(previousItemToken, commaToken)) {
|
|
85
|
+
const comment = sourceCode.getCommentsAfter(commaToken)[0];
|
|
86
|
+
const styleType = comment &&
|
|
87
|
+
comment.type === "Block" &&
|
|
88
|
+
(0, ast_utils_1.isTokenOnSameLine)(commaToken, comment)
|
|
89
|
+
? style
|
|
90
|
+
: "between";
|
|
91
|
+
context.report({
|
|
92
|
+
node: reportItem,
|
|
93
|
+
loc: commaToken.loc,
|
|
94
|
+
messageId: "unexpectedLineBeforeAndAfterComma",
|
|
95
|
+
fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
else if (style === "first" &&
|
|
99
|
+
!(0, ast_utils_1.isTokenOnSameLine)(commaToken, currentItemToken)) {
|
|
100
|
+
context.report({
|
|
101
|
+
node: reportItem,
|
|
102
|
+
loc: commaToken.loc,
|
|
103
|
+
messageId: "expectedCommaFirst",
|
|
104
|
+
fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else if (style === "last" &&
|
|
108
|
+
(0, ast_utils_1.isTokenOnSameLine)(commaToken, currentItemToken)) {
|
|
109
|
+
context.report({
|
|
110
|
+
node: reportItem,
|
|
111
|
+
loc: commaToken.loc,
|
|
112
|
+
messageId: "expectedCommaLast",
|
|
113
|
+
fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function validateComma(node, property) {
|
|
118
|
+
const items = node[property];
|
|
119
|
+
const arrayLiteral = node.type === "TOMLArray";
|
|
120
|
+
if (items.length > 1 || arrayLiteral) {
|
|
121
|
+
let previousItemToken = sourceCode.getFirstToken(node);
|
|
122
|
+
items.forEach((item) => {
|
|
123
|
+
const commaToken = item
|
|
124
|
+
? sourceCode.getTokenBefore(item)
|
|
125
|
+
: previousItemToken;
|
|
126
|
+
const currentItemToken = item
|
|
127
|
+
? sourceCode.getFirstToken(item)
|
|
128
|
+
: sourceCode.getTokenAfter(commaToken);
|
|
129
|
+
const reportItem = item || currentItemToken;
|
|
130
|
+
if ((0, ast_utils_1.isCommaToken)(commaToken))
|
|
131
|
+
validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem);
|
|
132
|
+
if (item) {
|
|
133
|
+
const tokenAfterItem = sourceCode.getTokenAfter(item, ast_utils_1.isNotClosingParenToken);
|
|
134
|
+
previousItemToken = tokenAfterItem
|
|
135
|
+
? sourceCode.getTokenBefore(tokenAfterItem)
|
|
136
|
+
: sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1];
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
previousItemToken = currentItemToken;
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
if (arrayLiteral) {
|
|
143
|
+
const lastToken = sourceCode.getLastToken(node);
|
|
144
|
+
const nextToLastToken = sourceCode.getTokenBefore(lastToken);
|
|
145
|
+
if ((0, ast_utils_1.isCommaToken)(nextToLastToken)) {
|
|
146
|
+
validateCommaItemSpacing(sourceCode.getTokenBefore(nextToLastToken), nextToLastToken, lastToken, lastToken);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const nodes = {};
|
|
152
|
+
if (!exceptions.ObjectExpression && !exceptions.TOMLInlineTable) {
|
|
153
|
+
nodes.TOMLInlineTable = function (node) {
|
|
154
|
+
validateComma(node, "body");
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (!exceptions.ArrayExpression && !exceptions.TOMLArray) {
|
|
158
|
+
nodes.TOMLArray = function (node) {
|
|
159
|
+
validateComma(node, "elements");
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
return nodes;
|
|
34
163
|
},
|
|
35
164
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("../utils");
|
|
4
|
-
const
|
|
4
|
+
const compat_1 = require("../utils/compat");
|
|
5
|
+
const ast_utils_1 = require("../utils/ast-utils");
|
|
5
6
|
exports.default = (0, utils_1.createRule)("inline-table-curly-spacing", {
|
|
6
7
|
meta: {
|
|
7
8
|
docs: {
|
|
@@ -9,23 +10,168 @@ exports.default = (0, utils_1.createRule)("inline-table-curly-spacing", {
|
|
|
9
10
|
categories: ["standard"],
|
|
10
11
|
extensionRule: "object-curly-spacing",
|
|
11
12
|
},
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
schema:
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
type: "layout",
|
|
14
|
+
fixable: "whitespace",
|
|
15
|
+
schema: [
|
|
16
|
+
{
|
|
17
|
+
type: "string",
|
|
18
|
+
enum: ["always", "never"],
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
arraysInObjects: {
|
|
24
|
+
type: "boolean",
|
|
25
|
+
},
|
|
26
|
+
objectsInObjects: {
|
|
27
|
+
type: "boolean",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
messages: {
|
|
34
|
+
requireSpaceBefore: "A space is required before '{{token}}'.",
|
|
35
|
+
requireSpaceAfter: "A space is required after '{{token}}'.",
|
|
36
|
+
unexpectedSpaceBefore: "There should be no space before '{{token}}'.",
|
|
37
|
+
unexpectedSpaceAfter: "There should be no space after '{{token}}'.",
|
|
38
|
+
},
|
|
17
39
|
},
|
|
18
40
|
create(context) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
41
|
+
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
42
|
+
if (!sourceCode.parserServices.isTOML) {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
const spaced = (context.options[0] || "always") === "always";
|
|
46
|
+
function isOptionSet(option) {
|
|
47
|
+
return context.options[1]
|
|
48
|
+
? context.options[1][option] === !spaced
|
|
49
|
+
: false;
|
|
50
|
+
}
|
|
51
|
+
const options = {
|
|
52
|
+
spaced,
|
|
53
|
+
arraysInObjectsException: isOptionSet("arraysInObjects"),
|
|
54
|
+
objectsInObjectsException: isOptionSet("objectsInObjects"),
|
|
55
|
+
isOpeningCurlyBraceMustBeSpaced(_second) {
|
|
56
|
+
return options.spaced;
|
|
57
|
+
},
|
|
58
|
+
isClosingCurlyBraceMustBeSpaced(penultimate) {
|
|
59
|
+
var _a;
|
|
60
|
+
const targetPenultimateType = options.arraysInObjectsException && (0, ast_utils_1.isClosingBracketToken)(penultimate)
|
|
61
|
+
? "TOMLArray"
|
|
62
|
+
: options.objectsInObjectsException &&
|
|
63
|
+
(0, ast_utils_1.isClosingBraceToken)(penultimate)
|
|
64
|
+
? "TOMLInlineTable"
|
|
65
|
+
: null;
|
|
66
|
+
return targetPenultimateType &&
|
|
67
|
+
((_a = sourceCode.getNodeByRangeIndex(penultimate.range[0])) === null || _a === void 0 ? void 0 : _a.type) ===
|
|
68
|
+
targetPenultimateType
|
|
69
|
+
? !options.spaced
|
|
70
|
+
: options.spaced;
|
|
27
71
|
},
|
|
28
|
-
|
|
29
|
-
|
|
72
|
+
};
|
|
73
|
+
function reportNoBeginningSpace(node, token) {
|
|
74
|
+
const nextToken = sourceCode.getTokenAfter(token, {
|
|
75
|
+
includeComments: true,
|
|
76
|
+
});
|
|
77
|
+
context.report({
|
|
78
|
+
node,
|
|
79
|
+
loc: { start: token.loc.end, end: nextToken.loc.start },
|
|
80
|
+
messageId: "unexpectedSpaceAfter",
|
|
81
|
+
data: {
|
|
82
|
+
token: token.value,
|
|
83
|
+
},
|
|
84
|
+
fix(fixer) {
|
|
85
|
+
return fixer.removeRange([token.range[1], nextToken.range[0]]);
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function reportNoEndingSpace(node, token) {
|
|
90
|
+
const previousToken = sourceCode.getTokenBefore(token, {
|
|
91
|
+
includeComments: true,
|
|
92
|
+
});
|
|
93
|
+
context.report({
|
|
94
|
+
node,
|
|
95
|
+
loc: { start: previousToken.loc.end, end: token.loc.start },
|
|
96
|
+
messageId: "unexpectedSpaceBefore",
|
|
97
|
+
data: {
|
|
98
|
+
token: token.value,
|
|
99
|
+
},
|
|
100
|
+
fix(fixer) {
|
|
101
|
+
return fixer.removeRange([previousToken.range[1], token.range[0]]);
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function reportRequiredBeginningSpace(node, token) {
|
|
106
|
+
context.report({
|
|
107
|
+
node,
|
|
108
|
+
loc: token.loc,
|
|
109
|
+
messageId: "requireSpaceAfter",
|
|
110
|
+
data: {
|
|
111
|
+
token: token.value,
|
|
112
|
+
},
|
|
113
|
+
fix(fixer) {
|
|
114
|
+
return fixer.insertTextAfter(token, " ");
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function reportRequiredEndingSpace(node, token) {
|
|
119
|
+
context.report({
|
|
120
|
+
node,
|
|
121
|
+
loc: token.loc,
|
|
122
|
+
messageId: "requireSpaceBefore",
|
|
123
|
+
data: {
|
|
124
|
+
token: token.value,
|
|
125
|
+
},
|
|
126
|
+
fix(fixer) {
|
|
127
|
+
return fixer.insertTextBefore(token, " ");
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
function validateBraceSpacing(node, first, second, penultimate, last) {
|
|
132
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(first, second)) {
|
|
133
|
+
const firstSpaced = sourceCode.isSpaceBetweenTokens(first, second);
|
|
134
|
+
if (options.isOpeningCurlyBraceMustBeSpaced(second)) {
|
|
135
|
+
if (!firstSpaced)
|
|
136
|
+
reportRequiredBeginningSpace(node, first);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
if (firstSpaced && second.type !== "Block") {
|
|
140
|
+
reportNoBeginningSpace(node, first);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if ((0, ast_utils_1.isTokenOnSameLine)(penultimate, last)) {
|
|
145
|
+
const lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last);
|
|
146
|
+
if (options.isClosingCurlyBraceMustBeSpaced(penultimate)) {
|
|
147
|
+
if (!lastSpaced)
|
|
148
|
+
reportRequiredEndingSpace(node, last);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
if (lastSpaced)
|
|
152
|
+
reportNoEndingSpace(node, last);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function getClosingBraceOfObject(node) {
|
|
157
|
+
const lastProperty = node.body[node.body.length - 1];
|
|
158
|
+
return sourceCode.getTokenAfter(lastProperty, ast_utils_1.isClosingBraceToken);
|
|
159
|
+
}
|
|
160
|
+
function checkForObject(node) {
|
|
161
|
+
if (node.body.length === 0)
|
|
162
|
+
return;
|
|
163
|
+
const first = sourceCode.getFirstToken(node);
|
|
164
|
+
const last = getClosingBraceOfObject(node);
|
|
165
|
+
const second = sourceCode.getTokenAfter(first, {
|
|
166
|
+
includeComments: true,
|
|
167
|
+
});
|
|
168
|
+
const penultimate = sourceCode.getTokenBefore(last, {
|
|
169
|
+
includeComments: true,
|
|
170
|
+
});
|
|
171
|
+
validateBraceSpacing(node, first, second, penultimate, last);
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
TOMLInlineTable: checkForObject,
|
|
175
|
+
};
|
|
30
176
|
},
|
|
31
177
|
});
|
package/lib/types.d.ts
CHANGED
|
@@ -114,7 +114,7 @@ export interface SourceCode {
|
|
|
114
114
|
getTokenByRangeStart(offset: number, options?: {
|
|
115
115
|
includeComments?: boolean;
|
|
116
116
|
}): TOMLToken | null;
|
|
117
|
-
getFirstToken(node: AST.TOMLNode): AST.Token;
|
|
117
|
+
getFirstToken(node: AST.TOMLNode | AST.Token): AST.Token;
|
|
118
118
|
getFirstToken(node: AST.TOMLNode, options?: CursorWithSkipOptions): TOMLToken | null;
|
|
119
119
|
getFirstTokens(node: AST.TOMLNode, options?: CursorWithCountOptions): TOMLToken[];
|
|
120
120
|
getLastToken(node: AST.TOMLNode): AST.Token;
|
|
@@ -186,7 +186,7 @@ export interface RuleFixer {
|
|
|
186
186
|
remove(nodeOrToken: TOMLNodeOrToken): Fix;
|
|
187
187
|
removeRange(range: AST.Range): Fix;
|
|
188
188
|
replaceText(nodeOrToken: TOMLNodeOrToken, text: string): Fix;
|
|
189
|
-
replaceTextRange(range: AST.Range
|
|
189
|
+
replaceTextRange(range: Readonly<AST.Range>, text: string): Fix;
|
|
190
190
|
}
|
|
191
191
|
export interface Fix {
|
|
192
192
|
range: AST.Range;
|
package/lib/utils/ast-utils.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import type { TOMLToken } from "../types";
|
|
2
|
+
export declare const LINEBREAK_MATCHER: RegExp;
|
|
2
3
|
export declare function isCommentToken(token: TOMLToken | null): boolean;
|
|
4
|
+
export declare function isCommaToken(token: TOMLToken | null): token is TOMLToken;
|
|
3
5
|
export declare function isEqualSign(token: TOMLToken | null): token is TOMLToken;
|
|
6
|
+
export declare function isClosingParenToken(token: TOMLToken | null): token is TOMLToken;
|
|
7
|
+
export declare const isNotClosingParenToken: typeof isClosingParenToken;
|
|
8
|
+
export declare function isClosingBracketToken(token: TOMLToken | null): token is TOMLToken;
|
|
9
|
+
export declare function isClosingBraceToken(token: TOMLToken | null): token is TOMLToken;
|
|
10
|
+
export declare function isTokenOnSameLine(left: TOMLToken | null, right: TOMLToken | null): boolean;
|
package/lib/utils/ast-utils.js
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isEqualSign = exports.isCommentToken = void 0;
|
|
3
|
+
exports.isTokenOnSameLine = exports.isClosingBraceToken = exports.isClosingBracketToken = exports.isNotClosingParenToken = exports.isClosingParenToken = exports.isEqualSign = exports.isCommaToken = exports.isCommentToken = exports.LINEBREAK_MATCHER = void 0;
|
|
4
|
+
exports.LINEBREAK_MATCHER = /\r\n|[\n\r\u2028\u2029]/u;
|
|
4
5
|
function isCommentToken(token) {
|
|
5
6
|
return Boolean(token && token.type === "Block");
|
|
6
7
|
}
|
|
7
8
|
exports.isCommentToken = isCommentToken;
|
|
9
|
+
function isCommaToken(token) {
|
|
10
|
+
return token != null && token.value === "," && token.type === "Punctuator";
|
|
11
|
+
}
|
|
12
|
+
exports.isCommaToken = isCommaToken;
|
|
8
13
|
function isEqualSign(token) {
|
|
9
14
|
return token != null && token.type === "Punctuator" && token.value === "=";
|
|
10
15
|
}
|
|
11
16
|
exports.isEqualSign = isEqualSign;
|
|
17
|
+
function isClosingParenToken(token) {
|
|
18
|
+
return token != null && token.value === ")" && token.type === "Punctuator";
|
|
19
|
+
}
|
|
20
|
+
exports.isClosingParenToken = isClosingParenToken;
|
|
21
|
+
exports.isNotClosingParenToken = negate(isClosingParenToken);
|
|
22
|
+
function isClosingBracketToken(token) {
|
|
23
|
+
return token != null && token.value === "]" && token.type === "Punctuator";
|
|
24
|
+
}
|
|
25
|
+
exports.isClosingBracketToken = isClosingBracketToken;
|
|
26
|
+
function isClosingBraceToken(token) {
|
|
27
|
+
return token != null && token.value === "}" && token.type === "Punctuator";
|
|
28
|
+
}
|
|
29
|
+
exports.isClosingBraceToken = isClosingBraceToken;
|
|
30
|
+
function isTokenOnSameLine(left, right) {
|
|
31
|
+
var _a, _b;
|
|
32
|
+
return ((_a = left === null || left === void 0 ? void 0 : left.loc) === null || _a === void 0 ? void 0 : _a.end.line) === ((_b = right === null || right === void 0 ? void 0 : right.loc) === null || _b === void 0 ? void 0 : _b.start.line);
|
|
33
|
+
}
|
|
34
|
+
exports.isTokenOnSameLine = isTokenOnSameLine;
|
|
35
|
+
function negate(f) {
|
|
36
|
+
return ((token) => !f(token));
|
|
37
|
+
}
|
package/lib/utils/index.d.ts
CHANGED
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type * as ESTree from "estree";
|
|
3
|
-
import type { Rule } from "eslint";
|
|
4
|
-
import type { AST } from "toml-eslint-parser";
|
|
1
|
+
import type { RuleModule, PartialRuleModule } from "../types";
|
|
5
2
|
export declare function createRule(ruleName: string, rule: PartialRuleModule): RuleModule;
|
|
6
|
-
type CoreRuleListener = {
|
|
7
|
-
[key: string]: (node: any) => void;
|
|
8
|
-
};
|
|
9
|
-
export declare function defineWrapperListener(coreRule: Rule.RuleModule, context: RuleContext, proxyOptions: {
|
|
10
|
-
options: any[];
|
|
11
|
-
createListenerProxy?: (listener: CoreRuleListener) => RuleListener;
|
|
12
|
-
getNodeProxy?: (node: AST.TOMLNode) => any;
|
|
13
|
-
}): RuleListener;
|
|
14
|
-
export declare function getProxyNode(node: AST.TOMLNode, properties: any): any;
|
|
15
|
-
export declare function convertESNode(node: AST.TOMLNode): ESTree.Node;
|
|
16
|
-
export declare function getCoreRule(ruleName: string): Rule.RuleModule;
|
|
17
|
-
export {};
|
package/lib/utils/index.js
CHANGED
|
@@ -26,12 +26,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.
|
|
29
|
+
exports.createRule = void 0;
|
|
30
30
|
const tomlESLintParser = __importStar(require("toml-eslint-parser"));
|
|
31
|
-
const debug_1 = __importDefault(require("debug"));
|
|
32
31
|
const path_1 = __importDefault(require("path"));
|
|
33
32
|
const compat_1 = require("./compat");
|
|
34
|
-
const log = (0, debug_1.default)("eslint-plugin-toml:utils/index");
|
|
35
33
|
function createRule(ruleName, rule) {
|
|
36
34
|
return {
|
|
37
35
|
meta: Object.assign(Object.assign({}, rule.meta), { docs: Object.assign(Object.assign({}, rule.meta.docs), { url: `https://ota-meshi.github.io/eslint-plugin-toml/rules/${ruleName}.html`, ruleId: `toml/${ruleName}`, ruleName }) }),
|
|
@@ -56,95 +54,3 @@ function createRule(ruleName, rule) {
|
|
|
56
54
|
};
|
|
57
55
|
}
|
|
58
56
|
exports.createRule = createRule;
|
|
59
|
-
function defineWrapperListener(coreRule, context, proxyOptions) {
|
|
60
|
-
var _a, _b;
|
|
61
|
-
const sourceCode = (0, compat_1.getSourceCode)(context);
|
|
62
|
-
if (!sourceCode.parserServices.isTOML) {
|
|
63
|
-
return {};
|
|
64
|
-
}
|
|
65
|
-
const proxySourceCode = Object.assign({ __proto__: sourceCode }, ["getNodeByRangeIndex"].reduce((obj, key) => {
|
|
66
|
-
obj[key] = (...args) => {
|
|
67
|
-
var _a;
|
|
68
|
-
const node = sourceCode[key](...args);
|
|
69
|
-
return ((_a = proxyOptions.getNodeProxy) === null || _a === void 0 ? void 0 : _a.call(proxyOptions, node)) || node;
|
|
70
|
-
};
|
|
71
|
-
return obj;
|
|
72
|
-
}, {}));
|
|
73
|
-
const listener = coreRule.create({
|
|
74
|
-
__proto__: context,
|
|
75
|
-
options: proxyOptions.options,
|
|
76
|
-
getSourceCode() {
|
|
77
|
-
return proxySourceCode;
|
|
78
|
-
},
|
|
79
|
-
sourceCode: proxySourceCode,
|
|
80
|
-
});
|
|
81
|
-
const tomlListener = (_b = (_a = proxyOptions.createListenerProxy) === null || _a === void 0 ? void 0 : _a.call(proxyOptions, listener)) !== null && _b !== void 0 ? _b : listener;
|
|
82
|
-
return tomlListener;
|
|
83
|
-
}
|
|
84
|
-
exports.defineWrapperListener = defineWrapperListener;
|
|
85
|
-
function getProxyNode(node, properties) {
|
|
86
|
-
const safeKeys = new Set([
|
|
87
|
-
"range",
|
|
88
|
-
"typeAnnotation",
|
|
89
|
-
]);
|
|
90
|
-
const cache = {};
|
|
91
|
-
return new Proxy(node, {
|
|
92
|
-
get(_t, key) {
|
|
93
|
-
if (key in cache) {
|
|
94
|
-
return cache[key];
|
|
95
|
-
}
|
|
96
|
-
if (key in properties) {
|
|
97
|
-
return (cache[key] = properties[key]);
|
|
98
|
-
}
|
|
99
|
-
if (!safeKeys.has(key)) {
|
|
100
|
-
log(`fallback: ${String(key)}`);
|
|
101
|
-
}
|
|
102
|
-
return node[key];
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
exports.getProxyNode = getProxyNode;
|
|
107
|
-
const convertedESNodeCache = new WeakMap();
|
|
108
|
-
function convertESNode(node) {
|
|
109
|
-
const converted = convertedESNodeCache.get(node);
|
|
110
|
-
if (converted) {
|
|
111
|
-
return converted;
|
|
112
|
-
}
|
|
113
|
-
let esNode;
|
|
114
|
-
if (node.type === "TOMLInlineTable") {
|
|
115
|
-
const properties = node.body;
|
|
116
|
-
esNode = getProxyNode(node, {
|
|
117
|
-
type: "ObjectExpression",
|
|
118
|
-
get properties() {
|
|
119
|
-
return properties.map(convertESNode);
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
else if (node.type === "TOMLArray") {
|
|
124
|
-
const elements = node.elements;
|
|
125
|
-
esNode = getProxyNode(node, {
|
|
126
|
-
type: "ArrayExpression",
|
|
127
|
-
get elements() {
|
|
128
|
-
return elements.map(convertESNode);
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
esNode = node;
|
|
134
|
-
}
|
|
135
|
-
convertedESNodeCache.set(node, esNode);
|
|
136
|
-
return esNode;
|
|
137
|
-
}
|
|
138
|
-
exports.convertESNode = convertESNode;
|
|
139
|
-
let ruleMap = null;
|
|
140
|
-
function getCoreRule(ruleName) {
|
|
141
|
-
let map;
|
|
142
|
-
if (ruleMap) {
|
|
143
|
-
map = ruleMap;
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
ruleMap = map = new (require("eslint").Linter)().getRules();
|
|
147
|
-
}
|
|
148
|
-
return map.get(ruleName);
|
|
149
|
-
}
|
|
150
|
-
exports.getCoreRule = getCoreRule;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-toml",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "This ESLint plugin provides linting rules for TOML.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"debug": "^4.1.1",
|
|
60
60
|
"eslint-compat-utils": "^0.1.2",
|
|
61
61
|
"lodash": "^4.17.19",
|
|
62
|
-
"toml-eslint-parser": "^0.
|
|
62
|
+
"toml-eslint-parser": "^0.9.0"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@changesets/changelog-github": "^0.
|
|
65
|
+
"@changesets/changelog-github": "^0.5.0",
|
|
66
66
|
"@changesets/cli": "^2.24.2",
|
|
67
67
|
"@ota-meshi/eslint-plugin": "^0.15.0",
|
|
68
68
|
"@ota-meshi/site-kit-eslint-editor-vue": "^0.1.2",
|
|
@@ -99,11 +99,11 @@
|
|
|
99
99
|
"pako": "^2.1.0",
|
|
100
100
|
"prettier": "^3.0.0",
|
|
101
101
|
"semver": "^7.3.2",
|
|
102
|
-
"stylelint": "^
|
|
102
|
+
"stylelint": "^16.0.0",
|
|
103
103
|
"stylelint-config-recommended-vue": "^1.0.0",
|
|
104
|
-
"stylelint-config-standard": "^
|
|
104
|
+
"stylelint-config-standard": "^35.0.0",
|
|
105
105
|
"stylelint-config-standard-vue": "^1.0.0",
|
|
106
|
-
"stylelint-stylus": "^0.
|
|
106
|
+
"stylelint-stylus": "^1.0.0",
|
|
107
107
|
"ts-node": "^10.0.0",
|
|
108
108
|
"typescript": "~5.0.0",
|
|
109
109
|
"vite-plugin-eslint4b": "^0.2.1",
|