]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/semi-style.js
0c9bec4c85ede81e29c4493f42234263df2fe5fc
2 * @fileoverview Rule to enforce location of semicolons.
3 * @author Toru Nagashima
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 const astUtils
= require("./utils/ast-utils");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
18 const SELECTOR
= `:matches(${
20 "BreakStatement", "ContinueStatement", "DebuggerStatement",
21 "DoWhileStatement", "ExportAllDeclaration",
22 "ExportDefaultDeclaration", "ExportNamedDeclaration",
23 "ExpressionStatement", "ImportDeclaration", "ReturnStatement",
24 "ThrowStatement", "VariableDeclaration"
29 * Get the child node list of a given node.
30 * This returns `Program#body`, `BlockStatement#body`, or `SwitchCase#consequent`.
31 * This is used to check whether a node is the first/last child.
32 * @param {Node} node A node to get child node list.
33 * @returns {Node[]|null} The child node list.
35 function getChildren(node
) {
38 if (t
=== "BlockStatement" || t
=== "Program") {
41 if (t
=== "SwitchCase") {
42 return node
.consequent
;
48 * Check whether a given node is the last statement in the parent block.
49 * @param {Node} node A node to check.
50 * @returns {boolean} `true` if the node is the last statement in the parent block.
52 function isLastChild(node
) {
53 const t
= node
.parent
.type
;
55 if (t
=== "IfStatement" && node
.parent
.consequent
=== node
&& node
.parent
.alternate
) { // before `else` keyword.
58 if (t
=== "DoWhileStatement") { // before `while` keyword.
61 const nodeList
= getChildren(node
.parent
);
63 return nodeList
!== null && nodeList
[nodeList
.length
- 1] === node
; // before `}` or etc.
71 description
: "enforce location of semicolons",
72 category
: "Stylistic Issues",
74 url
: "https://eslint.org/docs/rules/semi-style"
77 schema
: [{ enum: ["last", "first"] }],
78 fixable
: "whitespace",
81 expectedSemiColon
: "Expected this semicolon to be at {{pos}}."
86 const sourceCode
= context
.getSourceCode();
87 const option
= context
.options
[0] || "last";
90 * Check the given semicolon token.
91 * @param {Token} semiToken The semicolon token to check.
92 * @param {"first"|"last"} expected The expected location to check.
95 function check(semiToken
, expected
) {
96 const prevToken
= sourceCode
.getTokenBefore(semiToken
);
97 const nextToken
= sourceCode
.getTokenAfter(semiToken
);
98 const prevIsSameLine
= !prevToken
|| astUtils
.isTokenOnSameLine(prevToken
, semiToken
);
99 const nextIsSameLine
= !nextToken
|| astUtils
.isTokenOnSameLine(semiToken
, nextToken
);
101 if ((expected
=== "last" && !prevIsSameLine
) || (expected
=== "first" && !nextIsSameLine
)) {
104 messageId
: "expectedSemiColon",
106 pos
: (expected
=== "last")
107 ? "the end of the previous line"
108 : "the beginning of the next line"
111 if (prevToken
&& nextToken
&& sourceCode
.commentsExistBetween(prevToken
, nextToken
)) {
115 const start
= prevToken
? prevToken
.range
[1] : semiToken
.range
[0];
116 const end
= nextToken
? nextToken
.range
[0] : semiToken
.range
[1];
117 const text
= (expected
=== "last") ? ";\n" : "\n;";
119 return fixer
.replaceTextRange([start
, end
], text
);
127 if (option
=== "first" && isLastChild(node
)) {
131 const lastToken
= sourceCode
.getLastToken(node
);
133 if (astUtils
.isSemicolonToken(lastToken
)) {
134 check(lastToken
, option
);
139 const firstSemi
= node
.init
&& sourceCode
.getTokenAfter(node
.init
, astUtils
.isSemicolonToken
);
140 const secondSemi
= node
.test
&& sourceCode
.getTokenAfter(node
.test
, astUtils
.isSemicolonToken
);
143 check(firstSemi
, "last");
146 check(secondSemi
, "last");