ast-search 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +74 -63
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,86 +1,97 @@
1
1
  # ast-search
2
2
 
3
- A (somewhat) limited-case search tool meant to facilitate large-scale refactors.
3
+ A CLI tool for searching source files using AST patterns, designed to facilitate large-scale refactors.
4
4
 
5
- Searches files for a given function or property name, and then determines whether those functions or properties contain a given expression or value.
5
+ Accepts an [esquery](https://github.com/estools/esquery) CSS-selector-style query and searches all supported files under a directory, printing each match with its file path, line, and column.
6
6
 
7
7
  ## Example
8
8
 
9
- For example, say you have a large number of VueJS single-file-components with `setup` functions that might be improperly accessing the `this.` instance of the file:
9
+ Say you have Vue SFCs with `setup()` functions that improperly access `this`:
10
10
 
11
- ```
12
- <script>
13
- ...
11
+ ```js
14
12
  export default {
15
- setup() {
16
- const store = useStore();
17
- const dynamicTestValue = computed(() => {
18
- return this.testValue
19
- })
20
- },
21
- computed: {
22
- testValue: 0
23
- }
13
+ setup() {
14
+ const value = computed(() => {
15
+ return this.testValue // shouldn't be here
16
+ })
17
+ }
24
18
  }
25
- </script>
26
19
  ```
27
20
 
28
- If you have hundreds of component files, this would be especially difficult (if not impossible) to find with a regular expression because it would require both searching across multiple lines and knowing the lexical scope of the `setup` function, which would vary widely across each file.
21
+ Find all such occurrences across your whole repo:
22
+
23
+ ```bash
24
+ ast-search 'ObjectMethod[key.name="setup"] ThisExpression'
25
+ ```
26
+
27
+ Output:
28
+
29
+ ```
30
+ src/components/Foo.vue:5:13: return this.testValue
31
+ src/components/Bar.vue:9:18: return this.otherProp
32
+ ```
29
33
 
30
34
  ## Usage
31
35
 
32
- `ast-search` leverages [ acornjs ](https://github.com/acornjs/acorn) to construct an Abstract Syntax Tree of each JavaScript file it parses, and then searches relevant paths for both the given top-level function or property as well as the desired search term.
36
+ ```
37
+ ast-search <query> [--dir <path>] [--format <fmt>]
38
+ ```
39
+
40
+ | Argument | Description | Default |
41
+ | ---------------- | -------------------------------------------------------- | ------------ |
42
+ | `<query>` | esquery selector string (see below) | required |
43
+ | `-d, --dir` | root directory to search | current dir |
44
+ | `-f, --format` | output format: `text`, `json`, or `files` | `text` |
45
+
46
+ ### Output formats
47
+
48
+ - **`text`** (default) — one match per line as `file:line:col: source`
49
+ - **`files`** — unique file paths only, one per line; useful for piping to `xargs`
50
+ - **`json`** — full match array as JSON
33
51
 
34
- For example, say the above VueJS SFC is a file at `src/components/TestValue.vue`. To search this file and determine whether the `setup` function has a `this.` expression, you'd do the following:
52
+ ## Query syntax
53
+
54
+ Queries use [esquery](https://github.com/estools/esquery) CSS selector syntax over Babel AST node types. A few examples:
35
55
 
36
56
  ```bash
37
- $ ast-search -f ./src/components/TestValue.vue --fn setup -e ThisExpression
57
+ # Find all arrow functions inside a function named "setup"
58
+ ast-search 'ObjectMethod[key.name="setup"] ArrowFunctionExpression'
59
+
60
+ # Find await expressions anywhere
61
+ ast-search 'AwaitExpression'
62
+
63
+ # Find assignments inside catch clauses
64
+ ast-search 'CatchClause AssignmentExpression'
38
65
  ```
39
66
 
40
- If it finds the expression in the function, it echoes the file path:
67
+ ### Shorthands
68
+
69
+ Common node types can be written as short keywords:
70
+
71
+ | Shorthand | Expands to |
72
+ | ---------- | --------------------------- |
73
+ | `this` | `ThisExpression` |
74
+ | `await` | `AwaitExpression` |
75
+ | `yield` | `YieldExpression` |
76
+ | `new` | `NewExpression` |
77
+ | `call` | `CallExpression` |
78
+ | `arrow` | `ArrowFunctionExpression` |
79
+ | `fn` | `FunctionExpression` |
80
+ | `member` | `MemberExpression` |
81
+ | `ternary` | `ConditionalExpression` |
82
+ | `template` | `TemplateLiteral` |
83
+ | `tagged` | `TaggedTemplateExpression` |
84
+ | `assign` | `AssignmentExpression` |
85
+ | `binary` | `BinaryExpression` |
86
+ | `logical` | `LogicalExpression` |
87
+ | `spread` | `SpreadElement` |
88
+
89
+ The original Vue `this` example using shorthands:
41
90
 
42
91
  ```bash
43
- $ ast-search -f ./src/components/TestValue.vue --fn setup -e ThisExpression
44
- ./src/components/TestValue.vue
92
+ ast-search 'ObjectMethod[key.name="setup"] this'
45
93
  ```
46
94
 
47
- ## Arguments
48
-
49
- | Flag | Definition |
50
- | ------------------ | -------------------------------------------------------------------------------------------------- |
51
- | `-f, --file` | the file path to search, relative or absolute |
52
- | `--function, fn` | the function to search; can be any variation of a function declaration or expression |
53
- | `-p, --property` | the property to search; expected to be a property on an object |
54
- | `-m, --multiple` | used for searching function calls, of which a single file may contain several |
55
- | `-e, --expression` | the type of expression to search for; must be a valid `acornjs` JavaScript expression (list below) |
56
- | `-d, --debug` | output the full Abstract Syntax Tree to a file called `output.json` |
57
-
58
- ### Supported Expressions
59
-
60
- | Expression Name | Reference | Common Operators |
61
- | ------------------------ | ----------------------------------------------------- | ----------------------------- |
62
- | ArrayExpression | begins an array expression | `[]` |
63
- | ArrowFunctionExpression | begins an arrow function in any lexical context | `() =>` |
64
- | AssignmentExpression | equals operator | `=` |
65
- | AwaitExpression | asynchronous promise resolver | `await` |
66
- | BinaryExpression | any left + right side operation | `1 + 1` |
67
- | CallExpression | function calls | `fn()` |
68
- | ChainExpression | chained property or method accessors | `store.state.someFn()` |
69
- | ConditionalExpression | ternary expression | `x ? y : z` |
70
- | FunctionExpression | named, non-assigned functions | `fn() {}` |
71
- | ImportExpression | import statements | `import x from 'y'` |
72
- | LogicalExpression | evaluates to a boolean, e.g. if statement expressions | `if (x > y)` |
73
- | MemberExpression | object member accessor | `this.theMember` |
74
- | NewExpression | `new` constructor declaration | `const x = new Item()` |
75
- | ObjectExpression | an object as referenced by its brackets | `{}` |
76
- | ParenthesizedExpression | an expression wrapped in parens | `const foo = (bar)` |
77
- | SequenceExpression | deconstructor expressions | `({...(a,b),c})` |
78
- | TaggedTemplateExpression | backtick expressions | <pre>`${test}`</pre> |
79
- | ThisExpression | this accessors | `this.someItem` |
80
- | UnaryExpression | standalone statements | ` return x + 1` (the `x + 1`) |
81
- | UpdateExpression | increments, decrements | `x++` or `--y` |
82
- | YieldExpression | yield statements in iterators | `yield x` |
83
-
84
- ## Support
85
-
86
- Currently only supports VueJS's Single File Components.
95
+ ## Supported file types
96
+
97
+ `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs`, `.vue`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ast-search",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "main": "main.js",
6
6
  "scripts": {