rkirov / matscha

JS/TS AST matching tool

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

maTScha

Node.js CI

A library for performing syntactic (AST-based) matches for JS and TS.

How to use a CLI tool

Basic usage is:

node matscha 'matcher' file1 file2 ...

The matcher is matched against each node and the fullText of the matching node is printed.

Examples

  • match all trivial equality checks - _ === _
  • match all ternary expessions - _1 ? _2 : _3
  • match some function call when called with 0 as second arg - f(_arg1, 0, _arg2)

How to use as library

Basic matching is performed with createMatcher and match. Since this is AST based white-space and comments are ignored.

const m = createMatcher(`a + b`);
match(m, `a + b`).success  // true
match(m, `a + /* don't forget b */ b`).success  // true
match(m, `a * b`).success  // false

The matcher text can be any valid JavaScript or TypeScript text. Every token is interpreted to only match itself, except symbols that start with _. Such symbols create capture variables. Such variables match every expression, but the match has to be consistent on every recurring mention in the matcher.

const m = createMatcher(`_ + _`);
match(m, `a + a`).success  // true
match(m, `a + b`).success  // false
match(m, `(a + b) + (a + b)`).success  // true

--

The captures made during a successful match can be accessed by match(...).captures.

Replace

Matches can be used together with replacements. The captured variables are accessible using the same names.

const m = createMatcher(`_ + _`);
after = replace(m, `2 * _`, before); 

BEFORE
1 + 1
f(1) + f(1)

AFTER
2 * 1
2 * f(1) 

TODO: not implemented because I need a library to swap AST nodes and reprint the rest.

Problems

  • Does not make use of type info or module/symbol resolution. It would be nice to be able to match all API calls even if they are renamed through import/export or aliases.

  • Currently, we rely on structural recursion using ts.forEachChild which is not perfect as it ignores names of properties we recurse into. I can imagine cases where

  • Need some escaping mechanism for actual variables that use underscores to be used in the matcher.

  • Statement matching needs a differnt mechanism. For example, function() {...} to () => {...} is hard to write now.

Reference

Pronunciation

You can just say matcha.

About

JS/TS AST matching tool

License:Apache License 2.0


Languages

Language:JavaScript 51.8%Language:TypeScript 48.2%