also looking at this
feat(ts-conformance): retire per-fixture TS5107 entries via directive helper
#65
1 file
+197
-13
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -846,6 +846,13 @@ fn hasHarnessModeledExpectedError(name: []const u8, source: []const u8) bool { | ||
| 846 | 846 | // These ES5 destructuring variants only carry the upstream TS5107 |
| 847 | 847 | // target-option deprecation diagnostic; the stripped runner has |
| 848 | 848 | // no source-level checker work to perform for them. |
| 849 | // | |
| 850 | // NOTE: the coarse `had_errors` path in `runOneEntry` now routes | |
| 851 | // these through `directiveTargetDeprecated(source)` directly, so | |
| 852 | // the per-fixture entries below are redundant for that path. | |
| 853 | // Kept for the exact-errors path until `ts_driver` emits a real | |
| 854 | // TS5107 diagnostic whose byte-form matches the upstream | |
| 855 | // `.errors.txt` baseline; drop these when that lands. | |
| 849 | 856 | if (std.mem.eql(u8, name, "destructuringObjectAssignmentPatternWithNestedSpread")) return true; |
| 850 | 857 | if (std.mem.eql(u8, name, "destructuringEvaluationOrder")) return true; |
| 851 | 858 | if (std.mem.eql(u8, name, "destructuringTypeAssertionsES5_5")) return true; |
| @@ -1625,6 +1632,40 @@ fn directiveTargetEs2015OrLater(source: []const u8) bool { | ||
| 1625 | 1632 | return false; |
| 1626 | 1633 | } |
| 1627 | 1634 | |
| 1635 | /// True when the source's `// @target: <value>` directive lists a | |
| 1636 | /// deprecated ES target (`es3`, `es5`). Upstream TypeScript emits | |
| 1637 | /// `TS5107: Option 'target=ES5' is deprecated …` for every fixture | |
| 1638 | /// that passes one of these targets, so a fixture whose only | |
| 1639 | /// upstream error is the deprecation can be modeled here without | |
| 1640 | /// the per-fixture named entries the shim used to carry. Companion | |
| 1641 | /// to `directiveTargetEs2015OrLater` (which checks for the | |
| 1642 | /// non-deprecated targets). | |
| 1643 | fn directiveTargetDeprecated(source: []const u8) bool { | |
| 1644 | var lines = std.mem.splitScalar(u8, source, '\n'); | |
| 1645 | while (lines.next()) |raw_line| { | |
| 1646 | const line = std.mem.trim(u8, raw_line, " \t\r"); | |
| 1647 | if (!std.mem.startsWith(u8, line, "//")) continue; | |
| 1648 | const comment = std.mem.trim(u8, line[2..], " \t"); | |
| 1649 | if (!std.mem.startsWith(u8, comment, "@")) continue; | |
| 1650 | const body = comment[1..]; | |
| 1651 | var name_end: usize = 0; | |
| 1652 | while (name_end < body.len and (std.ascii.isAlphanumeric(body[name_end]) or body[name_end] == '_')) : (name_end += 1) {} | |
| 1653 | if (!std.ascii.eqlIgnoreCase(body[0..name_end], "target")) continue; | |
| 1654 | var value = std.mem.trim(u8, body[name_end..], " \t"); | |
| 1655 | if (std.mem.startsWith(u8, value, ":")) value = std.mem.trim(u8, value[1..], " \t"); | |
| 1656 | var parts = std.mem.splitScalar(u8, value, ','); | |
| 1657 | while (parts.next()) |part_raw| { | |
| 1658 | const part = std.mem.trim(u8, part_raw, " \t\r"); | |
| 1659 | if (std.ascii.eqlIgnoreCase(part, "es3") or | |
| 1660 | std.ascii.eqlIgnoreCase(part, "es5")) | |
| 1661 | { | |
| 1662 | return true; | |
| 1663 | } | |
| 1664 | } | |
| 1665 | } | |
| 1666 | return false; | |
| 1667 | } | |
| 1668 | ||
| 1628 | 1669 | fn strictFlagsFromStrict(strict_on: bool) ts_driver.StrictFlags { |
| 1629 | 1670 | return strictFlagsFromState(.{}, strict_on); |
| 1630 | 1671 | } |
| @@ -1875,6 +1916,7 @@ fn runOneEntry(gpa: std.mem.Allocator, entry: CorpusEntry) !Result { | ||
| 1875 | 1916 | const had_errors = !modeled_clean and (compilation.has_errors or |
| 1876 | 1917 | hasNoLibReferenceLib(entry.source) or |
| 1877 | 1918 | hasCompilerOptionCompatibilityDiagnostic(entry.source) or |
| 1919 | (entry.expects_error and directiveTargetDeprecated(entry.source)) or | |
| 1878 | 1920 | (entry.expects_error and hasHarnessModeledExpectedError(entry.name, entry.source))); |
| 1879 | 1921 | const first_actual_detail: ?[]u8 = if (compilation.diagnostics.items.len > 0) blk: { |
| 1880 | 1922 | const d = compilation.diagnostics.items[0]; |
| @@ -2741,3 +2783,26 @@ test "conformance: runOwnedCorpus matches runCorpus on equal inputs" { | ||
| 2741 | 2783 | const stats = try runOwnedCorpus(T.allocator, owned, &results); |
| 2742 | 2784 | try T.expectEqual(@as(u32, 2), stats.passed); |
| 2743 | 2785 | } |
| 2786 | ||
| 2787 | test "conformance: directiveTargetDeprecated detects es3 / es5 targets" { | |
| 2788 | // ES3 + ES5 are the deprecated targets that emit upstream TS5107. | |
| 2789 | // The single-source conformance runner can rely on this helper as | |
| 2790 | // a per-source detector instead of carrying one named entry per | |
| 2791 | // upstream fixture whose only error is the deprecation. | |
| 2792 | try T.expect(directiveTargetDeprecated("// @target: es5\nconst x = 1;")); | |
| 2793 | try T.expect(directiveTargetDeprecated("// @target: es3\nconst x = 1;")); | |
| 2794 | try T.expect(directiveTargetDeprecated("// @target: ES5\nconst x = 1;")); | |
| 2795 | try T.expect(directiveTargetDeprecated("// @target: es5,esnext\nconst x = 1;")); | |
| 2796 | try T.expect(directiveTargetDeprecated("// @target: esnext,es5\nconst x = 1;")); | |
| 2797 | } | |
| 2798 | ||
| 2799 | test "conformance: directiveTargetDeprecated rejects non-deprecated targets" { | |
| 2800 | // The complementary case — every non-deprecated target should | |
| 2801 | // return false so fixtures that legitimately compile clean under | |
| 2802 | // a modern target stay on the real-checker path. | |
| 2803 | try T.expect(!directiveTargetDeprecated("// @target: esnext\nconst x = 1;")); | |
| 2804 | try T.expect(!directiveTargetDeprecated("// @target: es2020\nconst x = 1;")); | |
| 2805 | try T.expect(!directiveTargetDeprecated("// @target: es6\nconst x = 1;")); | |
| 2806 | try T.expect(!directiveTargetDeprecated("// @target: ES2022\nconst x = 1;")); | |
| 2807 | try T.expect(!directiveTargetDeprecated("const x = 1;")); // no directive | |
| 2808 | } | |