@stacksjs/zig-dtsx 0.9.10
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/LICENSE.md +21 -0
- package/README.md +73 -0
- package/build.zig +79 -0
- package/build.zig.zon +11 -0
- package/package.json +23 -0
- package/src/char_utils.zig +158 -0
- package/src/emitter.zig +1045 -0
- package/src/extractors.zig +2464 -0
- package/src/index.ts +222 -0
- package/src/lib.zig +254 -0
- package/src/main.zig +532 -0
- package/src/scan_loop.zig +330 -0
- package/src/scanner.zig +908 -0
- package/src/type_inference.zig +1564 -0
- package/src/types.zig +105 -0
- package/test/benchmark.ts +343 -0
- package/test/fixtures/output/variable.d.ts +157 -0
- package/test/zig-dtsx.test.ts +1386 -0
- package/zig-out/bin/zig-dtsx +0 -0
- package/zig-out/bin/zig-dtsx.exe +0 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/// Main scan loop - first-character dispatch for keyword detection.
|
|
2
|
+
/// Port of scanner.ts lines 2600-2994.
|
|
3
|
+
const std = @import("std");
|
|
4
|
+
const ch = @import("char_utils.zig");
|
|
5
|
+
const types = @import("types.zig");
|
|
6
|
+
const Scanner = @import("scanner.zig").Scanner;
|
|
7
|
+
const ext = @import("extractors.zig");
|
|
8
|
+
const Declaration = types.Declaration;
|
|
9
|
+
|
|
10
|
+
/// Main scan loop: iterate through source and extract declarations
|
|
11
|
+
pub fn scanMainLoop(s: *Scanner) !void {
|
|
12
|
+
while (s.pos < s.len) {
|
|
13
|
+
s.skipWhitespaceAndComments();
|
|
14
|
+
if (s.pos >= s.len) break;
|
|
15
|
+
|
|
16
|
+
const stmt_start = s.pos;
|
|
17
|
+
const ch0 = s.source[s.pos];
|
|
18
|
+
|
|
19
|
+
if (ch0 == 'i' and s.matchWord("import")) {
|
|
20
|
+
const decl = ext.extractImport(s, stmt_start);
|
|
21
|
+
try s.declarations.append(decl);
|
|
22
|
+
} else if (ch0 == 'e' and s.matchWord("export")) {
|
|
23
|
+
try handleExport(s, stmt_start);
|
|
24
|
+
} else if (ch0 == 'd' and s.matchWord("declare")) {
|
|
25
|
+
s.pos += 7;
|
|
26
|
+
s.skipWhitespaceAndComments();
|
|
27
|
+
ext.handleDeclare(s, stmt_start, false);
|
|
28
|
+
} else if (ch0 == 'i' and s.matchWord("interface")) {
|
|
29
|
+
const decl = ext.extractInterface(s, stmt_start, false);
|
|
30
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
31
|
+
} else if (ch0 == 't' and s.matchWord("type")) {
|
|
32
|
+
const decl = ext.extractTypeAlias(s, stmt_start, false);
|
|
33
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
34
|
+
try s.declarations.append(decl);
|
|
35
|
+
} else if (ch0 == 'f' and s.matchWord("function")) {
|
|
36
|
+
s.skipToStatementEnd();
|
|
37
|
+
} else if (ch0 == 'a') {
|
|
38
|
+
if (s.matchWord("async")) {
|
|
39
|
+
s.skipToStatementEnd();
|
|
40
|
+
} else if (s.matchWord("abstract")) {
|
|
41
|
+
s.pos += 8;
|
|
42
|
+
s.skipWhitespaceAndComments();
|
|
43
|
+
if (s.matchWord("class")) {
|
|
44
|
+
const decl = ext.extractClass(s, stmt_start, false, false);
|
|
45
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
46
|
+
try s.declarations.append(decl);
|
|
47
|
+
} else {
|
|
48
|
+
s.skipToStatementEnd();
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
s.pos += 1;
|
|
52
|
+
s.skipToStatementEnd();
|
|
53
|
+
}
|
|
54
|
+
} else if (ch0 == 'c') {
|
|
55
|
+
if (s.matchWord("class")) {
|
|
56
|
+
const decl = ext.extractClass(s, stmt_start, false, false);
|
|
57
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
58
|
+
try s.declarations.append(decl);
|
|
59
|
+
} else if (s.matchWord("const")) {
|
|
60
|
+
const saved_pos = s.pos;
|
|
61
|
+
s.pos += 5;
|
|
62
|
+
s.skipWhitespaceAndComments();
|
|
63
|
+
if (s.matchWord("enum")) {
|
|
64
|
+
s.pos = saved_pos + 5;
|
|
65
|
+
s.skipWhitespaceAndComments();
|
|
66
|
+
const decl = ext.extractEnum(s, stmt_start, false, true);
|
|
67
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
68
|
+
try s.declarations.append(decl);
|
|
69
|
+
} else {
|
|
70
|
+
s.pos = saved_pos;
|
|
71
|
+
s.skipToStatementEnd();
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
s.pos += 1;
|
|
75
|
+
s.skipToStatementEnd();
|
|
76
|
+
}
|
|
77
|
+
} else if (ch0 == 'e' and s.matchWord("enum")) {
|
|
78
|
+
const decl = ext.extractEnum(s, stmt_start, false, false);
|
|
79
|
+
s.non_exported_types.put(decl.name, decl) catch {};
|
|
80
|
+
try s.declarations.append(decl);
|
|
81
|
+
} else if (ch0 == 'l' and s.matchWord("let")) {
|
|
82
|
+
s.skipToStatementEnd();
|
|
83
|
+
} else if (ch0 == 'v' and s.matchWord("var")) {
|
|
84
|
+
s.skipToStatementEnd();
|
|
85
|
+
} else if (ch0 == 'm' and s.matchWord("module")) {
|
|
86
|
+
const decl = ext.extractModule(s, stmt_start, false, "module");
|
|
87
|
+
try s.declarations.append(decl);
|
|
88
|
+
} else if (ch0 == 'n' and s.matchWord("namespace")) {
|
|
89
|
+
const decl = ext.extractModule(s, stmt_start, false, "namespace");
|
|
90
|
+
try s.declarations.append(decl);
|
|
91
|
+
} else {
|
|
92
|
+
// Skip unknown top-level content
|
|
93
|
+
if (ch0 == ch.CH_SQUOTE or ch0 == ch.CH_DQUOTE) {
|
|
94
|
+
s.skipString(ch0);
|
|
95
|
+
if (s.pos < s.len and s.source[s.pos] == ch.CH_SEMI) s.pos += 1;
|
|
96
|
+
} else if (ch0 == ch.CH_BACKTICK) {
|
|
97
|
+
s.skipTemplateLiteral();
|
|
98
|
+
if (s.pos < s.len and s.source[s.pos] == ch.CH_SEMI) s.pos += 1;
|
|
99
|
+
} else if (ch0 == ch.CH_AT) {
|
|
100
|
+
// Decorator
|
|
101
|
+
s.pos += 1;
|
|
102
|
+
_ = s.readIdent();
|
|
103
|
+
s.skipWhitespaceAndComments();
|
|
104
|
+
if (s.pos < s.len and s.source[s.pos] == ch.CH_DOT) {
|
|
105
|
+
s.pos += 1;
|
|
106
|
+
_ = s.readIdent();
|
|
107
|
+
s.skipWhitespaceAndComments();
|
|
108
|
+
}
|
|
109
|
+
if (s.pos < s.len and s.source[s.pos] == ch.CH_LPAREN) {
|
|
110
|
+
_ = s.findMatchingClose(ch.CH_LPAREN, ch.CH_RPAREN);
|
|
111
|
+
}
|
|
112
|
+
} else {
|
|
113
|
+
s.pos += 1;
|
|
114
|
+
s.skipToStatementEnd();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Handle `export ...` after `export` keyword
|
|
121
|
+
fn handleExport(s: *Scanner, stmt_start: usize) !void {
|
|
122
|
+
s.pos += 6; // skip 'export'
|
|
123
|
+
s.skipWhitespaceAndComments();
|
|
124
|
+
if (s.pos >= s.len) return;
|
|
125
|
+
const ech = s.source[s.pos];
|
|
126
|
+
|
|
127
|
+
if (ech == 'd' and s.matchWord("default")) {
|
|
128
|
+
s.pos += 7;
|
|
129
|
+
s.skipWhitespaceAndComments();
|
|
130
|
+
if (s.pos >= s.len) return;
|
|
131
|
+
const dch = s.source[s.pos];
|
|
132
|
+
|
|
133
|
+
if (dch == 'f' and s.matchWord("function")) {
|
|
134
|
+
const decl = ext.extractFunction(s, stmt_start, true, false, true);
|
|
135
|
+
if (decl) |d| try s.declarations.append(d);
|
|
136
|
+
} else if (dch == 'a' and s.matchWord("async")) {
|
|
137
|
+
s.pos += 5;
|
|
138
|
+
s.skipWhitespaceAndComments();
|
|
139
|
+
if (s.matchWord("function")) {
|
|
140
|
+
const decl = ext.extractFunction(s, stmt_start, true, true, true);
|
|
141
|
+
if (decl) |d| try s.declarations.append(d);
|
|
142
|
+
} else {
|
|
143
|
+
s.skipToStatementEnd();
|
|
144
|
+
const full_text = s.sliceTrimmed(stmt_start, s.pos);
|
|
145
|
+
try s.declarations.append(.{
|
|
146
|
+
.kind = .export_decl,
|
|
147
|
+
.name = "default",
|
|
148
|
+
.text = full_text,
|
|
149
|
+
.is_exported = true,
|
|
150
|
+
.start = stmt_start,
|
|
151
|
+
.end = s.pos,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
} else if (dch == 'c' and s.matchWord("class")) {
|
|
155
|
+
const decl = ext.extractClass(s, stmt_start, true, false);
|
|
156
|
+
try s.declarations.append(decl);
|
|
157
|
+
} else if (dch == 'a' and s.matchWord("abstract")) {
|
|
158
|
+
s.pos += 8;
|
|
159
|
+
s.skipWhitespaceAndComments();
|
|
160
|
+
if (s.matchWord("class")) {
|
|
161
|
+
const decl = ext.extractClass(s, stmt_start, true, true);
|
|
162
|
+
try s.declarations.append(decl);
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
s.skipToStatementEnd();
|
|
166
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
167
|
+
const comments = ext.extractLeadingComments(s, stmt_start);
|
|
168
|
+
try s.declarations.append(.{
|
|
169
|
+
.kind = .export_decl,
|
|
170
|
+
.name = "default",
|
|
171
|
+
.text = text,
|
|
172
|
+
.is_exported = true,
|
|
173
|
+
.leading_comments = comments,
|
|
174
|
+
.start = stmt_start,
|
|
175
|
+
.end = s.pos,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
} else if (ech == 't' and s.matchWord("type")) {
|
|
179
|
+
const saved_pos = s.pos;
|
|
180
|
+
s.pos += 4;
|
|
181
|
+
s.skipWhitespaceAndComments();
|
|
182
|
+
if (s.pos < s.len and s.source[s.pos] == ch.CH_LBRACE) {
|
|
183
|
+
s.skipExportBraces();
|
|
184
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
185
|
+
const comments = ext.extractLeadingComments(s, stmt_start);
|
|
186
|
+
try s.declarations.append(.{
|
|
187
|
+
.kind = .export_decl,
|
|
188
|
+
.name = "",
|
|
189
|
+
.text = text,
|
|
190
|
+
.is_exported = true,
|
|
191
|
+
.is_type_only = true,
|
|
192
|
+
.leading_comments = comments,
|
|
193
|
+
.start = stmt_start,
|
|
194
|
+
.end = s.pos,
|
|
195
|
+
});
|
|
196
|
+
} else if (s.pos < s.len and s.source[s.pos] == ch.CH_STAR) {
|
|
197
|
+
s.skipExportStar();
|
|
198
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
199
|
+
try s.declarations.append(.{
|
|
200
|
+
.kind = .export_decl,
|
|
201
|
+
.name = "",
|
|
202
|
+
.text = text,
|
|
203
|
+
.is_exported = true,
|
|
204
|
+
.is_type_only = true,
|
|
205
|
+
.start = stmt_start,
|
|
206
|
+
.end = s.pos,
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
s.pos = saved_pos;
|
|
210
|
+
const decl = ext.extractTypeAlias(s, stmt_start, true);
|
|
211
|
+
try s.declarations.append(decl);
|
|
212
|
+
}
|
|
213
|
+
} else if (ech == 'i' and s.matchWord("interface")) {
|
|
214
|
+
const decl = ext.extractInterface(s, stmt_start, true);
|
|
215
|
+
try s.declarations.append(decl);
|
|
216
|
+
} else if (ech == 'f' and s.matchWord("function")) {
|
|
217
|
+
const decl = ext.extractFunction(s, stmt_start, true, false, false);
|
|
218
|
+
if (decl) |d| try s.declarations.append(d);
|
|
219
|
+
} else if (ech == 'a' and s.matchWord("async")) {
|
|
220
|
+
s.pos += 5;
|
|
221
|
+
s.skipWhitespaceAndComments();
|
|
222
|
+
if (s.matchWord("function")) {
|
|
223
|
+
const decl = ext.extractFunction(s, stmt_start, true, true, false);
|
|
224
|
+
if (decl) |d| try s.declarations.append(d);
|
|
225
|
+
} else {
|
|
226
|
+
s.skipToStatementEnd();
|
|
227
|
+
}
|
|
228
|
+
} else if (ech == 'c') {
|
|
229
|
+
if (s.matchWord("class")) {
|
|
230
|
+
const decl = ext.extractClass(s, stmt_start, true, false);
|
|
231
|
+
try s.declarations.append(decl);
|
|
232
|
+
} else if (s.matchWord("const")) {
|
|
233
|
+
const saved_pos = s.pos;
|
|
234
|
+
s.pos += 5;
|
|
235
|
+
s.skipWhitespaceAndComments();
|
|
236
|
+
if (s.matchWord("enum")) {
|
|
237
|
+
s.pos = saved_pos + 5;
|
|
238
|
+
s.skipWhitespaceAndComments();
|
|
239
|
+
const decl = ext.extractEnum(s, stmt_start, true, true);
|
|
240
|
+
try s.declarations.append(decl);
|
|
241
|
+
} else {
|
|
242
|
+
s.pos = saved_pos;
|
|
243
|
+
const decls = ext.extractVariable(s, stmt_start, "const", true);
|
|
244
|
+
for (decls) |d| try s.declarations.append(d);
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
s.skipToStatementEnd();
|
|
248
|
+
}
|
|
249
|
+
} else if (ech == 'a' and s.matchWord("abstract")) {
|
|
250
|
+
s.pos += 8;
|
|
251
|
+
s.skipWhitespaceAndComments();
|
|
252
|
+
if (s.matchWord("class")) {
|
|
253
|
+
const decl = ext.extractClass(s, stmt_start, true, true);
|
|
254
|
+
try s.declarations.append(decl);
|
|
255
|
+
}
|
|
256
|
+
} else if (ech == 'l' and s.matchWord("let")) {
|
|
257
|
+
const decls = ext.extractVariable(s, stmt_start, "let", true);
|
|
258
|
+
for (decls) |d| try s.declarations.append(d);
|
|
259
|
+
} else if (ech == 'v' and s.matchWord("var")) {
|
|
260
|
+
const decls = ext.extractVariable(s, stmt_start, "var", true);
|
|
261
|
+
for (decls) |d| try s.declarations.append(d);
|
|
262
|
+
} else if (ech == 'e' and s.matchWord("enum")) {
|
|
263
|
+
const decl = ext.extractEnum(s, stmt_start, true, false);
|
|
264
|
+
try s.declarations.append(decl);
|
|
265
|
+
} else if (ech == 'd' and s.matchWord("declare")) {
|
|
266
|
+
s.pos += 7;
|
|
267
|
+
s.skipWhitespaceAndComments();
|
|
268
|
+
ext.handleDeclare(s, stmt_start, true);
|
|
269
|
+
} else if (ech == 'n' and s.matchWord("namespace")) {
|
|
270
|
+
const decl = ext.extractModule(s, stmt_start, true, "namespace");
|
|
271
|
+
try s.declarations.append(decl);
|
|
272
|
+
} else if (ech == 'm' and s.matchWord("module")) {
|
|
273
|
+
const decl = ext.extractModule(s, stmt_start, true, "module");
|
|
274
|
+
try s.declarations.append(decl);
|
|
275
|
+
} else if (ech == ch.CH_LBRACE) {
|
|
276
|
+
s.skipExportBraces();
|
|
277
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
278
|
+
const is_type_only = ch.contains(text, "export type");
|
|
279
|
+
const comments = ext.extractLeadingComments(s, stmt_start);
|
|
280
|
+
try s.declarations.append(.{
|
|
281
|
+
.kind = .export_decl,
|
|
282
|
+
.name = "",
|
|
283
|
+
.text = text,
|
|
284
|
+
.is_exported = true,
|
|
285
|
+
.is_type_only = is_type_only,
|
|
286
|
+
.leading_comments = comments,
|
|
287
|
+
.start = stmt_start,
|
|
288
|
+
.end = s.pos,
|
|
289
|
+
});
|
|
290
|
+
} else if (ech == ch.CH_STAR) {
|
|
291
|
+
s.skipExportStar();
|
|
292
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
293
|
+
const comments = ext.extractLeadingComments(s, stmt_start);
|
|
294
|
+
// Extract source from 'from "..."'
|
|
295
|
+
var export_source: []const u8 = "";
|
|
296
|
+
const from_idx = ch.indexOf(text, "from ", 0);
|
|
297
|
+
if (from_idx) |fi| {
|
|
298
|
+
var qi = fi + 5;
|
|
299
|
+
while (qi < text.len and (text[qi] == ' ' or text[qi] == '\t')) qi += 1;
|
|
300
|
+
if (qi < text.len and (text[qi] == '\'' or text[qi] == '"')) {
|
|
301
|
+
const q_str: []const u8 = if (text[qi] == '\'') "'" else "\"";
|
|
302
|
+
const q_end = ch.indexOf(text, q_str, qi + 1);
|
|
303
|
+
if (q_end) |qe| export_source = text[qi + 1 .. qe];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
try s.declarations.append(.{
|
|
307
|
+
.kind = .export_decl,
|
|
308
|
+
.name = "",
|
|
309
|
+
.text = text,
|
|
310
|
+
.is_exported = true,
|
|
311
|
+
.source_module = export_source,
|
|
312
|
+
.leading_comments = comments,
|
|
313
|
+
.start = stmt_start,
|
|
314
|
+
.end = s.pos,
|
|
315
|
+
});
|
|
316
|
+
} else {
|
|
317
|
+
s.skipToStatementEnd();
|
|
318
|
+
const text = s.sliceTrimmed(stmt_start, s.pos);
|
|
319
|
+
if (text.len > 0) {
|
|
320
|
+
try s.declarations.append(.{
|
|
321
|
+
.kind = .export_decl,
|
|
322
|
+
.name = "",
|
|
323
|
+
.text = text,
|
|
324
|
+
.is_exported = true,
|
|
325
|
+
.start = stmt_start,
|
|
326
|
+
.end = s.pos,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|