eslint-utils
Advanced tools
Comparing version 1.3.1 to 1.4.0
305
index.js
@@ -6,2 +6,6 @@ /*! @author Toru Nagashima <https://github.com/mysticatea> */ | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var evk = _interopDefault(require('eslint-visitor-keys')); | ||
/** | ||
@@ -746,3 +750,282 @@ * Get the innermost scope which contains a given location. | ||
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> | ||
@@ -752,3 +1035,3 @@ * See LICENSE file in root directory for full license. | ||
const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/g; | ||
const placeholder = /\$(?:[$&`']|[1-9][0-9]?)/gu; | ||
@@ -820,3 +1103,2 @@ /** @type {WeakMap<PatternMatcher, {pattern:RegExp,escaped:boolean}>} */ | ||
//eslint-disable-next-line valid-jsdoc | ||
/** | ||
@@ -897,3 +1179,2 @@ * Replace a given string by a given matcher. | ||
//eslint-disable-next-line valid-jsdoc | ||
/** | ||
@@ -912,4 +1193,4 @@ * Replace a given string. | ||
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); | ||
@@ -1135,3 +1416,3 @@ | ||
*/ | ||
//eslint-disable-next-line complexity, require-jsdoc | ||
//eslint-disable-next-line complexity | ||
*_iteratePropertyReferences(rootNode, path, traceMap) { | ||
@@ -1352,2 +1633,3 @@ let node = rootNode; | ||
getStringIfConstant, | ||
hasSideEffect, | ||
isArrowToken, | ||
@@ -1374,2 +1656,3 @@ isClosingBraceToken, | ||
isOpeningParenToken, | ||
isParenthesized, | ||
isSemicolonToken, | ||
@@ -1381,6 +1664,9 @@ PatternMatcher, | ||
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; | ||
@@ -1393,2 +1679,3 @@ exports.getFunctionHeadLocation = getFunctionHeadLocation; | ||
exports.getStringIfConstant = getStringIfConstant; | ||
exports.hasSideEffect = hasSideEffect; | ||
exports.isArrowToken = isArrowToken; | ||
@@ -1415,6 +1702,4 @@ exports.isClosingBraceToken = isClosingBraceToken; | ||
exports.isOpeningParenToken = isOpeningParenToken; | ||
exports.isParenthesized = isParenthesized; | ||
exports.isSemicolonToken = isSemicolonToken; | ||
exports.PatternMatcher = PatternMatcher; | ||
exports.READ = READ; | ||
exports.ReferenceTracker = ReferenceTracker; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "eslint-utils", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "Utilities for ESLint plugins.", | ||
@@ -8,20 +8,26 @@ "engines": { | ||
}, | ||
"sideEffects": false, | ||
"main": "index", | ||
"module": "index.mjs", | ||
"files": [ | ||
"index.*" | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"eslint-visitor-keys": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"@mysticatea/eslint-plugin": "^5.0.1", | ||
"@mysticatea/eslint-plugin": "^10.0.3", | ||
"codecov": "^3.0.2", | ||
"eslint": "^5.0.1", | ||
"dot-prop": "^4.2.0", | ||
"eslint": "^5.16.0", | ||
"esm": "^3.0.55", | ||
"espree": "^4.0.0", | ||
"espree": "^5.0.1", | ||
"mocha": "^5.2.0", | ||
"nyc": "^12.0.2", | ||
"nyc": "^13.0.1", | ||
"opener": "^1.4.3", | ||
"rimraf": "^2.6.2", | ||
"rollup": "^0.62.0", | ||
"rollup": "^1.16.7", | ||
"rollup-plugin-sourcemaps": "^0.4.2", | ||
"vuepress": "github:mysticatea/vuepress#skip-waiting" | ||
"vuepress": "^0.14.4", | ||
"warun": "^1.0.0" | ||
}, | ||
@@ -42,3 +48,3 @@ "scripts": { | ||
"prewatch": "npm run -s clean", | ||
"watch": "mocha --require esm --reporter dot --watch --growl \"test/*.js\"" | ||
"watch": "warun \"{src,test}/**/*.js\" -- nyc --reporter lcov mocha --reporter dot \"test/*.js\"" | ||
}, | ||
@@ -45,0 +51,0 @@ "repository": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
293507
3023
1
14
+ Addedeslint-visitor-keys@^1.0.0
+ Addedeslint-visitor-keys@1.3.0(transitive)