ESLint now supports many different types of AST selectors

ESLint AST selectors just got super powers 👍

Vítor Balocco
DailyJS
Published in
3 min readMar 17, 2017

--

With the new release of ESLint (v3.18.0), rule AST selectors just got super powers!

Previously, selectors were limited to matching against single node types. For example, if you were creating a custom ESLint rule, you could match against all FunctionDeclaration nodes like this:

https://gist.github.com/vitorbal/dfabb2fda24cd47e3d7986a215749b01#file-eslint-ast-selectors-1-js

But if you wanted to match, for example, againstFunctionDeclaration nodes that have more than three parameters, you had to first match against all FunctionDeclaration nodes, and then filter them out inside your callback:

https://gist.github.com/vitorbal/dfabb2fda24cd47e3d7986a215749b01#file-eslint-ast-selectors-2-js

Starting with version 3.18.0, ESLint now supports many different types of AST selectors. Here are just a few:

  • by attribute ([attr="foo"])
  • by first child (:first-child)
  • by descendant (FunctionExpression ReturnStatement)
  • by adjacent sibling (VariableDeclaration ~ VariableDeclaration)
  • by “classes” of AST nodes (:function, for all "function” types of nodes, such as FunctionExpression, FunctionDeclaration, ArrowFunctionExpression)
  • by negation (:not(ForStatement))
  • by matches-any, to match multiple selectors (:matches(:first-child, :last-child))

For a full list of supported selectors, see the official documentation.

With the new selectors support, the previous example can be greatly simplified:

https://gist.github.com/vitorbal/dfabb2fda24cd47e3d7986a215749b01#file-eslint-ast-selectors-3-js

That’s it! Now our function will only be called for FunctionDeclaration nodes that have more than 3 parameters.

Another great use of the new selectors feature is in combination with the no-restricted-syntax rule, which just became insanely more powerful. Here are just a few examples:

Disallow usage of fdescribe and fit in your tests:

"no-restricted-syntax": [
"error",
"CallExpression[callee.name='fdescribe']",
"CallExpression[callee.name='fit']"
]

Enforce that calls to setTimeout always have two arguments:

"no-restricted-syntax": [
"error",
"CallExpression[callee.name='setTimeout'][arguments.length!=2]"
]

My favorite part of the new selector support is how much boilerplate can be cleaned up from some rules thanks to it.

Here’s just a few examples of refactorings the team did on some of the core rules, thanks to this feature:

Thanks for reading! I hope you liked learning more about the brand-new AST selector support f0r ESLint!

--

--