Permalink
Cannot retrieve contributors at this time
149 lines (130 sloc)
5.04 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/eslint/lib/rules/no-extra-label.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @fileoverview Rule to disallow unnecessary labels | |
* @author Toru Nagashima | |
*/ | |
"use strict"; | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
const astUtils = require("./utils/ast-utils"); | |
//------------------------------------------------------------------------------ | |
// Rule Definition | |
//------------------------------------------------------------------------------ | |
/** @type {import('../shared/types').Rule} */ | |
module.exports = { | |
meta: { | |
type: "suggestion", | |
docs: { | |
description: "Disallow unnecessary labels", | |
recommended: false, | |
url: "https://eslint.org/docs/latest/rules/no-extra-label" | |
}, | |
schema: [], | |
fixable: "code", | |
messages: { | |
unexpected: "This label '{{name}}' is unnecessary." | |
} | |
}, | |
create(context) { | |
const sourceCode = context.sourceCode; | |
let scopeInfo = null; | |
/** | |
* Creates a new scope with a breakable statement. | |
* @param {ASTNode} node A node to create. This is a BreakableStatement. | |
* @returns {void} | |
*/ | |
function enterBreakableStatement(node) { | |
scopeInfo = { | |
label: node.parent.type === "LabeledStatement" ? node.parent.label : null, | |
breakable: true, | |
upper: scopeInfo | |
}; | |
} | |
/** | |
* Removes the top scope of the stack. | |
* @returns {void} | |
*/ | |
function exitBreakableStatement() { | |
scopeInfo = scopeInfo.upper; | |
} | |
/** | |
* Creates a new scope with a labeled statement. | |
* | |
* This ignores it if the body is a breakable statement. | |
* In this case it's handled in the `enterBreakableStatement` function. | |
* @param {ASTNode} node A node to create. This is a LabeledStatement. | |
* @returns {void} | |
*/ | |
function enterLabeledStatement(node) { | |
if (!astUtils.isBreakableStatement(node.body)) { | |
scopeInfo = { | |
label: node.label, | |
breakable: false, | |
upper: scopeInfo | |
}; | |
} | |
} | |
/** | |
* Removes the top scope of the stack. | |
* | |
* This ignores it if the body is a breakable statement. | |
* In this case it's handled in the `exitBreakableStatement` function. | |
* @param {ASTNode} node A node. This is a LabeledStatement. | |
* @returns {void} | |
*/ | |
function exitLabeledStatement(node) { | |
if (!astUtils.isBreakableStatement(node.body)) { | |
scopeInfo = scopeInfo.upper; | |
} | |
} | |
/** | |
* Reports a given control node if it's unnecessary. | |
* @param {ASTNode} node A node. This is a BreakStatement or a | |
* ContinueStatement. | |
* @returns {void} | |
*/ | |
function reportIfUnnecessary(node) { | |
if (!node.label) { | |
return; | |
} | |
const labelNode = node.label; | |
for (let info = scopeInfo; info !== null; info = info.upper) { | |
if (info.breakable || info.label && info.label.name === labelNode.name) { | |
if (info.breakable && info.label && info.label.name === labelNode.name) { | |
context.report({ | |
node: labelNode, | |
messageId: "unexpected", | |
data: labelNode, | |
fix(fixer) { | |
const breakOrContinueToken = sourceCode.getFirstToken(node); | |
if (sourceCode.commentsExistBetween(breakOrContinueToken, labelNode)) { | |
return null; | |
} | |
return fixer.removeRange([breakOrContinueToken.range[1], labelNode.range[1]]); | |
} | |
}); | |
} | |
return; | |
} | |
} | |
} | |
return { | |
WhileStatement: enterBreakableStatement, | |
"WhileStatement:exit": exitBreakableStatement, | |
DoWhileStatement: enterBreakableStatement, | |
"DoWhileStatement:exit": exitBreakableStatement, | |
ForStatement: enterBreakableStatement, | |
"ForStatement:exit": exitBreakableStatement, | |
ForInStatement: enterBreakableStatement, | |
"ForInStatement:exit": exitBreakableStatement, | |
ForOfStatement: enterBreakableStatement, | |
"ForOfStatement:exit": exitBreakableStatement, | |
SwitchStatement: enterBreakableStatement, | |
"SwitchStatement:exit": exitBreakableStatement, | |
LabeledStatement: enterLabeledStatement, | |
"LabeledStatement:exit": exitLabeledStatement, | |
BreakStatement: reportIfUnnecessary, | |
ContinueStatement: reportIfUnnecessary | |
}; | |
} | |
}; |