summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/node_modules/eslint-utils/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/node_modules/eslint-utils/index.js')
-rw-r--r--tools/node_modules/eslint/node_modules/eslint-utils/index.js305
1 files changed, 295 insertions, 10 deletions
diff --git a/tools/node_modules/eslint/node_modules/eslint-utils/index.js b/tools/node_modules/eslint/node_modules/eslint-utils/index.js
index a74dd9037a..d501e86d3f 100644
--- a/tools/node_modules/eslint/node_modules/eslint-utils/index.js
+++ b/tools/node_modules/eslint/node_modules/eslint-utils/index.js
@@ -3,6 +3,10 @@
Object.defineProperty(exports, '__esModule', { value: true });
+function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
+
+var evk = _interopDefault(require('eslint-visitor-keys'));
+
/**
* Get the innermost scope which contains a given location.
* @param {Scope} initialScope The initial scope to search.
@@ -742,12 +746,291 @@ function getFunctionNameWithKind(node) {
return tokens.join(" ")
}
+const typeConversionBinaryOps = Object.freeze(
+ new Set([
+ "==",
+ "!=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "<<",
+ ">>",
+ ">>>",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "|",
+ "^",
+ "&",
+ "in",
+ ])
+);
+const typeConversionUnaryOps = Object.freeze(new Set(["-", "+", "!", "~"]));
+const visitor = Object.freeze(
+ Object.assign(Object.create(null), {
+ $visit(node, options, visitorKeys) {
+ const { type } = node;
+
+ if (typeof this[type] === "function") {
+ return this[type](node, options, visitorKeys)
+ }
+
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+
+ $visitChildren(node, options, visitorKeys) {
+ const { type } = node;
+
+ for (const key of visitorKeys[type] || evk.getKeys(node)) {
+ const value = node[key];
+
+ if (Array.isArray(value)) {
+ for (const element of value) {
+ if (
+ element &&
+ this.$visit(element, options, visitorKeys)
+ ) {
+ return true
+ }
+ }
+ } else if (value && this.$visit(value, options, visitorKeys)) {
+ return true
+ }
+ }
+
+ return false
+ },
+
+ ArrowFunctionExpression() {
+ return false
+ },
+ AssignmentExpression() {
+ return true
+ },
+ AwaitExpression() {
+ return true
+ },
+ BinaryExpression(node, options, visitorKeys) {
+ if (
+ options.considerImplicitTypeConversion &&
+ typeConversionBinaryOps.has(node.operator) &&
+ (node.left.type !== "Literal" || node.right.type !== "Literal")
+ ) {
+ return true
+ }
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+ CallExpression() {
+ return true
+ },
+ FunctionExpression() {
+ return false
+ },
+ ImportExpression() {
+ return true
+ },
+ MemberExpression(node, options, visitorKeys) {
+ if (options.considerGetters) {
+ return true
+ }
+ if (
+ options.considerImplicitTypeConversion &&
+ node.computed &&
+ node.property.type !== "Literal"
+ ) {
+ return true
+ }
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+ MethodDefinition(node, options, visitorKeys) {
+ if (
+ options.considerImplicitTypeConversion &&
+ node.computed &&
+ node.key.type !== "Literal"
+ ) {
+ return true
+ }
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+ NewExpression() {
+ return true
+ },
+ Property(node, options, visitorKeys) {
+ if (
+ options.considerImplicitTypeConversion &&
+ node.computed &&
+ node.key.type !== "Literal"
+ ) {
+ return true
+ }
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+ UnaryExpression(node, options, visitorKeys) {
+ if (node.operator === "delete") {
+ return true
+ }
+ if (
+ options.considerImplicitTypeConversion &&
+ typeConversionUnaryOps.has(node.operator) &&
+ node.argument.type !== "Literal"
+ ) {
+ return true
+ }
+ return this.$visitChildren(node, options, visitorKeys)
+ },
+ UpdateExpression() {
+ return true
+ },
+ YieldExpression() {
+ return true
+ },
+ })
+);
+
+/**
+ * Check whether a given node has any side effect or not.
+ * @param {Node} node The node to get.
+ * @param {SourceCode} sourceCode The source code object.
+ * @param {object} [options] The option object.
+ * @param {boolean} [options.considerGetters=false] If `true` then it considers member accesses as the node which has side effects.
+ * @param {boolean} [options.considerImplicitTypeConversion=false] If `true` then it considers implicit type conversion as the node which has side effects.
+ * @param {object} [options.visitorKeys=evk.KEYS] The keys to traverse nodes. Use `context.getSourceCode().visitorKeys`.
+ * @returns {boolean} `true` if the node has a certain side effect.
+ */
+function hasSideEffect(
+ node,
+ sourceCode,
+ { considerGetters = false, considerImplicitTypeConversion = false } = {}
+) {
+ return visitor.$visit(
+ node,
+ { considerGetters, considerImplicitTypeConversion },
+ sourceCode.visitorKeys || evk.KEYS
+ )
+}
+
+/**
+ * Get the left parenthesis of the parent node syntax if it exists.
+ * E.g., `if (a) {}` then the `(`.
+ * @param {Node} node The AST node to check.
+ * @param {SourceCode} sourceCode The source code object to get tokens.
+ * @returns {Token|null} The left parenthesis of the parent node syntax
+ */
+function getParentSyntaxParen(node, sourceCode) {
+ const parent = node.parent;
+
+ switch (parent.type) {
+ case "CallExpression":
+ case "NewExpression":
+ if (parent.arguments.length === 1 && parent.arguments[0] === node) {
+ return sourceCode.getTokenAfter(
+ parent.callee,
+ isOpeningParenToken
+ )
+ }
+ return null
+
+ case "DoWhileStatement":
+ if (parent.test === node) {
+ return sourceCode.getTokenAfter(
+ parent.body,
+ isOpeningParenToken
+ )
+ }
+ return null
+
+ case "IfStatement":
+ case "WhileStatement":
+ if (parent.test === node) {
+ return sourceCode.getFirstToken(parent, 1)
+ }
+ return null
+
+ case "ImportExpression":
+ if (parent.source === node) {
+ return sourceCode.getFirstToken(parent, 1)
+ }
+ return null
+
+ case "SwitchStatement":
+ if (parent.discriminant === node) {
+ return sourceCode.getFirstToken(parent, 1)
+ }
+ return null
+
+ case "WithStatement":
+ if (parent.object === node) {
+ return sourceCode.getFirstToken(parent, 1)
+ }
+ return null
+
+ default:
+ return null
+ }
+}
+
+/**
+ * Check whether a given node is parenthesized or not.
+ * @param {number} times The number of parantheses.
+ * @param {Node} node The AST node to check.
+ * @param {SourceCode} sourceCode The source code object to get tokens.
+ * @returns {boolean} `true` if the node is parenthesized the given times.
+ */
+/**
+ * Check whether a given node is parenthesized or not.
+ * @param {Node} node The AST node to check.
+ * @param {SourceCode} sourceCode The source code object to get tokens.
+ * @returns {boolean} `true` if the node is parenthesized.
+ */
+function isParenthesized(
+ timesOrNode,
+ nodeOrSourceCode,
+ optionalSourceCode
+) {
+ let times, node, sourceCode, maybeLeftParen, maybeRightParen;
+ if (typeof timesOrNode === "number") {
+ times = timesOrNode | 0;
+ node = nodeOrSourceCode;
+ sourceCode = optionalSourceCode;
+ if (!(times >= 1)) {
+ throw new TypeError("'times' should be a positive integer.")
+ }
+ } else {
+ times = 1;
+ node = timesOrNode;
+ sourceCode = nodeOrSourceCode;
+ }
+
+ if (node == null) {
+ return false
+ }
+
+ maybeLeftParen = maybeRightParen = node;
+ do {
+ maybeLeftParen = sourceCode.getTokenBefore(maybeLeftParen);
+ maybeRightParen = sourceCode.getTokenAfter(maybeRightParen);
+ } while (
+ maybeLeftParen != null &&
+ maybeRightParen != null &&
+ isOpeningParenToken(maybeLeftParen) &&
+ isClosingParenToken(maybeRightParen) &&
+ // Avoid false positive such as `if (a) {}`
+ maybeLeftParen !== getParentSyntaxParen(node, sourceCode) &&
+ --times > 0
+ )
+
+ return times === 0
+}
+
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
-const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/g;
+const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu;
/** @type {WeakMap<PatternMatcher, {pattern:RegExp,escaped:boolean}>} */
const internal = new WeakMap();
@@ -814,7 +1097,6 @@ function replaceS(matcher, str, replacement) {
return chunks.join("")
}
-//eslint-disable-next-line valid-jsdoc
/**
* Replace a given string by a given matcher.
* @param {PatternMatcher} matcher The pattern matcher.
@@ -890,7 +1172,6 @@ class PatternMatcher {
return !ret.done
}
- //eslint-disable-next-line valid-jsdoc
/**
* Replace a given string.
* @param {string} str The string to be replaced.
@@ -904,8 +1185,8 @@ class PatternMatcher {
}
}
-const SENTINEL_TYPE = /^(?:.+?Statement|.+?Declaration|(?:Array|ArrowFunction|Assignment|Call|Class|Function|Member|New|Object)Expression|AssignmentPattern|Program|VariableDeclarator)$/;
-const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/;
+const SENTINEL_TYPE = /^(?:.+?Statement|.+?Declaration|(?:Array|ArrowFunction|Assignment|Call|Class|Function|Member|New|Object)Expression|AssignmentPattern|Program|VariableDeclarator)$/u;
+const IMPORT_TYPE = /^(?:Import|Export(?:All|Default|Named))Declaration$/u;
const has = Function.call.bind(Object.hasOwnProperty);
const READ = Symbol("read");
@@ -1126,7 +1407,7 @@ class ReferenceTracker {
* @param {object} traceMap The trace map.
* @returns {IterableIterator<{node:Node,path:string[],type:symbol,info:any}>} The iterator to iterate references.
*/
- //eslint-disable-next-line complexity, require-jsdoc
+ //eslint-disable-next-line complexity
*_iteratePropertyReferences(rootNode, path, traceMap) {
let node = rootNode;
while (!SENTINEL_TYPE.test(node.parent.type)) {
@@ -1342,6 +1623,7 @@ var index = {
getPropertyName,
getStaticValue,
getStringIfConstant,
+ hasSideEffect,
isArrowToken,
isClosingBraceToken,
isClosingBracketToken,
@@ -1363,16 +1645,20 @@ var index = {
isOpeningBraceToken,
isOpeningBracketToken,
isOpeningParenToken,
+ isParenthesized,
isSemicolonToken,
PatternMatcher,
READ,
ReferenceTracker,
};
-exports.default = index;
exports.CALL = CALL;
exports.CONSTRUCT = CONSTRUCT;
exports.ESM = ESM;
+exports.PatternMatcher = PatternMatcher;
+exports.READ = READ;
+exports.ReferenceTracker = ReferenceTracker;
+exports.default = index;
exports.findVariable = findVariable;
exports.getFunctionHeadLocation = getFunctionHeadLocation;
exports.getFunctionNameWithKind = getFunctionNameWithKind;
@@ -1380,6 +1666,7 @@ exports.getInnermostScope = getInnermostScope;
exports.getPropertyName = getPropertyName;
exports.getStaticValue = getStaticValue;
exports.getStringIfConstant = getStringIfConstant;
+exports.hasSideEffect = hasSideEffect;
exports.isArrowToken = isArrowToken;
exports.isClosingBraceToken = isClosingBraceToken;
exports.isClosingBracketToken = isClosingBracketToken;
@@ -1401,8 +1688,6 @@ exports.isNotSemicolonToken = isNotSemicolonToken;
exports.isOpeningBraceToken = isOpeningBraceToken;
exports.isOpeningBracketToken = isOpeningBracketToken;
exports.isOpeningParenToken = isOpeningParenToken;
+exports.isParenthesized = isParenthesized;
exports.isSemicolonToken = isSemicolonToken;
-exports.PatternMatcher = PatternMatcher;
-exports.READ = READ;
-exports.ReferenceTracker = ReferenceTracker;
//# sourceMappingURL=index.js.map