sh-ast 0.3.1 → 0.4.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.
- package/README.md +116 -144
- package/dist/analyze/ansi-c-escapes.d.ts +1 -1
- package/dist/analyze/ansi-c-escapes.js +1 -1
- package/dist/analyze/enumerate-commands.d.ts +11 -16
- package/dist/analyze/enumerate-commands.d.ts.map +1 -1
- package/dist/analyze/enumerate-commands.js +82 -92
- package/dist/analyze/enumerate-commands.js.map +1 -1
- package/dist/analyze/index.d.ts +3 -2
- package/dist/analyze/index.d.ts.map +1 -1
- package/dist/analyze/index.js +1 -1
- package/dist/analyze/node-helpers.d.ts +10 -21
- package/dist/analyze/node-helpers.d.ts.map +1 -1
- package/dist/analyze/node-helpers.js +16 -27
- package/dist/analyze/node-helpers.js.map +1 -1
- package/dist/analyze/resolve-argv0.d.ts +6 -6
- package/dist/analyze/resolve-argv0.js +6 -6
- package/dist/analyze/resolve-word.d.ts +7 -10
- package/dist/analyze/resolve-word.d.ts.map +1 -1
- package/dist/analyze/resolve-word.js +39 -22
- package/dist/analyze/resolve-word.js.map +1 -1
- package/dist/analyze.d.ts +3780 -397
- package/dist/errors.d.ts +6 -79
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -64
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +16 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -4
- package/dist/index.js.map +1 -1
- package/dist/sh-ast.d.ts +3503 -1027
- package/dist/syntax-errors.d.ts +56 -0
- package/dist/syntax-errors.d.ts.map +1 -0
- package/dist/syntax-errors.js +80 -0
- package/dist/syntax-errors.js.map +1 -0
- package/dist/syntax-snapshot.d.ts +47 -0
- package/dist/syntax-snapshot.d.ts.map +1 -0
- package/dist/syntax-snapshot.js +121 -0
- package/dist/syntax-snapshot.js.map +1 -0
- package/dist/syntax-wire.d.ts +31 -0
- package/dist/syntax-wire.d.ts.map +1 -0
- package/dist/syntax-wire.js +202 -0
- package/dist/syntax-wire.js.map +1 -0
- package/dist/syntax.d.ts +65 -0
- package/dist/syntax.d.ts.map +1 -0
- package/dist/syntax.js +152 -0
- package/dist/syntax.js.map +1 -0
- package/dist/wasm-instance.d.ts +5 -8
- package/dist/wasm-instance.d.ts.map +1 -1
- package/dist/wasm-instance.js +44 -47
- package/dist/wasm-instance.js.map +1 -1
- package/generated/syntax-constants.d.ts +1652 -0
- package/generated/syntax-constants.js +1384 -0
- package/generated/syntax-schema.d.ts +60 -0
- package/generated/syntax-schema.js +1740 -0
- package/generated/syntax-types.d.ts +1977 -0
- package/package.json +2 -2
- package/shim/sh-ast.wasm +0 -0
- package/dist/normalize.d.ts +0 -52
- package/dist/normalize.d.ts.map +0 -1
- package/dist/normalize.js +0 -260
- package/dist/normalize.js.map +0 -1
- package/dist/parse.d.ts +0 -50
- package/dist/parse.d.ts.map +0 -1
- package/dist/parse.js +0 -125
- package/dist/parse.js.map +0 -1
- package/dist/types.d.ts +0 -74
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/visitor-keys.d.ts +0 -21
- package/dist/visitor-keys.d.ts.map +0 -1
- package/dist/visitor-keys.js +0 -23
- package/dist/visitor-keys.js.map +0 -1
- package/dist/walk.d.ts +0 -18
- package/dist/walk.d.ts.map +0 -1
- package/dist/walk.js +0 -40
- package/dist/walk.js.map +0 -1
- package/generated/child-type-schema.d.ts +0 -14
- package/generated/child-type-schema.js +0 -188
- package/generated/node-types.d.ts +0 -1002
- package/generated/position-fields.d.ts +0 -21
- package/generated/position-fields.js +0 -50
- package/generated/visitor-keys.d.ts +0 -11
- package/generated/visitor-keys.js +0 -50
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sh-ast",
|
|
3
|
-
"description": "Synchronous
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "Synchronous, faithfully typed mvdan/sh syntax records and parsing via WebAssembly.",
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"author": "Mike North <michael.l.north@gmail.com>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
package/shim/sh-ast.wasm
CHANGED
|
Binary file
|
package/dist/normalize.d.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { ShNode } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* A JSON value as produced by `JSON.parse`.
|
|
4
|
-
*
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
8
|
-
[key: string]: JsonValue;
|
|
9
|
-
};
|
|
10
|
-
/**
|
|
11
|
-
* Builds a byte-offset -> UTF-16-index lookup for `text`. mvdan/sh reports
|
|
12
|
-
* byte offsets; ESLint (and JavaScript strings generally) index by UTF-16
|
|
13
|
-
* code unit, so every position needs this conversion. Throws if asked to
|
|
14
|
-
* convert an offset that does not fall on a UTF-8 code-point boundary — an
|
|
15
|
-
* invariant every offset the parser emits must satisfy (see
|
|
16
|
-
* design/ARCHITECTURE.md's "Serialization contract").
|
|
17
|
-
*
|
|
18
|
-
* @internal
|
|
19
|
-
*/
|
|
20
|
-
export declare function makeByteToUtf16(text: string): (byteOffset: number) => number;
|
|
21
|
-
/**
|
|
22
|
-
* Converts a byte offset and the 1-based line mvdan/sh already computed for
|
|
23
|
-
* it into a 1-based, UTF-16-code-unit column — the same conversion
|
|
24
|
-
* `normalize` applies to every node's `loc.start`/`loc.end` below, extracted
|
|
25
|
-
* so a parse error's reported position (see `errors.ts`'s
|
|
26
|
-
* `ShParseErrorInfo`) can use the identical algorithm instead of the raw
|
|
27
|
-
* byte-counting column mvdan/sh itself reports. See design/ARCHITECTURE.md's
|
|
28
|
-
* "Byte→UTF-16 conversion".
|
|
29
|
-
*
|
|
30
|
-
* @internal
|
|
31
|
-
*/
|
|
32
|
-
export declare function toUtf16Column(text: string, byteOffset: number, line: number): number;
|
|
33
|
-
/**
|
|
34
|
-
* Normalizes mvdan/sh's typedjson tree into the shape ESLint expects: every
|
|
35
|
-
* node gets `type`, `range` (UTF-16), `loc` (1-based, UTF-16 columns), and
|
|
36
|
-
* every other field copied over with its name lowercased. See
|
|
37
|
-
* design/ARCHITECTURE.md's "Normalized node shape".
|
|
38
|
-
*
|
|
39
|
-
* Three of mvdan/sh's struct types — `Slice`, `Replace`, `Expansion`, all
|
|
40
|
-
* reachable only via `ParamExp.Slice`/`.Repl`/`.Exp` — do not implement
|
|
41
|
-
* `syntax.Node` (no `Pos()`/`End()`), so typedjson never gives them a `Pos`/
|
|
42
|
-
* `End` pair, let alone a `Type` discriminator. They still hold real child
|
|
43
|
-
* nodes (`Slice.Offset`/`.Length`, `Replace.Orig`/`.With`,
|
|
44
|
-
* `Expansion.Word`), so dropping them would silently lose that subtree (see
|
|
45
|
-
* issue #13 — `${USER:-nobody}`'s `nobody` literal). This function
|
|
46
|
-
* synthesizes a `type`/`range`/`loc` for these from their own children's
|
|
47
|
-
* already-computed positions instead, via `walkSynthetic` below.
|
|
48
|
-
*
|
|
49
|
-
* @internal
|
|
50
|
-
*/
|
|
51
|
-
export declare function normalize(root: JsonValue, text: string): ShNode;
|
|
52
|
-
//# sourceMappingURL=normalize.d.ts.map
|
package/dist/normalize.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAY,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBnD;;;;GAIG;AACH,MAAM,MAAM,SAAS,GACnB,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAoEhF;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAsB5E;AAkBD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsI/D"}
|
package/dist/normalize.js
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import { deepFreeze } from './deep-freeze.js';
|
|
2
|
-
import { CHILD_TYPE_SCHEMA } from '../generated/child-type-schema.js';
|
|
3
|
-
import { POSITION_FIELDS } from '../generated/position-fields.js';
|
|
4
|
-
/**
|
|
5
|
-
* Frozen (including each per-type field record) so immutability of this
|
|
6
|
-
* shared, module-scoped table is a contract, not just a convention any
|
|
7
|
-
* importer happens to honor — mirrors {@link visitorKeys}'s freezing in
|
|
8
|
-
* `visitor-keys.ts`.
|
|
9
|
-
*/
|
|
10
|
-
const FROZEN_CHILD_TYPE_SCHEMA = deepFreeze(CHILD_TYPE_SCHEMA);
|
|
11
|
-
/**
|
|
12
|
-
* Frozen (including each per-type field-name array), same rationale as
|
|
13
|
-
* {@link FROZEN_CHILD_TYPE_SCHEMA} above.
|
|
14
|
-
*/
|
|
15
|
-
const FROZEN_POSITION_FIELDS = deepFreeze(POSITION_FIELDS);
|
|
16
|
-
/**
|
|
17
|
-
* `Pos`/`End` are synthesized top-level keys every raw node carries (see
|
|
18
|
-
* `shim/internal/nodeencode/encode.go`'s `posField`/`endField`) — never a
|
|
19
|
-
* literal Go struct field, so they're checked directly rather than through
|
|
20
|
-
* {@link FROZEN_POSITION_FIELDS} (which is keyed by node *type*, and these
|
|
21
|
-
* two keys are universal, not type-specific).
|
|
22
|
-
*/
|
|
23
|
-
const UNIVERSAL_POSITION_KEYS = new Set(['Pos', 'End']);
|
|
24
|
-
/**
|
|
25
|
-
* Reports whether `key` on a raw node of type `type` holds a position
|
|
26
|
-
* (`syntax.Pos`) rather than child/scalar data — driving the "drop this
|
|
27
|
-
* field" decision `buildFields` below makes, in place of the bare-name
|
|
28
|
-
* `POS_KEYS` denylist this replaced (see issue #8, "replace the bare-name
|
|
29
|
-
* POS_KEYS denylist with generated per-(type,field) position data").
|
|
30
|
-
*
|
|
31
|
-
* Scoping the check per (type, key) — via the generated
|
|
32
|
-
* {@link FROZEN_POSITION_FIELDS} table, itself derived from mvdan/sh's own
|
|
33
|
-
* struct definitions by `tools/gen-visitor-keys` — is what closes the
|
|
34
|
-
* collision class a single global bare-name set could never close: mvdan/sh
|
|
35
|
-
* reuses field names across unrelated struct shapes. `Do` is both
|
|
36
|
-
* `WhileClause.DoPos Pos` (a position) and `ForClause.Do []*Stmt` (the loop
|
|
37
|
-
* body — real data, issue #2); `Dollar` is both `ParamExp.Dollar Pos` and
|
|
38
|
-
* `SglQuoted.Dollar`/`DblQuoted.Dollar bool` (the `$'...'`/`$"..."` ANSI-C
|
|
39
|
-
* quoting flag — real data, issue #3); `Select` (`ForClause.Select bool`),
|
|
40
|
-
* `Until` (`WhileClause.Until bool`), and `Unsigned`
|
|
41
|
-
* (`ArithmExp`/`ArithmCmd.Unsigned bool`) were never positions in *any*
|
|
42
|
-
* mvdan/sh v3.13.1 struct at all, yet the old bare-name denylist dropped
|
|
43
|
-
* them unconditionally regardless of node type.
|
|
44
|
-
*/
|
|
45
|
-
function isPositionField(type, key) {
|
|
46
|
-
if (UNIVERSAL_POSITION_KEYS.has(key))
|
|
47
|
-
return true;
|
|
48
|
-
return (FROZEN_POSITION_FIELDS[type] ?? []).includes(key);
|
|
49
|
-
}
|
|
50
|
-
function isJsonObject(value) {
|
|
51
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
52
|
-
}
|
|
53
|
-
function isRawPos(value) {
|
|
54
|
-
if (!isJsonObject(value))
|
|
55
|
-
return false;
|
|
56
|
-
const keys = Object.keys(value);
|
|
57
|
-
return (keys.length === 3 &&
|
|
58
|
-
typeof value.Offset === 'number' &&
|
|
59
|
-
typeof value.Line === 'number' &&
|
|
60
|
-
typeof value.Col === 'number');
|
|
61
|
-
}
|
|
62
|
-
function isRawNode(value) {
|
|
63
|
-
return isJsonObject(value) && isRawPos(value.Pos) && isRawPos(value.End);
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Builds a byte-offset -> UTF-16-index lookup for `text`. mvdan/sh reports
|
|
67
|
-
* byte offsets; ESLint (and JavaScript strings generally) index by UTF-16
|
|
68
|
-
* code unit, so every position needs this conversion. Throws if asked to
|
|
69
|
-
* convert an offset that does not fall on a UTF-8 code-point boundary — an
|
|
70
|
-
* invariant every offset the parser emits must satisfy (see
|
|
71
|
-
* design/ARCHITECTURE.md's "Serialization contract").
|
|
72
|
-
*
|
|
73
|
-
* @internal
|
|
74
|
-
*/
|
|
75
|
-
export function makeByteToUtf16(text) {
|
|
76
|
-
const map = new Map();
|
|
77
|
-
let byte = 0;
|
|
78
|
-
map.set(0, 0);
|
|
79
|
-
for (let i = 0; i < text.length;) {
|
|
80
|
-
const codePoint = text.codePointAt(i);
|
|
81
|
-
// codePointAt(i) is always defined for i < text.length; this guards the
|
|
82
|
-
// type only (strict null checks require it, not a reachable branch).
|
|
83
|
-
if (codePoint === undefined)
|
|
84
|
-
break;
|
|
85
|
-
const units = codePoint > 0xffff ? 2 : 1;
|
|
86
|
-
const bytes = codePoint <= 0x7f ? 1 : codePoint <= 0x7ff ? 2 : codePoint <= 0xffff ? 3 : 4;
|
|
87
|
-
byte += bytes;
|
|
88
|
-
i += units;
|
|
89
|
-
map.set(byte, i);
|
|
90
|
-
}
|
|
91
|
-
return (byteOffset) => {
|
|
92
|
-
const value = map.get(byteOffset);
|
|
93
|
-
if (value === undefined) {
|
|
94
|
-
throw new Error(`byte offset ${String(byteOffset)} is not a UTF-8 code point boundary`);
|
|
95
|
-
}
|
|
96
|
-
return value;
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* The UTF-16 index of the start of each 1-based source line (`lineStarts[0]`
|
|
101
|
-
* is line 1's start, always `0`).
|
|
102
|
-
*/
|
|
103
|
-
function computeLineStarts(text) {
|
|
104
|
-
const lineStarts = [0];
|
|
105
|
-
for (let i = 0; i < text.length; i++) {
|
|
106
|
-
if (text[i] === '\n')
|
|
107
|
-
lineStarts.push(i + 1);
|
|
108
|
-
}
|
|
109
|
-
return lineStarts;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Converts a byte offset and the 1-based line mvdan/sh already computed for
|
|
113
|
-
* it into a 1-based, UTF-16-code-unit column — the same conversion
|
|
114
|
-
* `normalize` applies to every node's `loc.start`/`loc.end` below, extracted
|
|
115
|
-
* so a parse error's reported position (see `errors.ts`'s
|
|
116
|
-
* `ShParseErrorInfo`) can use the identical algorithm instead of the raw
|
|
117
|
-
* byte-counting column mvdan/sh itself reports. See design/ARCHITECTURE.md's
|
|
118
|
-
* "Byte→UTF-16 conversion".
|
|
119
|
-
*
|
|
120
|
-
* @internal
|
|
121
|
-
*/
|
|
122
|
-
export function toUtf16Column(text, byteOffset, line) {
|
|
123
|
-
const index = makeByteToUtf16(text)(byteOffset);
|
|
124
|
-
const lineStart = computeLineStarts(text)[line - 1] ?? 0;
|
|
125
|
-
return index - lineStart + 1;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Normalizes mvdan/sh's typedjson tree into the shape ESLint expects: every
|
|
129
|
-
* node gets `type`, `range` (UTF-16), `loc` (1-based, UTF-16 columns), and
|
|
130
|
-
* every other field copied over with its name lowercased. See
|
|
131
|
-
* design/ARCHITECTURE.md's "Normalized node shape".
|
|
132
|
-
*
|
|
133
|
-
* Three of mvdan/sh's struct types — `Slice`, `Replace`, `Expansion`, all
|
|
134
|
-
* reachable only via `ParamExp.Slice`/`.Repl`/`.Exp` — do not implement
|
|
135
|
-
* `syntax.Node` (no `Pos()`/`End()`), so typedjson never gives them a `Pos`/
|
|
136
|
-
* `End` pair, let alone a `Type` discriminator. They still hold real child
|
|
137
|
-
* nodes (`Slice.Offset`/`.Length`, `Replace.Orig`/`.With`,
|
|
138
|
-
* `Expansion.Word`), so dropping them would silently lose that subtree (see
|
|
139
|
-
* issue #13 — `${USER:-nobody}`'s `nobody` literal). This function
|
|
140
|
-
* synthesizes a `type`/`range`/`loc` for these from their own children's
|
|
141
|
-
* already-computed positions instead, via `walkSynthetic` below.
|
|
142
|
-
*
|
|
143
|
-
* @internal
|
|
144
|
-
*/
|
|
145
|
-
export function normalize(root, text) {
|
|
146
|
-
const toUtf16 = makeByteToUtf16(text);
|
|
147
|
-
const lineStarts = computeLineStarts(text);
|
|
148
|
-
const toLoc = (pos) => {
|
|
149
|
-
const index = toUtf16(pos.Offset);
|
|
150
|
-
const lineStart = lineStarts[pos.Line - 1] ?? 0;
|
|
151
|
-
const column = index - lineStart + 1;
|
|
152
|
-
return { line: pos.Line, column, index };
|
|
153
|
-
};
|
|
154
|
-
const startOf = (node) => ({
|
|
155
|
-
index: node.range[0],
|
|
156
|
-
line: node.loc.start.line,
|
|
157
|
-
column: node.loc.start.column,
|
|
158
|
-
});
|
|
159
|
-
const endOf = (node) => ({
|
|
160
|
-
index: node.range[1],
|
|
161
|
-
line: node.loc.end.line,
|
|
162
|
-
column: node.loc.end.column,
|
|
163
|
-
});
|
|
164
|
-
const earlier = (a, b) => (a.index <= b.index ? a : b);
|
|
165
|
-
const later = (a, b) => (a.index >= b.index ? a : b);
|
|
166
|
-
/**
|
|
167
|
-
* Builds `node`'s own lowercased field map, recursing into schema-declared
|
|
168
|
-
* children (real or synthetic). `fallback` is the nearest enclosing *real*
|
|
169
|
-
* node's start/end — used only if a synthetic child ends up with no
|
|
170
|
-
* positioned children of its own to derive a span from (see
|
|
171
|
-
* `walkSynthetic`).
|
|
172
|
-
*/
|
|
173
|
-
function buildFields(node, type, fallback) {
|
|
174
|
-
const schema = FROZEN_CHILD_TYPE_SCHEMA[type] ?? {};
|
|
175
|
-
const out = {};
|
|
176
|
-
const children = [];
|
|
177
|
-
const resolve = (value, childType) => {
|
|
178
|
-
if (isRawNode(value)) {
|
|
179
|
-
const child = walkNode(value, childType);
|
|
180
|
-
children.push(child);
|
|
181
|
-
return child;
|
|
182
|
-
}
|
|
183
|
-
if (childType !== null && isJsonObject(value)) {
|
|
184
|
-
const child = walkSynthetic(value, childType, fallback);
|
|
185
|
-
children.push(child);
|
|
186
|
-
return child;
|
|
187
|
-
}
|
|
188
|
-
return value;
|
|
189
|
-
};
|
|
190
|
-
for (const [key, value] of Object.entries(node)) {
|
|
191
|
-
if (key === 'Type' || isPositionField(type, key))
|
|
192
|
-
continue;
|
|
193
|
-
const outKey = key.toLowerCase();
|
|
194
|
-
const childType = schema[key] ?? null;
|
|
195
|
-
if (Array.isArray(value)) {
|
|
196
|
-
out[outKey] = value.map((item) => resolve(item, childType));
|
|
197
|
-
}
|
|
198
|
-
else if (isRawNode(value) || (childType !== null && isJsonObject(value))) {
|
|
199
|
-
out[outKey] = resolve(value, childType);
|
|
200
|
-
}
|
|
201
|
-
else if (!isRawPos(value)) {
|
|
202
|
-
out[outKey] = value;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return { fields: out, children };
|
|
206
|
-
}
|
|
207
|
-
function walkNode(node, staticType) {
|
|
208
|
-
const rawType = node.Type;
|
|
209
|
-
const type = typeof rawType === 'string' ? rawType : staticType;
|
|
210
|
-
if (type === null) {
|
|
211
|
-
throw new Error(`node without resolvable type: ${JSON.stringify(node).slice(0, 120)}`);
|
|
212
|
-
}
|
|
213
|
-
if (!isRawPos(node.Pos) || !isRawPos(node.End)) {
|
|
214
|
-
throw new Error(`node of type ${type} is missing Pos/End`);
|
|
215
|
-
}
|
|
216
|
-
const start = toLoc(node.Pos);
|
|
217
|
-
const end = toLoc(node.End);
|
|
218
|
-
const { fields } = buildFields(node, type, { start, end });
|
|
219
|
-
return {
|
|
220
|
-
type,
|
|
221
|
-
range: [start.index, end.index],
|
|
222
|
-
loc: {
|
|
223
|
-
start: { line: start.line, column: start.column },
|
|
224
|
-
end: { line: end.line, column: end.column },
|
|
225
|
-
},
|
|
226
|
-
...fields,
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Normalizes a struct-typed field's value that has no `Pos`/`End` of its
|
|
231
|
-
* own — one of mvdan/sh's three non-`Node` "auxiliary" structs (`Slice`,
|
|
232
|
-
* `Replace`, `Expansion`). Its `range`/`loc` are synthesized from the
|
|
233
|
-
* union of its own children's already-computed spans (the exact source
|
|
234
|
-
* span its children cover — e.g. a `Replace`'s span is `Orig`'s start
|
|
235
|
-
* through `With`'s end, which for `${var/foo/bar}` is exactly `foo/bar`).
|
|
236
|
-
* Falls back to the nearest enclosing real node's span only when there
|
|
237
|
-
* are no positioned children at all to derive one from — e.g.
|
|
238
|
-
* `Expansion.Word` is nil (omitted from typedjson's output entirely, via
|
|
239
|
-
* `omitempty`) for an empty default like `${a:-}`.
|
|
240
|
-
*/
|
|
241
|
-
function walkSynthetic(node, type, fallback) {
|
|
242
|
-
const { fields, children } = buildFields(node, type, fallback);
|
|
243
|
-
const start = children.length > 0 ? children.map(startOf).reduce(earlier) : fallback.start;
|
|
244
|
-
const end = children.length > 0 ? children.map(endOf).reduce(later) : fallback.end;
|
|
245
|
-
return {
|
|
246
|
-
type,
|
|
247
|
-
range: [start.index, end.index],
|
|
248
|
-
loc: {
|
|
249
|
-
start: { line: start.line, column: start.column },
|
|
250
|
-
end: { line: end.line, column: end.column },
|
|
251
|
-
},
|
|
252
|
-
...fields,
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
if (!isRawNode(root)) {
|
|
256
|
-
throw new Error('normalize: root value is not a node (missing Pos/End)');
|
|
257
|
-
}
|
|
258
|
-
return walkNode(root, 'File');
|
|
259
|
-
}
|
|
260
|
-
//# sourceMappingURL=normalize.js.map
|
package/dist/normalize.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"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"}
|
package/dist/parse.d.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { type JsonValue } from './normalize.js';
|
|
2
|
-
import type { ParseOptions, ShFile } from './types.js';
|
|
3
|
-
interface ParseErrorPayload {
|
|
4
|
-
message: string;
|
|
5
|
-
filename: string;
|
|
6
|
-
line: number;
|
|
7
|
-
column: number;
|
|
8
|
-
offset: number;
|
|
9
|
-
}
|
|
10
|
-
interface ErrorPayload {
|
|
11
|
-
message: string;
|
|
12
|
-
}
|
|
13
|
-
interface ResultEnvelope {
|
|
14
|
-
file?: JsonValue;
|
|
15
|
-
parseError?: ParseErrorPayload;
|
|
16
|
-
error?: ErrorPayload;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* @internal
|
|
20
|
-
*/
|
|
21
|
-
export declare function isResultEnvelope(value: unknown): value is ResultEnvelope;
|
|
22
|
-
/**
|
|
23
|
-
* Synchronously parses shell source into a normalized AST.
|
|
24
|
-
*
|
|
25
|
-
* The first call instantiates the WASM shim synchronously (Node-only); the
|
|
26
|
-
* instance is reused across subsequent calls, so repeated calls do not
|
|
27
|
-
* re-instantiate (see design/ARCHITECTURE.md).
|
|
28
|
-
*
|
|
29
|
-
* Throws {@link ShParseError} on a shell syntax error, carrying the position
|
|
30
|
-
* mvdan/sh reported: `.line` is 1-based exactly as mvdan/sh reports it;
|
|
31
|
-
* `.column` is converted to UTF-16 code units so it agrees with
|
|
32
|
-
* {@link ShNode.loc}'s columns (mvdan/sh itself reports `column` as a byte
|
|
33
|
-
* count — see {@link ShParseErrorInfo.column}). That unconverted, raw
|
|
34
|
-
* position appears only inside `.message`, which is mvdan/sh's own
|
|
35
|
-
* formatted string, verbatim. Throws {@link ShInvalidDialectError} when
|
|
36
|
-
* {@link ParseOptions.dialect} is not a supported dialect. Throws
|
|
37
|
-
* {@link ShInternalError} for failures that should never happen given
|
|
38
|
-
* a correctly-behaving shim (malformed envelope, unexpected root node
|
|
39
|
-
* type, shim contract violations). Throws {@link ShParseMaxDepthError} if
|
|
40
|
-
* `text`'s conservatively estimated structural nesting depth exceeds the
|
|
41
|
-
* limit this bridge accepts — checked, and thrown, *before* `text` is ever
|
|
42
|
-
* handed to the WASM shim, since mvdan/sh's own parser has no recovery path
|
|
43
|
-
* for exhausting its stack on pathological nesting (see that error's doc
|
|
44
|
-
* comment and `parse-depth-guard.ts`).
|
|
45
|
-
*
|
|
46
|
-
* @public
|
|
47
|
-
*/
|
|
48
|
-
export declare function parseSync(text: string, options?: ParseOptions): ShFile;
|
|
49
|
-
export {};
|
|
50
|
-
//# sourceMappingURL=parse.d.ts.map
|
package/dist/parse.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG1E,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,EAAE,MAAM,YAAY,CAAC;AAcrE,UAAU,iBAAiB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAoCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAKxE;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAsCtE"}
|
package/dist/parse.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { ShInternalError, ShInvalidDialectError, ShParseError } from './errors.js';
|
|
2
|
-
import { normalize, toUtf16Column } from './normalize.js';
|
|
3
|
-
import { assertParseDepthWithinLimit } from './parse-depth-guard.js';
|
|
4
|
-
import { callParse } from './wasm-instance.js';
|
|
5
|
-
/**
|
|
6
|
-
* The full set of dialects {@link parseSync} accepts, in the order surfaced
|
|
7
|
-
* by {@link ShInvalidDialectError}'s message. Kept as a runtime value
|
|
8
|
-
* distinct from the {@link ShellDialect} union so `parseSync` can validate
|
|
9
|
-
* `options.dialect` before ever calling into the WASM shim.
|
|
10
|
-
*/
|
|
11
|
-
const SUPPORTED_SHELL_DIALECTS = ['bash', 'posix', 'mksh', 'bats', 'zsh'];
|
|
12
|
-
function isSupportedShellDialect(value) {
|
|
13
|
-
return SUPPORTED_SHELL_DIALECTS.includes(value);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Checks that `value` is a plain object — rejects arrays, `null`, wrapped
|
|
17
|
-
* primitives, class instances, and symbol-keyed objects. `isResultEnvelope`
|
|
18
|
-
* and its field-level helpers below all validate `unknown` input coming
|
|
19
|
-
* straight out of `JSON.parse`, so this is the full-rigor check, not just
|
|
20
|
-
* `typeof value === 'object'`.
|
|
21
|
-
*
|
|
22
|
-
* @internal
|
|
23
|
-
*/
|
|
24
|
-
function isPlainObject(value) {
|
|
25
|
-
return (typeof value === 'object' &&
|
|
26
|
-
value !== null &&
|
|
27
|
-
!Array.isArray(value) &&
|
|
28
|
-
Object.getPrototypeOf(value) === Object.prototype &&
|
|
29
|
-
Object.getOwnPropertySymbols(value).length === 0);
|
|
30
|
-
}
|
|
31
|
-
function isParseErrorPayload(value) {
|
|
32
|
-
return (isPlainObject(value) &&
|
|
33
|
-
typeof value.message === 'string' &&
|
|
34
|
-
typeof value.filename === 'string' &&
|
|
35
|
-
typeof value.line === 'number' &&
|
|
36
|
-
typeof value.column === 'number' &&
|
|
37
|
-
typeof value.offset === 'number');
|
|
38
|
-
}
|
|
39
|
-
function isErrorPayload(value) {
|
|
40
|
-
return isPlainObject(value) && typeof value.message === 'string';
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* @internal
|
|
44
|
-
*/
|
|
45
|
-
export function isResultEnvelope(value) {
|
|
46
|
-
if (!isPlainObject(value))
|
|
47
|
-
return false;
|
|
48
|
-
if (value.parseError !== undefined && !isParseErrorPayload(value.parseError))
|
|
49
|
-
return false;
|
|
50
|
-
if (value.error !== undefined && !isErrorPayload(value.error))
|
|
51
|
-
return false;
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
function asShFile(node) {
|
|
55
|
-
if (node.type !== 'File') {
|
|
56
|
-
throw new ShInternalError(`bridge: expected root node of type "File", got "${node.type}"`);
|
|
57
|
-
}
|
|
58
|
-
if (!Array.isArray(node.stmts)) {
|
|
59
|
-
throw new ShInternalError('bridge: expected root node to have an array "stmts" field');
|
|
60
|
-
}
|
|
61
|
-
return node;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Synchronously parses shell source into a normalized AST.
|
|
65
|
-
*
|
|
66
|
-
* The first call instantiates the WASM shim synchronously (Node-only); the
|
|
67
|
-
* instance is reused across subsequent calls, so repeated calls do not
|
|
68
|
-
* re-instantiate (see design/ARCHITECTURE.md).
|
|
69
|
-
*
|
|
70
|
-
* Throws {@link ShParseError} on a shell syntax error, carrying the position
|
|
71
|
-
* mvdan/sh reported: `.line` is 1-based exactly as mvdan/sh reports it;
|
|
72
|
-
* `.column` is converted to UTF-16 code units so it agrees with
|
|
73
|
-
* {@link ShNode.loc}'s columns (mvdan/sh itself reports `column` as a byte
|
|
74
|
-
* count — see {@link ShParseErrorInfo.column}). That unconverted, raw
|
|
75
|
-
* position appears only inside `.message`, which is mvdan/sh's own
|
|
76
|
-
* formatted string, verbatim. Throws {@link ShInvalidDialectError} when
|
|
77
|
-
* {@link ParseOptions.dialect} is not a supported dialect. Throws
|
|
78
|
-
* {@link ShInternalError} for failures that should never happen given
|
|
79
|
-
* a correctly-behaving shim (malformed envelope, unexpected root node
|
|
80
|
-
* type, shim contract violations). Throws {@link ShParseMaxDepthError} if
|
|
81
|
-
* `text`'s conservatively estimated structural nesting depth exceeds the
|
|
82
|
-
* limit this bridge accepts — checked, and thrown, *before* `text` is ever
|
|
83
|
-
* handed to the WASM shim, since mvdan/sh's own parser has no recovery path
|
|
84
|
-
* for exhausting its stack on pathological nesting (see that error's doc
|
|
85
|
-
* comment and `parse-depth-guard.ts`).
|
|
86
|
-
*
|
|
87
|
-
* @public
|
|
88
|
-
*/
|
|
89
|
-
export function parseSync(text, options) {
|
|
90
|
-
const dialect = options?.dialect ?? 'bash';
|
|
91
|
-
const filename = options?.filename ?? 'input.sh';
|
|
92
|
-
if (!isSupportedShellDialect(dialect)) {
|
|
93
|
-
throw new ShInvalidDialectError(dialect, SUPPORTED_SHELL_DIALECTS);
|
|
94
|
-
}
|
|
95
|
-
assertParseDepthWithinLimit(text);
|
|
96
|
-
const raw = callParse(text, dialect, filename);
|
|
97
|
-
const result = JSON.parse(raw);
|
|
98
|
-
if (!isResultEnvelope(result)) {
|
|
99
|
-
throw new ShInternalError('bridge: WASM shim returned an unexpected payload shape');
|
|
100
|
-
}
|
|
101
|
-
if (result.parseError) {
|
|
102
|
-
// mvdan/sh reports `column` as a byte count on the source line, not a
|
|
103
|
-
// UTF-16 code unit count — inconsistent with ShNode.loc.column, which is
|
|
104
|
-
// always UTF-16 (see design/ARCHITECTURE.md's "Byte→UTF-16 conversion").
|
|
105
|
-
// Recompute it from `offset` (a byte offset from the start of the file,
|
|
106
|
-
// which every position mvdan/sh reports carries) via the same
|
|
107
|
-
// conversion `normalize` applies to every node, so a thrown
|
|
108
|
-
// ShParseError's column always agrees with the column a ShNode at that
|
|
109
|
-
// position would report.
|
|
110
|
-
const column = toUtf16Column(text, result.parseError.offset, result.parseError.line);
|
|
111
|
-
throw new ShParseError(result.parseError.message, {
|
|
112
|
-
line: result.parseError.line,
|
|
113
|
-
column,
|
|
114
|
-
filename: result.parseError.filename,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
if (result.error) {
|
|
118
|
-
throw new ShInternalError(result.error.message);
|
|
119
|
-
}
|
|
120
|
-
if (result.file === undefined) {
|
|
121
|
-
throw new ShInternalError('bridge: WASM shim returned neither a file nor an error');
|
|
122
|
-
}
|
|
123
|
-
return asShFile(normalize(result.file, text));
|
|
124
|
-
}
|
|
125
|
-
//# sourceMappingURL=parse.js.map
|
package/dist/parse.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shell dialect (mvdan/sh `LangVariant`) to parse against. Mapped to
|
|
3
|
-
* `LangVariant` by string name via `LangVariant.Set()` — never by numeric
|
|
4
|
-
* value, since the bit-flag encoding of `LangVariant` is not a stable
|
|
5
|
-
* contract across mvdan/sh versions. See design/ARCHITECTURE.md, "Parse
|
|
6
|
-
* errors and dialects".
|
|
7
|
-
*
|
|
8
|
-
* @public
|
|
9
|
-
*/
|
|
10
|
-
export type ShellDialect = 'bash' | 'posix' | 'mksh' | 'bats' | 'zsh';
|
|
11
|
-
/**
|
|
12
|
-
* Options accepted by {@link parseSync}.
|
|
13
|
-
*
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export interface ParseOptions {
|
|
17
|
-
/**
|
|
18
|
-
* The shell dialect to parse against.
|
|
19
|
-
* @defaultValue `"bash"`
|
|
20
|
-
*/
|
|
21
|
-
readonly dialect?: ShellDialect;
|
|
22
|
-
/**
|
|
23
|
-
* Filename used only to annotate error messages and positions; the source
|
|
24
|
-
* is never read from disk.
|
|
25
|
-
* @defaultValue `"input.sh"`
|
|
26
|
-
*/
|
|
27
|
-
readonly filename?: string;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* A 1-based line/column position. Columns are UTF-16 code units, matching
|
|
31
|
-
* JavaScript string indexing (see {@link ShNode.range}).
|
|
32
|
-
*
|
|
33
|
-
* @public
|
|
34
|
-
*/
|
|
35
|
-
export interface Position {
|
|
36
|
-
readonly line: number;
|
|
37
|
-
readonly column: number;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* A normalized AST node produced by {@link sh-ast#parseSync | parseSync}.
|
|
41
|
-
*
|
|
42
|
-
* `range` and `loc` are expressed in UTF-16 code units, so
|
|
43
|
-
* `code.slice(node.range[0], node.range[1])` reproduces the node's exact
|
|
44
|
-
* source text — even though mvdan/sh itself reports byte offsets and
|
|
45
|
-
* byte-counting columns internally (see design/ARCHITECTURE.md's
|
|
46
|
-
* "Serialization contract"). Every other field copied over from mvdan/sh's
|
|
47
|
-
* typedjson tree keeps its original value but with the field name
|
|
48
|
-
* lowercased (`Stmts` becomes `stmts`, `CondLast` becomes `condlast`, etc.).
|
|
49
|
-
*
|
|
50
|
-
* Also re-exported from `sh-ast/analyze` (see #23) — the subpath's public
|
|
51
|
-
* surface consumes and exposes `ShNode`, so a consumer can reference the type
|
|
52
|
-
* without also importing from the root `sh-ast` entry point.
|
|
53
|
-
*
|
|
54
|
-
* @public
|
|
55
|
-
*/
|
|
56
|
-
export interface ShNode {
|
|
57
|
-
readonly type: string;
|
|
58
|
-
readonly range: readonly [number, number];
|
|
59
|
-
readonly loc: {
|
|
60
|
-
readonly start: Position;
|
|
61
|
-
readonly end: Position;
|
|
62
|
-
};
|
|
63
|
-
[field: string]: unknown;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* The root node of a parsed shell script.
|
|
67
|
-
*
|
|
68
|
-
* @public
|
|
69
|
-
*/
|
|
70
|
-
export interface ShFile extends ShNode {
|
|
71
|
-
readonly type: 'File';
|
|
72
|
-
readonly stmts: readonly ShNode[];
|
|
73
|
-
}
|
|
74
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAEtE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,YAAY,CAAC;IAEhC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;KAAE,CAAC;IACnE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,MAAO,SAAQ,MAAM;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC"}
|
package/dist/types.js
DELETED
package/dist/types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/visitor-keys.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Maps each normalized node `type` to the field names (lowercased, matching
|
|
3
|
-
* the normalized node shape produced by `normalize`) whose values hold child
|
|
4
|
-
* nodes.
|
|
5
|
-
*
|
|
6
|
-
* Generated from mvdan/sh's `syntax` package struct definitions by
|
|
7
|
-
* `tools/gen-visitor-keys` (see design/ARCHITECTURE.md, "The schema table is
|
|
8
|
-
* generated, not hand-written") — this module only re-exports the generated
|
|
9
|
-
* table under the public name, frozen. {@link walk} does not depend on this
|
|
10
|
-
* table for correctness — it discovers children structurally — so any gap
|
|
11
|
-
* here (there shouldn't be one; the kitchen-sink golden test guards it)
|
|
12
|
-
* affects only external consumers that choose to traverse via this table.
|
|
13
|
-
*
|
|
14
|
-
* Frozen (including each per-type field-name array) so immutability of this
|
|
15
|
-
* shared, module-scoped table is a contract, not just a convention any
|
|
16
|
-
* importer happens to honor.
|
|
17
|
-
*
|
|
18
|
-
* @public
|
|
19
|
-
*/
|
|
20
|
-
export declare const visitorKeys: Readonly<Record<string, readonly string[]>>;
|
|
21
|
-
//# sourceMappingURL=visitor-keys.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"visitor-keys.d.ts","sourceRoot":"","sources":["../src/visitor-keys.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAClC,CAAC"}
|