ttsc 0.19.3 → 0.20.1
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 +36 -34
- package/cmd/graphdump/main.go +2 -4
- package/cmd/ttsc/filter.go +12 -4
- package/cmd/ttsc/filter_resolves_flag_names_case_insensitively_test.go +53 -0
- package/cmd/ttsc/flags_gen.go +3 -3
- package/cmd/ttscgraph/dump.go +5 -7
- package/cmd/ttscgraph/run_dump_emits_only_checker_verified_member_relations_test.go +118 -0
- package/cmd/ttscgraph/serve.go +58 -308
- package/cmd/ttscgraph/serve_session_keeps_base_url_fallback_unchanged_test.go +49 -0
- package/cmd/ttscgraph/serve_session_keeps_esm_directory_candidate_unchanged_test.go +61 -0
- package/cmd/ttscgraph/serve_session_keeps_exports_blocked_file_candidates_unchanged_test.go +64 -0
- package/cmd/ttscgraph/serve_session_keeps_inactive_conditional_export_unchanged_test.go +66 -0
- package/cmd/ttscgraph/serve_session_keeps_lower_priority_module_candidate_unchanged_test.go +67 -0
- package/cmd/ttscgraph/serve_session_keeps_lower_priority_paths_pattern_unchanged_test.go +58 -0
- package/cmd/ttscgraph/serve_session_keeps_nonlongest_root_dirs_candidate_unchanged_test.go +54 -0
- package/cmd/ttscgraph/serve_session_reloads_commonjs_package_entry_for_esm_test.go +50 -0
- package/cmd/ttscgraph/serve_session_reloads_module_suffix_candidate_test.go +41 -0
- package/cmd/ttscgraph/serve_session_reloads_superseding_module_candidates_test.go +216 -0
- package/cmd/ttscgraph/serve_session_retries_failed_dump_test.go +103 -0
- package/driver/graph.go +12 -6
- package/driver/lsp.go +30 -0
- package/driver/program.go +37 -1
- package/driver/resolution_candidates.go +819 -0
- package/driver/windowsjunction/windowsjunction.go +40 -0
- package/go.mod +2 -0
- package/internal/graph/build.go +45 -11
- package/internal/graph/dump.go +276 -100
- package/internal/graph/dump_checkout_paths_are_stable_test.go +210 -0
- package/internal/graph/dump_diagnostics_ride_the_generation_that_built_it_test.go +9 -3
- package/internal/graph/dump_paths.go +172 -0
- package/internal/graph/dump_paths_are_portable_and_injective_test.go +93 -0
- package/internal/graph/dump_uses_ecma_line_terminators_test.go +87 -0
- package/internal/graph/duplicate_variable_object_members_keep_first_declaration_test.go +61 -0
- package/internal/graph/edges.go +208 -0
- package/internal/graph/graph.go +143 -5
- package/internal/graph/line_model.go +122 -0
- package/internal/graph/member_relation_edges_follow_checker_validity_test.go +85 -0
- package/internal/graph/member_relation_edges_preserve_checker_boundaries_test.go +191 -0
- package/internal/graph/member_relation_edges_reject_checker_invalid_pairs_test.go +119 -0
- package/internal/graph/node_ids_preserve_hash_bearing_components_test.go +41 -0
- package/internal/graph/node_modifiers_emit_union_strings_test.go +4 -1
- package/internal/graph/object_literal_members_ride_on_the_snapshot_test.go +192 -0
- package/internal/graph/object_member_signatures_preserve_literal_whitespace_test.go +67 -0
- package/internal/graph/object_members.go +229 -0
- package/internal/graph/provenance.go +88 -30
- package/internal/graph/source_texts_cover_every_resident_program_source_test.go +73 -0
- package/internal/graphsymbols/position_helpers_follow_ecma_line_terminators_test.go +66 -0
- package/internal/graphsymbols/provider.go +26 -91
- package/internal/lspserver/lsp_clean_didopen_refreshes_compiler_state_test.go +144 -0
- package/internal/lspserver/lsp_completion.go +109 -0
- package/internal/lspserver/lsp_completion_gate_never_refuses_a_matching_line_test.go +50 -0
- package/internal/lspserver/lsp_completion_hints_longest_trigger_wins_test.go +149 -0
- package/internal/lspserver/lsp_completion_hints_nearest_trigger_wins_test.go +37 -0
- package/internal/lspserver/lsp_completion_merges_into_upstream_response_test.go +149 -0
- package/internal/lspserver/lsp_completion_nearest_hint_replaces_nearest_filter_test.go +43 -0
- package/internal/lspserver/lsp_completion_preserves_completion_list_extensions_test.go +99 -0
- package/internal/lspserver/lsp_completion_refuses_hints_inside_a_string_literal_test.go +69 -0
- package/internal/lspserver/lsp_completion_replaces_full_filter_in_rank_order_test.go +85 -0
- package/internal/lspserver/lsp_completion_request.go +455 -0
- package/internal/lspserver/lsp_completion_scope.go +530 -0
- package/internal/lspserver/lsp_completion_scope_bench_test.go +41 -0
- package/internal/lspserver/lsp_completion_scope_classifies_regex_statement_and_operator_boundaries_test.go +39 -0
- package/internal/lspserver/lsp_completion_scope_ignores_jsdoc_bytes_in_literals_test.go +108 -0
- package/internal/lspserver/lsp_completion_scope_refuses_regex_hints_test.go +52 -0
- package/internal/lspserver/lsp_completion_trigger_uses_last_rune_test.go +24 -0
- package/internal/lspserver/lsp_deleted_watched_file_withdraws_plugin_diagnostics_test.go +110 -0
- package/internal/lspserver/lsp_didsave_keeps_the_incremental_changed_uri_path_test.go +78 -0
- package/internal/lspserver/lsp_hints_absence_is_not_an_error_test.go +46 -0
- package/internal/lspserver/lsp_hints_refresh_coalesces_concurrent_requests_test.go +82 -0
- package/internal/lspserver/lsp_hints_refresh_ignores_a_superseded_generation_test.go +40 -0
- package/internal/lspserver/lsp_hints_refresh_keeps_each_producer_isolated_test.go +64 -0
- package/internal/lspserver/lsp_hints_refresh_replaces_the_session_snapshot_test.go +66 -0
- package/internal/lspserver/lsp_hints_refresh_scheduled_by_editor_events_test.go +90 -0
- package/internal/lspserver/lsp_hints_refresh_serves_completion_while_running_test.go +91 -0
- package/internal/lspserver/lsp_index_byte_from_bounds_its_search_start_test.go +38 -0
- package/internal/lspserver/lsp_initialize_constrains_position_encoding_to_utf16_test.go +205 -0
- package/internal/lspserver/lsp_late_completion_trigger_is_reported_once_test.go +105 -0
- package/internal/lspserver/lsp_native_completion_hints_decode_flat_lint_wire_test.go +66 -0
- package/internal/lspserver/lsp_native_completion_hints_grouped_compatibility_boundary_test.go +60 -0
- package/internal/lspserver/lsp_native_plugin_source.go +315 -2
- package/internal/lspserver/lsp_native_resident.go +304 -0
- package/internal/lspserver/lsp_plugin.go +85 -8
- package/internal/lspserver/lsp_plugin_completion_resolve_stays_local_test.go +82 -0
- package/internal/lspserver/lsp_position_conversions_span_astral_and_combining_runes_test.go +119 -0
- package/internal/lspserver/lsp_proxy.go +601 -9
- package/internal/lspserver/lsp_refresh.go +70 -0
- package/internal/lspserver/lsp_resident_falls_back_when_serve_unsupported_test.go +43 -0
- package/internal/lspserver/lsp_resident_maps_verb_args_test.go +34 -0
- package/internal/lspserver/lsp_server.go +13 -1
- package/internal/lspserver/lsp_watched_file_changes_reach_compiler_caches_test.go +172 -0
- package/lib/TtscCompiler.d.ts +3 -1
- package/lib/TtscCompiler.js +5 -1
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/TtscService.d.ts +13 -3
- package/lib/TtscService.js +6 -6
- package/lib/TtscService.js.map +1 -1
- package/lib/compiler/internal/project/readConfigJson.d.ts +30 -0
- package/lib/compiler/internal/project/readConfigJson.js +208 -0
- package/lib/compiler/internal/project/readConfigJson.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.js +53 -149
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/residentTransformProcess.d.ts +15 -2
- package/lib/compiler/internal/residentTransformProcess.js +159 -39
- package/lib/compiler/internal/residentTransformProcess.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +6 -0
- package/lib/compiler/internal/runBuild.js +143 -44
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/startResidentTransform.d.ts +5 -1
- package/lib/compiler/internal/startResidentTransform.js +3 -1
- package/lib/compiler/internal/startResidentTransform.js.map +1 -1
- package/lib/compiler/internal/transformProjectInMemory.js +12 -2
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/flags/parser.d.ts +19 -0
- package/lib/flags/parser.js +78 -36
- package/lib/flags/parser.js.map +1 -1
- package/lib/flags/schema.d.ts +49 -11
- package/lib/flags/schema.js +94 -22
- package/lib/flags/schema.js.map +1 -1
- package/lib/internal/assertSafeExplicitCacheDirectory.d.ts +5 -0
- package/lib/internal/assertSafeExplicitCacheDirectory.js +26 -0
- package/lib/internal/assertSafeExplicitCacheDirectory.js.map +1 -0
- package/lib/launcher/internal/runTtsc.js +107 -69
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtsx.js +28 -41
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/internal/runtimeHooks.d.ts +15 -0
- package/lib/launcher/internal/runtimeHooks.js +18 -1
- package/lib/launcher/internal/runtimeHooks.js.map +1 -1
- package/lib/launcher/internal/watchTopology.d.ts +43 -0
- package/lib/launcher/internal/watchTopology.js +360 -0
- package/lib/launcher/internal/watchTopology.js.map +1 -0
- package/lib/plugin/internal/buildSourcePlugin.d.ts +14 -3
- package/lib/plugin/internal/buildSourcePlugin.js +247 -61
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.js +63 -2
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerTransformation.d.ts +16 -0
- package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +2 -0
- package/package.json +8 -8
- package/shim/ast/shim.go +48 -3
- package/shim/astnav/go.mod +14 -0
- package/shim/astnav/go.sum +20 -0
- package/shim/astnav/shim.go +15 -0
- package/shim/checker/shim.go +100 -0
- package/shim/core/shim.go +47 -0
- package/shim/diagnosticwriter/lint.go +50 -0
- package/src/TtscCompiler.ts +5 -1
- package/src/TtscService.ts +37 -10
- package/src/compiler/internal/project/readConfigJson.ts +209 -0
- package/src/compiler/internal/project/readProjectConfig.ts +62 -158
- package/src/compiler/internal/residentTransformProcess.ts +197 -39
- package/src/compiler/internal/runBuild.ts +169 -47
- package/src/compiler/internal/startResidentTransform.ts +12 -1
- package/src/compiler/internal/transformProjectInMemory.ts +12 -1
- package/src/flags/parser.ts +113 -42
- package/src/flags/schema.ts +113 -31
- package/src/internal/assertSafeExplicitCacheDirectory.ts +29 -0
- package/src/launcher/internal/runTtsc.ts +117 -68
- package/src/launcher/internal/runTtsx.ts +29 -44
- package/src/launcher/internal/runtimeHooks.ts +30 -2
- package/src/launcher/internal/watchTopology.ts +466 -0
- package/src/plugin/internal/buildSourcePlugin.ts +326 -64
- package/src/plugin/internal/loadProjectPlugins.ts +80 -2
- package/src/structures/ITtscCompilerTransformation.ts +17 -0
- package/src/structures/internal/ITtscParsedProjectConfig.ts +2 -0
- package/tools/shim_audit/baseline.json +0 -3
- package/tools/shim_audit/main.go +42 -14
- package/tools/shim_audit/shim_dir_coverage_test.go +25 -0
- package/utility/flags_gen.go +3 -3
- package/utility/host.go +9 -3
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ A `typescript-go` toolchain for compiler-powered plugins and type-safe execution
|
|
|
8
8
|
|
|
9
9
|
- **`ttsc`**: build, check, and transform.
|
|
10
10
|
- **`ttsx`**: execute TypeScript with type checking.
|
|
11
|
-
- [**`@ttsc/lint`**](https://github.com/samchon/ttsc/tree/master/packages/lint): lint violations as compiler errors.
|
|
12
11
|
- [**`@ttsc/graph`**](https://github.com/samchon/ttsc/tree/master/packages/graph): MCP code graph that reduces agent token usage.
|
|
12
|
+
- [**`@ttsc/lint`**](https://github.com/samchon/ttsc/tree/master/packages/lint): lint violations as compiler errors.
|
|
13
13
|
- **plugin support**: compiler-powered libraries, such as `typia`.
|
|
14
14
|
|
|
15
15
|
## Setup
|
|
@@ -35,6 +35,33 @@ That covers the CLI. The integrations each have a short guide:
|
|
|
35
35
|
- [`@ttsc/metro`](https://ttsc.dev/docs/setup/metro): React Native and Expo.
|
|
36
36
|
- [`@ttsc/vscode`](https://ttsc.dev/docs/setup/vscode): live editor diagnostics.
|
|
37
37
|
|
|
38
|
+
## Graph
|
|
39
|
+
|
|
40
|
+
Your coding agent answers from the compiler, spending roughly 90% fewer tokens.
|
|
41
|
+
|
|
42
|
+
`@ttsc/graph` is an MCP server that gives the agent a compiler-resolved graph of your project: what calls what, what a change would touch, and where to start reading. The agent asks the type checker instead of grepping and re-reading files.
|
|
43
|
+
|
|
44
|
+
Register it with your MCP client. For Claude Code, a `.mcp.json` in the project root:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -D ttsc @ttsc/graph typescript
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"ttsc-graph": {
|
|
54
|
+
"command": "npx",
|
|
55
|
+
"args": ["-y", "@ttsc/graph"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
On the agent-cost benchmark, Claude agents answer reading zero files, cutting tokens by roughly 90% and tool calls by 93% to 96%. The design and per-repository numbers are in the [Code Graph guide](https://ttsc.dev/docs/graph) and the [benchmark](https://ttsc.dev/docs/benchmark/graph).
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
38
65
|
## Lint
|
|
39
66
|
|
|
40
67
|
Lint and format at compiler speed: up to 800x faster than ESLint.
|
|
@@ -75,15 +102,17 @@ let total = count;
|
|
|
75
102
|
|
|
76
103
|
```text
|
|
77
104
|
$ npx ttsc --noEmit
|
|
105
|
+
src/index.ts:1:1 - error TS11966: [no-var] Unexpected var, use let or const instead.
|
|
106
|
+
|
|
107
|
+
1 var count = 3;
|
|
108
|
+
~~~
|
|
109
|
+
|
|
78
110
|
src/index.ts:2:5 - error TS17397: [prefer-const] Use const instead of let.
|
|
79
111
|
|
|
80
112
|
2 let total = count;
|
|
81
|
-
|
|
113
|
+
~~~~~
|
|
82
114
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
1 var count = 3;
|
|
86
|
-
~~~~~~~~~~~~~~
|
|
115
|
+
Found 2 errors in the same file, starting at: src/index.ts:1
|
|
87
116
|
```
|
|
88
117
|
|
|
89
118
|
Clean the project in place:
|
|
@@ -95,33 +124,6 @@ npx ttsc format # format edits only, never changes behavior
|
|
|
95
124
|
|
|
96
125
|
The rule catalog and every `format` key are in the [Lint & Format guide](https://ttsc.dev/docs/lint).
|
|
97
126
|
|
|
98
|
-
## Graph
|
|
99
|
-
|
|
100
|
-
Your coding agent answers from the compiler, spending roughly 90% fewer tokens.
|
|
101
|
-
|
|
102
|
-
`@ttsc/graph` is an MCP server that gives the agent a compiler-resolved graph of your project: what calls what, what a change would touch, and where to start reading. The agent asks the type checker instead of grepping and re-reading files.
|
|
103
|
-
|
|
104
|
-
Register it with your MCP client. For Claude Code, a `.mcp.json` in the project root:
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
npm install -D ttsc @ttsc/graph typescript
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
```json
|
|
111
|
-
{
|
|
112
|
-
"mcpServers": {
|
|
113
|
-
"ttsc-graph": {
|
|
114
|
-
"command": "npx",
|
|
115
|
-
"args": ["-y", "@ttsc/graph"]
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
On the agent-cost benchmark, Claude agents answer reading zero files, cutting tokens by roughly 90% and tool calls by 93% to 96%. The design and per-repository numbers are in the [Code Graph guide](https://ttsc.dev/docs/graph) and the [benchmark](https://ttsc.dev/docs/benchmark/graph).
|
|
122
|
-
|
|
123
|
-

|
|
124
|
-
|
|
125
127
|
## Plugins
|
|
126
128
|
|
|
127
129
|
A plugin hooks the compile to add checks, transforms, or type-driven code generation, all driven by the types the checker has already resolved. It runs on every `ttsc` build and `ttsx` run, with no extra step.
|
|
@@ -146,8 +148,8 @@ export const isStringArray = (() => {
|
|
|
146
148
|
Utility plugins shipped in this repository:
|
|
147
149
|
|
|
148
150
|
- [`@ttsc/banner`](https://github.com/samchon/ttsc/tree/master/packages/banner): adds `@packageDocumentation` JSDoc banners.
|
|
149
|
-
- [`@ttsc/lint`](https://github.com/samchon/ttsc/tree/master/packages/lint): lints and formats TypeScript source.
|
|
150
151
|
- [`@ttsc/graph`](https://github.com/samchon/ttsc/tree/master/packages/graph): MCP server exposing a checker-resolved code graph to coding agents.
|
|
152
|
+
- [`@ttsc/lint`](https://github.com/samchon/ttsc/tree/master/packages/lint): lints and formats TypeScript source.
|
|
151
153
|
- [`@ttsc/paths`](https://github.com/samchon/ttsc/tree/master/packages/paths): rewrites source path aliases so JS and declaration emit receive relative imports.
|
|
152
154
|
- [`@ttsc/strip`](https://github.com/samchon/ttsc/tree/master/packages/strip): removes configured calls and `debugger` statements.
|
|
153
155
|
- [`@ttsc/unplugin`](https://github.com/samchon/ttsc/tree/master/packages/unplugin): runs `ttsc` plugins inside bundlers supported by `unplugin`.
|
package/cmd/graphdump/main.go
CHANGED
|
@@ -28,9 +28,8 @@ func run() int {
|
|
|
28
28
|
flag.Parse()
|
|
29
29
|
|
|
30
30
|
// Resolve the project root the same way LoadProgram does (absolute, then
|
|
31
|
-
// tsgo-normalized) so
|
|
32
|
-
//
|
|
33
|
-
// leave every path absolute.
|
|
31
|
+
// tsgo-normalized) so the schema-v6 mapper receives the same canonical root
|
|
32
|
+
// grammar and drive-letter case as the compiler's source paths.
|
|
34
33
|
root := *cwd
|
|
35
34
|
if abs, err := filepath.Abs(root); err == nil {
|
|
36
35
|
root = abs
|
|
@@ -60,7 +59,6 @@ func run() int {
|
|
|
60
59
|
// `ttscgraph dump` is the one that proves the whole contract.
|
|
61
60
|
data, err := graph.MarshalDump(g, root, *tsconfig, ignored, texts, graph.DumpOrigin{
|
|
62
61
|
Provenance: graph.NewProvenance(
|
|
63
|
-
root,
|
|
64
62
|
// No version: this tool is built from the tree on demand and never
|
|
65
63
|
// stamped, and an invented one would be worse than an absent one.
|
|
66
64
|
graph.Producer{Tool: "graphdump", Typescript: graph.TypescriptVersion()},
|
package/cmd/ttsc/filter.go
CHANGED
|
@@ -59,12 +59,20 @@ func filterHostArgs(args []string) []string {
|
|
|
59
59
|
return filtered
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
// splitFlagName strips the leading `--` from a flag argument
|
|
63
|
-
// whether the argument carries an inline value
|
|
62
|
+
// splitFlagName strips the leading `--` from a flag argument, lower-cases the
|
|
63
|
+
// result, and reports whether the argument carries an inline value
|
|
64
|
+
// (`--foo=value`).
|
|
65
|
+
//
|
|
66
|
+
// Lower-casing is the same normalization `normalizeFlagToken` in
|
|
67
|
+
// `packages/ttsc/src/flags/schema.ts` applies, and the generated
|
|
68
|
+
// `HostFlagAllowList` keys are produced by it. TypeScript's option parser
|
|
69
|
+
// matches option names case-insensitively, so keying this lookup on the exact
|
|
70
|
+
// spelling would make the Go layer stop recognising a flag the launcher and the
|
|
71
|
+
// compiler both resolve.
|
|
64
72
|
func splitFlagName(arg string) (string, bool) {
|
|
65
73
|
name := strings.TrimPrefix(arg, "--")
|
|
66
74
|
if i := strings.IndexByte(name, '='); i != -1 {
|
|
67
|
-
return name[:i], true
|
|
75
|
+
return strings.ToLower(name[:i]), true
|
|
68
76
|
}
|
|
69
|
-
return name, false
|
|
77
|
+
return strings.ToLower(name), false
|
|
70
78
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"reflect"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestFilterHostArgsResolvesFlagNamesCaseInsensitively verifies the host
|
|
9
|
+
// allow-list lookup applies the same flag-name normalization the schema uses
|
|
10
|
+
// when it generates that allow-list.
|
|
11
|
+
//
|
|
12
|
+
// TypeScript's option parser matches option names case-insensitively, and
|
|
13
|
+
// `normalizeFlagToken` in `packages/ttsc/src/flags/schema.ts` is the one
|
|
14
|
+
// normalization every layer keys off — including `buildGoAllowList`, whose
|
|
15
|
+
// output is `flags_gen.go`. Keying this lookup on the exact spelling while the
|
|
16
|
+
// generated keys are normalized would recreate the split-brain one layer
|
|
17
|
+
// further down: a flag the launcher and the compiler both resolve would be
|
|
18
|
+
// dropped here, silently taking the following token with it.
|
|
19
|
+
//
|
|
20
|
+
// 1. A case-variant known flag survives with its value.
|
|
21
|
+
// 2. A case-variant boolean known flag survives and does not eat the next token.
|
|
22
|
+
// 3. An unknown flag is still dropped in every casing, with its value.
|
|
23
|
+
func TestFilterHostArgsResolvesFlagNamesCaseInsensitively(t *testing.T) {
|
|
24
|
+
cases := []struct {
|
|
25
|
+
name string
|
|
26
|
+
in []string
|
|
27
|
+
want []string
|
|
28
|
+
}{
|
|
29
|
+
{
|
|
30
|
+
name: "keeps a case-variant value flag with its value",
|
|
31
|
+
in: []string{"--TSCONFIG", "tsconfig.json", "--CWD=."},
|
|
32
|
+
want: []string{"--TSCONFIG", "tsconfig.json", "--CWD=."},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "keeps a case-variant boolean flag without eating the next token",
|
|
36
|
+
in: []string{"--NOEMIT", "--tsconfig", "tsconfig.json"},
|
|
37
|
+
want: []string{"--NOEMIT", "--tsconfig", "tsconfig.json"},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "still drops an unknown flag in any casing",
|
|
41
|
+
in: []string{"--tsconfig=tsconfig.json", "--sTrIcT", "true"},
|
|
42
|
+
want: []string{"--tsconfig=tsconfig.json"},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
for _, tc := range cases {
|
|
46
|
+
t.Run(tc.name, func(t *testing.T) {
|
|
47
|
+
got := filterHostArgs(tc.in)
|
|
48
|
+
if !reflect.DeepEqual(got, tc.want) {
|
|
49
|
+
t.Fatalf("filterHostArgs(%v):\n want %v\n got %v", tc.in, tc.want, got)
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
package/cmd/ttsc/flags_gen.go
CHANGED
|
@@ -17,13 +17,13 @@ var HostFlagAllowList = map[string]bool{
|
|
|
17
17
|
"cwd": true,
|
|
18
18
|
"emit": false,
|
|
19
19
|
"manifest": true,
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"noemit": false,
|
|
21
|
+
"outdir": true,
|
|
22
22
|
"p": true,
|
|
23
23
|
"plugins-json": true,
|
|
24
24
|
"project": true,
|
|
25
25
|
"quiet": false,
|
|
26
|
-
"
|
|
26
|
+
"singlethreaded": false,
|
|
27
27
|
"tsconfig": true,
|
|
28
28
|
"tsgo-args": true,
|
|
29
29
|
"verbose": false,
|
package/cmd/ttscgraph/dump.go
CHANGED
|
@@ -37,9 +37,8 @@ func runDump(args []string) int {
|
|
|
37
37
|
cwd = resolved
|
|
38
38
|
}
|
|
39
39
|
// Resolve the project root the same way LoadProgram does (absolute, then
|
|
40
|
-
// tsgo-normalized) so
|
|
41
|
-
//
|
|
42
|
-
// leave every path absolute.
|
|
40
|
+
// tsgo-normalized) so the schema-v6 mapper receives the same canonical root
|
|
41
|
+
// grammar and drive-letter case as the compiler's source paths.
|
|
43
42
|
if abs, err := filepath.Abs(cwd); err == nil {
|
|
44
43
|
cwd = abs
|
|
45
44
|
}
|
|
@@ -60,7 +59,7 @@ func runDump(args []string) int {
|
|
|
60
59
|
g := graph.Build(prog)
|
|
61
60
|
ignored := graph.GitIgnoredFiles(cwd, g)
|
|
62
61
|
texts := graph.SourceTexts(prog)
|
|
63
|
-
origin, err := dumpOrigin(prog,
|
|
62
|
+
origin, err := dumpOrigin(prog, texts)
|
|
64
63
|
if err != nil {
|
|
65
64
|
fmt.Fprintf(stderr, "ttscgraph: %v\n", err)
|
|
66
65
|
return 1
|
|
@@ -90,7 +89,7 @@ func runDump(args []string) int {
|
|
|
90
89
|
// saw the project, so it carries the same provenance a served snapshot does:
|
|
91
90
|
// without it the file is a pile of facts with no way to tell which program, or
|
|
92
91
|
// which day, they describe.
|
|
93
|
-
func dumpOrigin(prog *driver.Program,
|
|
92
|
+
func dumpOrigin(prog *driver.Program, texts map[string]string) (graph.DumpOrigin, error) {
|
|
94
93
|
configs, err := parsedConfigs(prog)
|
|
95
94
|
if err != nil {
|
|
96
95
|
return graph.DumpOrigin{}, err
|
|
@@ -105,7 +104,6 @@ func dumpOrigin(prog *driver.Program, cwd string, texts map[string]string) (grap
|
|
|
105
104
|
}
|
|
106
105
|
return graph.DumpOrigin{
|
|
107
106
|
Provenance: graph.NewProvenance(
|
|
108
|
-
cwd,
|
|
109
107
|
serveProducer(),
|
|
110
108
|
fullSnapshotCapabilities,
|
|
111
109
|
fileDigests(configHashes),
|
|
@@ -113,6 +111,6 @@ func dumpOrigin(prog *driver.Program, cwd string, texts map[string]string) (grap
|
|
|
113
111
|
texts,
|
|
114
112
|
diskDigests,
|
|
115
113
|
),
|
|
116
|
-
Diagnostics: graph.NewDiagnostics(prog
|
|
114
|
+
Diagnostics: graph.NewDiagnostics(prog),
|
|
117
115
|
}, nil
|
|
118
116
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"encoding/json"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"testing"
|
|
8
|
+
|
|
9
|
+
"github.com/samchon/ttsc/packages/ttsc/internal/graph"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// TestRunDumpEmitsOnlyCheckerVerifiedMemberRelations verifies the shipped dump
|
|
13
|
+
// command serializes native member facts and does not revive a rejected pair.
|
|
14
|
+
//
|
|
15
|
+
// The graph reader no longer synthesizes member edges from equal names, so the
|
|
16
|
+
// command boundary must prove all three layers together: compiler diagnostics,
|
|
17
|
+
// native pair validation, and the public implements/overrides wire vocabulary.
|
|
18
|
+
//
|
|
19
|
+
// 1. Dump a program with one valid and one TS2416-invalid implementation.
|
|
20
|
+
// 2. Locate the container and member nodes in the serialized document.
|
|
21
|
+
// 3. Require the valid member edge and its evidence, reject the invalid edge,
|
|
22
|
+
// and ensure the internal native edge kind never reaches JSON.
|
|
23
|
+
func TestRunDumpEmitsOnlyCheckerVerifiedMemberRelations(t *testing.T) {
|
|
24
|
+
root := t.TempDir()
|
|
25
|
+
writeGraphFile(t, filepath.Join(root, "tsconfig.json"), `{
|
|
26
|
+
"compilerOptions": {
|
|
27
|
+
"target": "ES2022",
|
|
28
|
+
"module": "commonjs",
|
|
29
|
+
"strict": true,
|
|
30
|
+
"rootDir": "src",
|
|
31
|
+
"outDir": "dist"
|
|
32
|
+
},
|
|
33
|
+
"files": ["src/main.ts"]
|
|
34
|
+
}
|
|
35
|
+
`)
|
|
36
|
+
writeGraphFile(t, filepath.Join(root, "src", "main.ts"), `export interface Contract {
|
|
37
|
+
execute(input: number): void;
|
|
38
|
+
}
|
|
39
|
+
export class Good implements Contract {
|
|
40
|
+
execute(input: number): void {}
|
|
41
|
+
}
|
|
42
|
+
export class Bad implements Contract {
|
|
43
|
+
execute(input: string): void {}
|
|
44
|
+
}
|
|
45
|
+
`)
|
|
46
|
+
|
|
47
|
+
oldStdout, oldStderr := stdout, stderr
|
|
48
|
+
defer func() { stdout, stderr = oldStdout, oldStderr }()
|
|
49
|
+
var out, errBuf bytes.Buffer
|
|
50
|
+
stdout, stderr = &out, &errBuf
|
|
51
|
+
|
|
52
|
+
if code := run([]string{"dump", "--cwd", root, "--tsconfig", "tsconfig.json"}); code != 0 {
|
|
53
|
+
t.Fatalf("run dump exit = %d, want 0; stderr:\n%s", code, errBuf.String())
|
|
54
|
+
}
|
|
55
|
+
if bytes.Contains(out.Bytes(), []byte("member-relation")) {
|
|
56
|
+
t.Fatalf("internal edge kind leaked into the public dump:\n%s", out.String())
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
var dump graph.Dump
|
|
60
|
+
if err := json.Unmarshal(out.Bytes(), &dump); err != nil {
|
|
61
|
+
t.Fatalf("dump output is not valid JSON: %v\n%s", err, out.String())
|
|
62
|
+
}
|
|
63
|
+
seen2416 := false
|
|
64
|
+
for _, diagnostic := range dump.Diagnostics {
|
|
65
|
+
seen2416 = seen2416 || diagnostic.Code == 2416
|
|
66
|
+
}
|
|
67
|
+
if !seen2416 {
|
|
68
|
+
t.Fatalf("fixture must retain TS2416 in the same snapshot: %v", dump.Diagnostics)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
node := func(name, kind string) *graph.DumpNode {
|
|
72
|
+
t.Helper()
|
|
73
|
+
for i := range dump.Nodes {
|
|
74
|
+
candidate := &dump.Nodes[i]
|
|
75
|
+
declaredName := candidate.QualifiedName
|
|
76
|
+
if declaredName == "" {
|
|
77
|
+
declaredName = candidate.Name
|
|
78
|
+
}
|
|
79
|
+
if declaredName == name && candidate.Kind == kind {
|
|
80
|
+
return candidate
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
t.Fatalf("missing %s %s; nodes: %v", kind, name, dump.Nodes)
|
|
84
|
+
return nil
|
|
85
|
+
}
|
|
86
|
+
contract := node("Contract", "interface")
|
|
87
|
+
good := node("Good", "class")
|
|
88
|
+
contractExecute := node("Contract.execute", "method")
|
|
89
|
+
goodExecute := node("Good.execute", "method")
|
|
90
|
+
badExecute := node("Bad.execute", "method")
|
|
91
|
+
|
|
92
|
+
countEdge := func(from, to, kind string) int {
|
|
93
|
+
count := 0
|
|
94
|
+
for _, edge := range dump.Edges {
|
|
95
|
+
if edge.From == from && edge.To == to && edge.Kind == kind {
|
|
96
|
+
count++
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return count
|
|
100
|
+
}
|
|
101
|
+
if count := countEdge(good.ID, contract.ID, "implements"); count != 1 {
|
|
102
|
+
t.Fatalf("container implementation edge count = %d, want 1; edges: %v", count, dump.Edges)
|
|
103
|
+
}
|
|
104
|
+
if count := countEdge(goodExecute.ID, contractExecute.ID, "implements"); count != 1 {
|
|
105
|
+
t.Fatalf("valid member implementation edge count = %d, want 1; edges: %v", count, dump.Edges)
|
|
106
|
+
}
|
|
107
|
+
if count := countEdge(badExecute.ID, contractExecute.ID, "implements"); count != 0 {
|
|
108
|
+
t.Fatalf("checker-invalid member implementation edge count = %d, want 0; edges: %v", count, dump.Edges)
|
|
109
|
+
}
|
|
110
|
+
for _, edge := range dump.Edges {
|
|
111
|
+
if edge.From == goodExecute.ID && edge.To == contractExecute.ID && edge.Kind == "implements" {
|
|
112
|
+
if edge.Evidence == nil || goodExecute.Evidence == nil ||
|
|
113
|
+
edge.Evidence.StartLine != goodExecute.Evidence.StartLine {
|
|
114
|
+
t.Fatalf("member edge evidence does not identify Good.execute: edge=%v node=%v", edge.Evidence, goodExecute.Evidence)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|