yuku-analyzer 0.5.39 → 0.5.42
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 +22 -0
- package/decode.js +20 -49
- package/index.d.ts +0 -5
- package/module.js +0 -6
- package/package.json +13 -13
package/README.md
CHANGED
|
@@ -66,6 +66,28 @@ module.resolve("name") // scope-chain lookup, like the engine does at runtime
|
|
|
66
66
|
|
|
67
67
|
Node identity is exact: the node you reach by walking `module.ast` and the node a semantic query returns are the same JavaScript object, so `===` always works.
|
|
68
68
|
|
|
69
|
+
## Editing the AST
|
|
70
|
+
|
|
71
|
+
That identity is the payoff. Because the `node` on a symbol or reference _is_ the AST node, a refactor is a plain assignment, and [`yuku-codegen`](https://www.npmjs.com/package/yuku-codegen) prints the mutated tree back to source. No visitor to register, no separate model to translate back.
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
import { print } from "yuku-codegen";
|
|
75
|
+
|
|
76
|
+
const m = analyzer.addFile("util.ts", `const tmp = load();\nexport const data = tmp.value + tmp.size;`);
|
|
77
|
+
const tmp = m.rootScope.find("tmp");
|
|
78
|
+
tmp.declarations[0] === m.ast.body[0].declarations[0].id; // true, literally the same node
|
|
79
|
+
|
|
80
|
+
tmp.declarations[0].name = "raw"; // rename the binding
|
|
81
|
+
for (const ref of tmp.references) ref.node.name = "raw"; // and every resolved use
|
|
82
|
+
|
|
83
|
+
// across files, analyzer.referencesOf(symbol) hands back these same live nodes for every use
|
|
84
|
+
print(m.ast).code;
|
|
85
|
+
// const raw = load();
|
|
86
|
+
// export const data = raw.value + raw.size;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The uses come from resolved references, not a name search, so a shadowing inner `tmp` is left untouched: the rename only reaches the identifiers that actually bind to this symbol.
|
|
90
|
+
|
|
69
91
|
## Walking with semantic context
|
|
70
92
|
|
|
71
93
|
`module.walk` is a typed visitor walk where every handler also receives the current scope, symbol, and reference. No manual scope tracking, ever:
|
package/decode.js
CHANGED
|
@@ -619,15 +619,14 @@ function decode(buffer, source) {
|
|
|
619
619
|
extraCount = _u32[1],
|
|
620
620
|
spLen = _u32[2];
|
|
621
621
|
const commentCount = _u32[4],
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
progIdx = _u32[8];
|
|
622
|
+
diagCount = _u32[6],
|
|
623
|
+
progIdx = _u32[7];
|
|
625
624
|
const attachedCommentCount = _u32[5];
|
|
626
|
-
const _flags = _u32[
|
|
625
|
+
const _flags = _u32[8];
|
|
627
626
|
const _isTs = !!(_flags & 1);
|
|
628
627
|
const _attached = !!(_flags & 2);
|
|
629
|
-
const _firstNa = _u32[
|
|
630
|
-
const _nodesOff =
|
|
628
|
+
const _firstNa = _u32[9];
|
|
629
|
+
const _nodesOff = 40;
|
|
631
630
|
const eOff = _nodesOff + nodeCount * 48;
|
|
632
631
|
const _extraBase = eOff >> 2;
|
|
633
632
|
const _spOff = eOff + extraCount * 4;
|
|
@@ -670,19 +669,20 @@ function decode(buffer, source) {
|
|
|
670
669
|
if (s === e) return "";
|
|
671
670
|
if (s >= _srcLen) return _poolDecode(s, e);
|
|
672
671
|
if (e <= _firstNa) return _src.slice(s, e);
|
|
673
|
-
|
|
674
|
-
return _src.slice(ss, pm[e - _firstNa]);
|
|
672
|
+
return _src.slice(s < _firstNa ? s : pm[s - _firstNa], pm[e - _firstNa]);
|
|
675
673
|
};
|
|
676
674
|
function nodeArr(s, len) {
|
|
677
|
-
const r =
|
|
678
|
-
|
|
675
|
+
const r = [];
|
|
676
|
+
const base = _extraBase + s;
|
|
677
|
+
for (let j = 0; j < len; j++) r.push(node(_u32[base + j]));
|
|
679
678
|
return r;
|
|
680
679
|
}
|
|
681
680
|
function nodeArrHoles(s, len) {
|
|
682
|
-
const r =
|
|
681
|
+
const r = [];
|
|
682
|
+
const base = _extraBase + s;
|
|
683
683
|
for (let j = 0; j < len; j++) {
|
|
684
|
-
const x = _u32[
|
|
685
|
-
r
|
|
684
|
+
const x = _u32[base + j];
|
|
685
|
+
r.push(x !== NULL ? node(x) : null);
|
|
686
686
|
}
|
|
687
687
|
return r;
|
|
688
688
|
}
|
|
@@ -722,11 +722,11 @@ function decode(buffer, source) {
|
|
|
722
722
|
return r;
|
|
723
723
|
}
|
|
724
724
|
function _decode(i) {
|
|
725
|
-
const
|
|
726
|
-
const
|
|
727
|
-
const
|
|
728
|
-
const
|
|
729
|
-
const
|
|
725
|
+
const b = (_nodesOff + i * 48) >> 2;
|
|
726
|
+
const h0 = _u32[b];
|
|
727
|
+
const tag = h0 & 255;
|
|
728
|
+
const flags = h0 >>> 16;
|
|
729
|
+
const f0 = _u32[b + 1] & 65535;
|
|
730
730
|
const f1 = _u32[b + 2], f2 = _u32[b + 3],
|
|
731
731
|
f3 = _u32[b + 4], f4 = _u32[b + 5],
|
|
732
732
|
f5 = _u32[b + 6], f6 = _u32[b + 7],
|
|
@@ -1164,8 +1164,7 @@ function decode(buffer, source) {
|
|
|
1164
1164
|
const _nodesU32 = _nodesOff >> 2;
|
|
1165
1165
|
function startOf(i) { return _p(_u32[_nodesU32 + i * 12 + 10]); }
|
|
1166
1166
|
function endOf(i) { return _p(_u32[_nodesU32 + i * 12 + 11]); }
|
|
1167
|
-
const
|
|
1168
|
-
const dOff = lsOff + lineStartsCount * 4;
|
|
1167
|
+
const dOff = _cOff + commentCount * 20;
|
|
1169
1168
|
function _decodeComments() {
|
|
1170
1169
|
const out = Array.from({ length: commentCount });
|
|
1171
1170
|
for (let j = 0; j < commentCount; j++) {
|
|
@@ -1184,20 +1183,6 @@ function decode(buffer, source) {
|
|
|
1184
1183
|
}
|
|
1185
1184
|
return out;
|
|
1186
1185
|
}
|
|
1187
|
-
function _decodeLineStarts() {
|
|
1188
|
-
const out = Array.from({ length: lineStartsCount });
|
|
1189
|
-
if (_firstNa >= _srcLen) {
|
|
1190
|
-
for (let j = 0; j < lineStartsCount; j++) {
|
|
1191
|
-
out[j] = dv.getUint32(lsOff + j * 4, true);
|
|
1192
|
-
}
|
|
1193
|
-
return out;
|
|
1194
|
-
}
|
|
1195
|
-
for (let j = 0; j < lineStartsCount; j++) {
|
|
1196
|
-
const v = dv.getUint32(lsOff + j * 4, true);
|
|
1197
|
-
out[j] = v < _firstNa ? v : (v >= _srcLen ? pm[pm.length - 1] : pm[v - _firstNa]);
|
|
1198
|
-
}
|
|
1199
|
-
return out;
|
|
1200
|
-
}
|
|
1201
1186
|
function _decodeDiagnostics() {
|
|
1202
1187
|
const out = Array.from({ length: diagCount });
|
|
1203
1188
|
let dp = dOff;
|
|
@@ -1359,11 +1344,7 @@ function decode(buffer, source) {
|
|
|
1359
1344
|
nodeScope: (i) => nodeScopes[i],
|
|
1360
1345
|
});
|
|
1361
1346
|
}
|
|
1362
|
-
let _program,
|
|
1363
|
-
function _getLineStarts() {
|
|
1364
|
-
if (_lineStarts === undefined) _lineStarts = _decodeLineStarts();
|
|
1365
|
-
return _lineStarts;
|
|
1366
|
-
}
|
|
1347
|
+
let _program, _diagnostics, _comments;
|
|
1367
1348
|
return {
|
|
1368
1349
|
get program() {
|
|
1369
1350
|
return _program !== undefined ? _program : (_program = node(progIdx));
|
|
@@ -1378,16 +1359,6 @@ function decode(buffer, source) {
|
|
|
1378
1359
|
? _diagnostics
|
|
1379
1360
|
: (_diagnostics = _decodeDiagnostics());
|
|
1380
1361
|
},
|
|
1381
|
-
get lineStarts() { return _getLineStarts(); },
|
|
1382
|
-
locOf(offset) {
|
|
1383
|
-
const ls = _getLineStarts();
|
|
1384
|
-
let lo = 0, hi = ls.length;
|
|
1385
|
-
while (lo < hi) {
|
|
1386
|
-
const mid = (lo + hi) >>> 1;
|
|
1387
|
-
if (ls[mid] <= offset) lo = mid + 1; else hi = mid;
|
|
1388
|
-
}
|
|
1389
|
-
return { line: lo, column: offset - ls[lo - 1] };
|
|
1390
|
-
},
|
|
1391
1362
|
nodeOf: node,
|
|
1392
1363
|
indexOf: (n) => _nodeIndexes.get(n),
|
|
1393
1364
|
parentIndex: (i) => _parents()[i],
|
package/index.d.ts
CHANGED
|
@@ -13,7 +13,6 @@ import type {
|
|
|
13
13
|
NodeType,
|
|
14
14
|
Program,
|
|
15
15
|
SourceLang,
|
|
16
|
-
SourceLocation,
|
|
17
16
|
SourceType,
|
|
18
17
|
WalkContext as BaseWalkContext,
|
|
19
18
|
} from "@yuku-toolchain/types";
|
|
@@ -364,10 +363,6 @@ interface Module {
|
|
|
364
363
|
readonly diagnostics: Diagnostic[];
|
|
365
364
|
/** Every comment in source order. */
|
|
366
365
|
readonly comments: Comment[];
|
|
367
|
-
/** Sorted offsets where each line begins. */
|
|
368
|
-
readonly lineStarts: number[];
|
|
369
|
-
/** Resolves an offset to a `(line, column)` pair. */
|
|
370
|
-
locOf(offset: number): SourceLocation;
|
|
371
366
|
|
|
372
367
|
/** Every lexical scope; index is the scope id. `scopes[0]` is global. */
|
|
373
368
|
readonly scopes: Scope[];
|
package/module.js
CHANGED
|
@@ -256,12 +256,6 @@ export class Module {
|
|
|
256
256
|
get comments() {
|
|
257
257
|
return this.#r.comments;
|
|
258
258
|
}
|
|
259
|
-
get lineStarts() {
|
|
260
|
-
return this.#r.lineStarts;
|
|
261
|
-
}
|
|
262
|
-
locOf(offset) {
|
|
263
|
-
return this.#r.locOf(offset);
|
|
264
|
-
}
|
|
265
259
|
|
|
266
260
|
get scopes() {
|
|
267
261
|
return (this.#scopes ??= this.#rows(Scope, this.#sem.scope.count));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yuku-analyzer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.42",
|
|
4
4
|
"description": "Full JavaScript and TypeScript semantic analysis: scopes, symbols, resolved references, closures, and cross-file module linking, computed natively in Zig and queried as plain JavaScript objects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,17 +21,17 @@
|
|
|
21
21
|
"decode.js"
|
|
22
22
|
],
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"@yuku-analyzer/binding-linux-x64-gnu": "0.5.
|
|
25
|
-
"@yuku-analyzer/binding-linux-arm64-gnu": "0.5.
|
|
26
|
-
"@yuku-analyzer/binding-linux-arm-gnu": "0.5.
|
|
27
|
-
"@yuku-analyzer/binding-linux-x64-musl": "0.5.
|
|
28
|
-
"@yuku-analyzer/binding-linux-arm64-musl": "0.5.
|
|
29
|
-
"@yuku-analyzer/binding-linux-arm-musl": "0.5.
|
|
30
|
-
"@yuku-analyzer/binding-darwin-x64": "0.5.
|
|
31
|
-
"@yuku-analyzer/binding-darwin-arm64": "0.5.
|
|
32
|
-
"@yuku-analyzer/binding-win32-x64": "0.5.
|
|
33
|
-
"@yuku-analyzer/binding-win32-arm64": "0.5.
|
|
34
|
-
"@yuku-analyzer/binding-freebsd-x64": "0.5.
|
|
24
|
+
"@yuku-analyzer/binding-linux-x64-gnu": "0.5.42",
|
|
25
|
+
"@yuku-analyzer/binding-linux-arm64-gnu": "0.5.42",
|
|
26
|
+
"@yuku-analyzer/binding-linux-arm-gnu": "0.5.42",
|
|
27
|
+
"@yuku-analyzer/binding-linux-x64-musl": "0.5.42",
|
|
28
|
+
"@yuku-analyzer/binding-linux-arm64-musl": "0.5.42",
|
|
29
|
+
"@yuku-analyzer/binding-linux-arm-musl": "0.5.42",
|
|
30
|
+
"@yuku-analyzer/binding-darwin-x64": "0.5.42",
|
|
31
|
+
"@yuku-analyzer/binding-darwin-arm64": "0.5.42",
|
|
32
|
+
"@yuku-analyzer/binding-win32-x64": "0.5.42",
|
|
33
|
+
"@yuku-analyzer/binding-win32-arm64": "0.5.42",
|
|
34
|
+
"@yuku-analyzer/binding-freebsd-x64": "0.5.42"
|
|
35
35
|
},
|
|
36
36
|
"keywords": [
|
|
37
37
|
"analyzer",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
"typescript"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@yuku-toolchain/types": "0.5.
|
|
52
|
+
"@yuku-toolchain/types": "0.5.41"
|
|
53
53
|
}
|
|
54
54
|
}
|