ast-search 0.2.1 → 0.2.3
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 +5 -0
- package/build/search.js +23 -0
- package/package.json +2 -2
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
|
@@ -16,10 +16,13 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
16
16
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
17
|
};
|
|
18
18
|
import yargs from "yargs/yargs";
|
|
19
|
+
import { createRequire } from "module";
|
|
19
20
|
import { walkRepoFiles } from "./walk.js";
|
|
20
21
|
import { getAstFromPath } from "./file.js";
|
|
21
22
|
import { runQuery, validateSelector } from "./search.js";
|
|
22
23
|
import { formatMatches } from "./output.js";
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
const { version } = require("../package.json");
|
|
23
26
|
export function searchRepo(selector, dir) {
|
|
24
27
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
28
|
var _a, e_1, _b, _c;
|
|
@@ -115,6 +118,8 @@ const y = yargs(process.argv.slice(2))
|
|
|
115
118
|
"reformat all files containing async functions",
|
|
116
119
|
],
|
|
117
120
|
])
|
|
121
|
+
.version(version)
|
|
122
|
+
.alias("version", "V")
|
|
118
123
|
.help();
|
|
119
124
|
if (process.env.NODE_ENV !== "test") {
|
|
120
125
|
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, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ast-search",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"scripts": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"license": "ISC",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "https://github.com/shiplet/ast-search.git"
|
|
25
|
+
"url": "https://github.com/willey-shiplet/ast-search.git"
|
|
26
26
|
},
|
|
27
27
|
"packageManager": "pnpm@10.33.0",
|
|
28
28
|
"dependencies": {
|