eslint-ast-utils ![Build Status](https://travis-ci.org/jfmengels/eslint-ast-utils.svg?branch=master)
Utility library to manipulate ASTs for ESLint projects
Install
$ npm install --save eslint-ast-utils
Usage
const astUtils = require('eslint-ast-utils');
API
astUtils.isStaticRequire(node)
Checks whether node
is a call to CommonJS's require
function.
Returns true
if and only if:
node
is a CallExpression
node
's callee is an Identifier
named require
node
has exactly 1 Literal
argument whose value is a string
Example:
require('lodash');
require(foo);
foo('lodash');
Usage example:
function create(context) {
return {
CallExpression(node) {
if (astUtils.isStaticRequire(node)) {
context.report({
node: node,
message: 'Use import syntax rather than `require`'
});
}
}
};
}
astUtils.getRequireSource(node)
Gets the source of a require()
call. If node
is not a require
call (in the definition of isStaticRequire
), it will return undefined
.
Example:
require('lodash');
require('./foo');
Usage example:
function create(context) {
return {
CallExpression(node) {
if (astUtils.isStaticRequire(node) && astUtils.getRequireSource(node) === 'underscore') {
context.report({
node: node,
message: 'Use `lodash` instead of `underscore`'
});
}
}
};
}
astUtils.containsIdentifier(name, node)
Checks if there is a reference to a variable named name
inside of node
.
Returns true if and only if:
- There is an
Identifier
named name
inside of node
- That
Identifier
is a variable (i.e. not a static property name for instance) - That
Identifier
does not reference a different variable named name
introduced in a sub-scope of node
.
Example:
foo(a);
function foo(fn) {
return function(a) {
return fn(a);
};
}
Usage example:
function create(context) {
return {
FunctionDeclaration(node) {
node.params.forEach(param => {
if (param.type === 'Identifier' && !astUtils.containsIdentifier(param.name, node.body)) {
context.report({
node: node,
message: `${name} is never used`
});
}
});
}
};
}
astUtils.someContainIdentifier(name, nodes)
Checks if there is a reference to a variable named name
inside any node of the nodes
array. Will return false
if nodes
is not an array.
This is a shorthand version of containsIdentifier
that works for arrays. The following are equivalent:
[node1, node2, node3].some(node => astUtils.containsIdentifier('a', node));
astUtils.someContainIdentifier('a', [node1, node2, node3]);
astUtils.getPropertyName(node)
Get the name of a MemberExpression
's property. Returns:
- a
string
if the property is accessed through dot notation. - a
string
if the property is accessed through brackets and is a string. - a
number
if the property is accessed through brackets and is a number. undefined
if node
is not a MemberExpression
undefined
if the property name is a hard to compute expression.
Example:
foo.bar
foo['bar']
foo[bar]
foo[0]
foo[null]
foo[undefined]
Usage example:
function create(context) {
return {
MemberExpression(node) {
if (astUtils.getPropertyName(node).startsWith('_')) {
context.report({
node: node,
message: 'Don\'t access "private" fields'
});
}
}
};
}
astUtils.computeStaticExpression(node)
Get the value of an expression that can be statically computed, i.e. without variables references or expressions too complex.
Returns:
undefined
if the value could not be statically computed.- An object with a
value
property containing the computed value.
Example:
foo
42
'foo'
undefined
null
1 + 2 - 4 + (-1)
true ? 1 : 2
`foo ${'bar'}`
Usage example:
function create(context) {
return {
TemplateLiteral(node) {
const expression = astUtils.computeStaticExpression(node);
if (expression) {
context.report({
node: node,
message: `You can replace this template literal by the regular string '${expression.value}'.`
});
}
}
};
}
astUtils.isPromise(node)
Checks whether node
is a Promise.
Returns true
if and only if node
is one of the following:
- a call of an expression's
then
or catch
properties - a call to a property of
Promise
(except cancel
, promisify
, promisifyAll
and is
) - a call to
new Promise
If node
uses unknown properties of a value that would be considered a Promise, node
itself would not be considered as a Promise.
Example:
foo.then(fn);
foo.catch(fn);
foo.then(fn).catch(fn);
foo.then(fn).isFulfilled(fn);
Promise.resolve(value);
Promise.reject(value);
Promise.race(promises);
Promise.all(promises);
Promise.map(promises, fn);
new Promise(fn);
new Promise.resolve(value);
Usage example:
function create(context) {
function reportIfPromise(node) {
if (astUtils.isPromise(node)) {
context.report({
node: node,
message: 'Prefer using async/await'
});
}
}
return {
CallExpression: reportIfPromise,
NewExpression: reportIfPromise
};
}
astUtils.isFunctionExpression(node)
Checks whether node
is a function expression or an arrow function expression (not a function declaration).
If node
uses unknown properties of a value that would be considered a Promise, node
itself would not be considered as a Promise.
Example:
(function foo() {})
() => {}
function foo() {}
Usage example:
function create(context) {
return {
CallExpression(node) {
if (node.callee.type === 'Identifier'
&& node.callee.name === 'test'
&& !astUtils.isFunctionExpression(node.arguments[0])
&& !astUtils.isFunctionExpression(node.arguments[1])
) {
context.report({
node: node,
message: 'You need to pass a function to test()'
});
}
}
};
}
License
MIT © Jeroen Engels