You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
4.1 KiB
126 lines
4.1 KiB
/** |
|
* @fileoverview Rule to flag use of unnecessary semicolons |
|
* @author Nicholas C. Zakas |
|
*/ |
|
|
|
"use strict"; |
|
|
|
//------------------------------------------------------------------------------ |
|
// Requirements |
|
//------------------------------------------------------------------------------ |
|
|
|
const FixTracker = require("./utils/fix-tracker"); |
|
const astUtils = require("./utils/ast-utils"); |
|
|
|
//------------------------------------------------------------------------------ |
|
// Rule Definition |
|
//------------------------------------------------------------------------------ |
|
|
|
/** @type {import('../shared/types').Rule} */ |
|
module.exports = { |
|
meta: { |
|
type: "suggestion", |
|
|
|
docs: { |
|
description: "Disallow unnecessary semicolons", |
|
recommended: true, |
|
url: "https://eslint.org/docs/rules/no-extra-semi" |
|
}, |
|
|
|
fixable: "code", |
|
schema: [], |
|
|
|
messages: { |
|
unexpected: "Unnecessary semicolon." |
|
} |
|
}, |
|
|
|
create(context) { |
|
const sourceCode = context.getSourceCode(); |
|
|
|
/** |
|
* Reports an unnecessary semicolon error. |
|
* @param {Node|Token} nodeOrToken A node or a token to be reported. |
|
* @returns {void} |
|
*/ |
|
function report(nodeOrToken) { |
|
context.report({ |
|
node: nodeOrToken, |
|
messageId: "unexpected", |
|
fix(fixer) { |
|
|
|
/* |
|
* Expand the replacement range to include the surrounding |
|
* tokens to avoid conflicting with semi. |
|
* https://github.com/eslint/eslint/issues/7928 |
|
*/ |
|
return new FixTracker(fixer, context.getSourceCode()) |
|
.retainSurroundingTokens(nodeOrToken) |
|
.remove(nodeOrToken); |
|
} |
|
}); |
|
} |
|
|
|
/** |
|
* Checks for a part of a class body. |
|
* This checks tokens from a specified token to a next MethodDefinition or the end of class body. |
|
* @param {Token} firstToken The first token to check. |
|
* @returns {void} |
|
*/ |
|
function checkForPartOfClassBody(firstToken) { |
|
for (let token = firstToken; |
|
token.type === "Punctuator" && !astUtils.isClosingBraceToken(token); |
|
token = sourceCode.getTokenAfter(token) |
|
) { |
|
if (astUtils.isSemicolonToken(token)) { |
|
report(token); |
|
} |
|
} |
|
} |
|
|
|
return { |
|
|
|
/** |
|
* Reports this empty statement, except if the parent node is a loop. |
|
* @param {Node} node A EmptyStatement node to be reported. |
|
* @returns {void} |
|
*/ |
|
EmptyStatement(node) { |
|
const parent = node.parent, |
|
allowedParentTypes = [ |
|
"ForStatement", |
|
"ForInStatement", |
|
"ForOfStatement", |
|
"WhileStatement", |
|
"DoWhileStatement", |
|
"IfStatement", |
|
"LabeledStatement", |
|
"WithStatement" |
|
]; |
|
|
|
if (!allowedParentTypes.includes(parent.type)) { |
|
report(node); |
|
} |
|
}, |
|
|
|
/** |
|
* Checks tokens from the head of this class body to the first MethodDefinition or the end of this class body. |
|
* @param {Node} node A ClassBody node to check. |
|
* @returns {void} |
|
*/ |
|
ClassBody(node) { |
|
checkForPartOfClassBody(sourceCode.getFirstToken(node, 1)); // 0 is `{`. |
|
}, |
|
|
|
/** |
|
* Checks tokens from this MethodDefinition to the next MethodDefinition or the end of this class body. |
|
* @param {Node} node A MethodDefinition node of the start point. |
|
* @returns {void} |
|
*/ |
|
"MethodDefinition, PropertyDefinition, StaticBlock"(node) { |
|
checkForPartOfClassBody(sourceCode.getTokenAfter(node)); |
|
} |
|
}; |
|
|
|
} |
|
};
|
|
|