@stacksjs/zig-dtsx 0.9.16 → 0.9.18
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/package.json +2 -2
- package/src/extractors.zig +71 -0
- package/test/zig-dtsx.test.ts +23 -0
- package/zig-out/bin/zig-dtsx +0 -0
- package/zig-out/bin/zig-dtsx.exe +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/zig-dtsx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.18",
|
|
5
5
|
"description": "High-performance DTS emitter written in Zig",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -18,6 +18,6 @@
|
|
|
18
18
|
"benchmark": "bun run test/benchmark.ts"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@stacksjs/dtsx": "0.9.
|
|
21
|
+
"@stacksjs/dtsx": "0.9.18"
|
|
22
22
|
}
|
|
23
23
|
}
|
package/src/extractors.zig
CHANGED
|
@@ -555,11 +555,21 @@ pub fn buildDtsParams(s: *Scanner, raw_params: []const u8) []const u8 {
|
|
|
555
555
|
var str_ch: u8 = 0;
|
|
556
556
|
var skip_next = false;
|
|
557
557
|
|
|
558
|
+
var in_block_comment = false;
|
|
559
|
+
var skip_to_eol = false;
|
|
558
560
|
for (inner, 0..) |c, i| {
|
|
559
561
|
if (skip_next) {
|
|
560
562
|
skip_next = false;
|
|
561
563
|
continue;
|
|
562
564
|
}
|
|
565
|
+
if (skip_to_eol) {
|
|
566
|
+
if (c == '\n') skip_to_eol = false;
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
if (in_block_comment) {
|
|
570
|
+
if (c == '/' and i > 0 and inner[i - 1] == '*') in_block_comment = false;
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
563
573
|
if (in_str) {
|
|
564
574
|
if (c == ch.CH_BACKSLASH) {
|
|
565
575
|
skip_next = true; // skip the escaped character
|
|
@@ -568,6 +578,20 @@ pub fn buildDtsParams(s: *Scanner, raw_params: []const u8) []const u8 {
|
|
|
568
578
|
if (c == str_ch) in_str = false;
|
|
569
579
|
continue;
|
|
570
580
|
}
|
|
581
|
+
// Skip block and line comments — JSDoc prose can contain unmatched
|
|
582
|
+
// quote chars (e.g. apostrophe in "error's") that would otherwise
|
|
583
|
+
// trip the scanner into a string-literal mode it never escapes.
|
|
584
|
+
if (c == '/' and i + 1 < inner.len) {
|
|
585
|
+
const nc = inner[i + 1];
|
|
586
|
+
if (nc == '*') {
|
|
587
|
+
in_block_comment = true;
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
if (nc == '/') {
|
|
591
|
+
skip_to_eol = true;
|
|
592
|
+
continue;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
571
595
|
if (c == ch.CH_SQUOTE or c == ch.CH_DQUOTE or c == ch.CH_BACKTICK) {
|
|
572
596
|
in_str = true;
|
|
573
597
|
str_ch = c;
|
|
@@ -655,11 +679,21 @@ pub fn buildSingleDtsParam(s: *Scanner, raw: []const u8) []const u8 {
|
|
|
655
679
|
var str_ch2: u8 = 0;
|
|
656
680
|
var skip_next2 = false;
|
|
657
681
|
|
|
682
|
+
var in_block_comment2 = false;
|
|
683
|
+
var skip_to_eol2 = false;
|
|
658
684
|
for (p, 0..) |c, i| {
|
|
659
685
|
if (skip_next2) {
|
|
660
686
|
skip_next2 = false;
|
|
661
687
|
continue;
|
|
662
688
|
}
|
|
689
|
+
if (skip_to_eol2) {
|
|
690
|
+
if (c == '\n') skip_to_eol2 = false;
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (in_block_comment2) {
|
|
694
|
+
if (c == '/' and i > 0 and p[i - 1] == '*') in_block_comment2 = false;
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
663
697
|
if (in_str2) {
|
|
664
698
|
if (c == ch.CH_BACKSLASH) {
|
|
665
699
|
skip_next2 = true;
|
|
@@ -668,6 +702,19 @@ pub fn buildSingleDtsParam(s: *Scanner, raw: []const u8) []const u8 {
|
|
|
668
702
|
if (c == str_ch2) in_str2 = false;
|
|
669
703
|
continue;
|
|
670
704
|
}
|
|
705
|
+
// Skip block and line comments before string-mode detection so JSDoc
|
|
706
|
+
// apostrophes (e.g. "error's") don't trigger an unclosed string.
|
|
707
|
+
if (c == '/' and i + 1 < p.len) {
|
|
708
|
+
const nc = p[i + 1];
|
|
709
|
+
if (nc == '*') {
|
|
710
|
+
in_block_comment2 = true;
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
if (nc == '/') {
|
|
714
|
+
skip_to_eol2 = true;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
671
718
|
if (c == ch.CH_SQUOTE or c == ch.CH_DQUOTE or c == ch.CH_BACKTICK) {
|
|
672
719
|
in_str2 = true;
|
|
673
720
|
str_ch2 = c;
|
|
@@ -763,6 +810,30 @@ fn cleanDestructuredPattern(alloc: std.mem.Allocator, pattern: []const u8) []con
|
|
|
763
810
|
while (i < pattern.len) : (i += 1) {
|
|
764
811
|
const c = pattern[i];
|
|
765
812
|
|
|
813
|
+
// Preserve block and line comments verbatim (useful JSDoc) but skip
|
|
814
|
+
// parsing inside them so apostrophes in prose (e.g. "error's") don't
|
|
815
|
+
// put us in an inescapable string mode.
|
|
816
|
+
if (!in_str and c == '/' and i + 1 < pattern.len) {
|
|
817
|
+
const nc = pattern[i + 1];
|
|
818
|
+
if (nc == '*') {
|
|
819
|
+
const start = i;
|
|
820
|
+
var j = i + 2;
|
|
821
|
+
while (j + 1 < pattern.len and !(pattern[j] == '*' and pattern[j + 1] == '/')) : (j += 1) {}
|
|
822
|
+
const end = if (j + 1 < pattern.len) j + 2 else pattern.len;
|
|
823
|
+
result.appendSlice(pattern[start..end]) catch {};
|
|
824
|
+
i = end - 1; // loop's += 1 advances past
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
827
|
+
if (nc == '/') {
|
|
828
|
+
const start = i;
|
|
829
|
+
var j = i;
|
|
830
|
+
while (j < pattern.len and pattern[j] != '\n') : (j += 1) {}
|
|
831
|
+
result.appendSlice(pattern[start..j]) catch {};
|
|
832
|
+
i = if (j == 0) 0 else j - 1; // loop's += 1 lands on the newline
|
|
833
|
+
continue;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
|
|
766
837
|
// String tracking
|
|
767
838
|
if (!in_str and (c == '\'' or c == '"' or c == '`')) {
|
|
768
839
|
in_str = true;
|
package/test/zig-dtsx.test.ts
CHANGED
|
@@ -1173,6 +1173,29 @@ export function merge<T extends Record<string, unknown>, U extends Record<string
|
|
|
1173
1173
|
expect(result).toContain('declare function parse')
|
|
1174
1174
|
})
|
|
1175
1175
|
|
|
1176
|
+
test('issue 3095 — destructured param with JSDoc apostrophe', () => {
|
|
1177
|
+
// JSDoc prose containing an apostrophe (e.g. "error's") used to put the
|
|
1178
|
+
// param scanner into an inescapable string-literal mode, producing
|
|
1179
|
+
// `,: unknown):` that TypeScript rejects with TS1138.
|
|
1180
|
+
const result = dts(`export class CLI {
|
|
1181
|
+
async parse(
|
|
1182
|
+
argv: string[] = [],
|
|
1183
|
+
{
|
|
1184
|
+
/** Whether to run the action for matched command */
|
|
1185
|
+
run = true,
|
|
1186
|
+
/**
|
|
1187
|
+
* Defaults to \`false\`. When set, render the error's message and exit.
|
|
1188
|
+
*/
|
|
1189
|
+
exitOnError = false,
|
|
1190
|
+
}: { run?: boolean, exitOnError?: boolean } = {},
|
|
1191
|
+
): Promise<void> {}
|
|
1192
|
+
}`)
|
|
1193
|
+
expect(result).not.toMatch(/,\s*:\s*unknown\)/)
|
|
1194
|
+
expect(result).not.toContain('= {}')
|
|
1195
|
+
expect(result).toContain('run?: boolean')
|
|
1196
|
+
expect(result).toContain('exitOnError?: boolean')
|
|
1197
|
+
})
|
|
1198
|
+
|
|
1176
1199
|
test('export declare (already declared)', () => {
|
|
1177
1200
|
const result = dts(`export declare const VERSION: string`)
|
|
1178
1201
|
expect(result).toContain('export declare const VERSION: string')
|
package/zig-out/bin/zig-dtsx
CHANGED
|
Binary file
|
package/zig-out/bin/zig-dtsx.exe
CHANGED
|
Binary file
|