ast-search 0.2.0 → 0.2.2
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.
- package/README.md +15 -0
- package/build/main.js +22 -0
- package/build/search.js +23 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,21 @@ The original Vue `this` example using shorthands:
|
|
|
92
92
|
ast-search 'ObjectMethod[key.name="setup"] this'
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Optional chaining
|
|
96
|
+
|
|
97
|
+
Optional chains (`?.`) are normalized transparently — `CallExpression` and `MemberExpression` selectors match both regular and optional-chain variants:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Matches both items.map(...) and items?.map(...)
|
|
101
|
+
ast-search 'CallExpression[callee.property.name="map"]'
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The `optional` flag is preserved on matched nodes, so you can still narrow to strictly optional calls:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
ast-search 'CallExpression[optional=true]'
|
|
108
|
+
```
|
|
109
|
+
|
|
95
110
|
## Supported file types
|
|
96
111
|
|
|
97
112
|
`.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs`, `.vue`
|
package/build/main.js
CHANGED
|
@@ -93,6 +93,28 @@ const y = yargs(process.argv.slice(2))
|
|
|
93
93
|
process.exit(2);
|
|
94
94
|
}
|
|
95
95
|
}))
|
|
96
|
+
.example([
|
|
97
|
+
[
|
|
98
|
+
'$0 \'ObjectMethod[key.name="setup"] this\'',
|
|
99
|
+
"Vue: find setup() methods that use this",
|
|
100
|
+
],
|
|
101
|
+
[
|
|
102
|
+
"$0 'await' --format files",
|
|
103
|
+
"list files containing await expressions",
|
|
104
|
+
],
|
|
105
|
+
[
|
|
106
|
+
"$0 'call[callee.name=\"myFn\"]' --dir src",
|
|
107
|
+
"find all calls to myFn under src/",
|
|
108
|
+
],
|
|
109
|
+
[
|
|
110
|
+
"$0 'VariableDeclarator:has(call[callee.property.name=\"map\"]):not(:has(JSXAttribute[name.name=\"key\"]))' --format json",
|
|
111
|
+
"React: .map() calls missing a key attribute, as JSON",
|
|
112
|
+
],
|
|
113
|
+
[
|
|
114
|
+
"$0 'FunctionDeclaration[async=true]' --format files | xargs prettier --write",
|
|
115
|
+
"reformat all files containing async functions",
|
|
116
|
+
],
|
|
117
|
+
])
|
|
96
118
|
.help();
|
|
97
119
|
if (process.env.NODE_ENV !== "test") {
|
|
98
120
|
y.parse();
|
package/build/search.js
CHANGED
|
@@ -52,8 +52,31 @@ function extractFirstLine(source, node) {
|
|
|
52
52
|
export function validateSelector(selector) {
|
|
53
53
|
esquery.parse(expandShorthands(selector));
|
|
54
54
|
}
|
|
55
|
+
// Normalize Babel's optional-chain node types so esquery selectors like
|
|
56
|
+
// CallExpression[callee.property.name="map"] transparently match optional
|
|
57
|
+
// chains (foo?.bar()). The `optional` flag is preserved, so callers can
|
|
58
|
+
// still narrow to optional-only with [optional=true] or [callee.optional=true].
|
|
59
|
+
export function normalizeOptionalChaining(node) {
|
|
60
|
+
var _a;
|
|
61
|
+
if (!node || typeof node !== "object")
|
|
62
|
+
return;
|
|
63
|
+
// Capture visitor keys before renaming so we use the original type's keys.
|
|
64
|
+
const keys = (_a = VISITOR_KEYS[node.type]) !== null && _a !== void 0 ? _a : [];
|
|
65
|
+
if (node.type === "OptionalCallExpression")
|
|
66
|
+
node.type = "CallExpression";
|
|
67
|
+
else if (node.type === "OptionalMemberExpression")
|
|
68
|
+
node.type = "MemberExpression";
|
|
69
|
+
for (const key of keys) {
|
|
70
|
+
const child = node[key];
|
|
71
|
+
if (Array.isArray(child))
|
|
72
|
+
child.forEach(normalizeOptionalChaining);
|
|
73
|
+
else
|
|
74
|
+
normalizeOptionalChaining(child);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
55
77
|
export function runQuery(selector, ast, source = "", filename = "") {
|
|
56
78
|
const expanded = expandShorthands(selector);
|
|
79
|
+
normalizeOptionalChaining(ast);
|
|
57
80
|
// Cast to any: esquery expects estree.Node but Babel AST is structurally
|
|
58
81
|
// compatible; VISITOR_KEYS ensures correct traversal of Babel-specific nodes.
|
|
59
82
|
const nodes = esquery.query(ast, expanded, {
|