ttsc 0.19.2 → 0.20.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 +7 -5
- 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 +312 -108
- 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_schema_version_matches_the_typescript_client_test.go +1 -1
- 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 +220 -5
- package/internal/graph/enum_members_carry_their_names_on_the_enum_node_test.go +131 -0
- package/internal/graph/graph.go +177 -5
- package/internal/graph/line_model.go +122 -0
- package/internal/graph/literals.go +175 -0
- package/internal/graph/literals_are_absent_when_the_type_admits_more_than_it_can_name_test.go +74 -0
- package/internal/graph/literals_cover_enum_members_the_graph_has_no_nodes_for_test.go +79 -0
- package/internal/graph/literals_do_not_depend_on_declaration_line_wrapping_test.go +84 -0
- package/internal/graph/literals_render_every_value_in_typescript_source_form_test.go +77 -0
- package/internal/graph/literals_resolve_through_alias_indirection_test.go +64 -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 +113 -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
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
package lspserver
|
|
2
|
+
|
|
3
|
+
import "sync"
|
|
4
|
+
|
|
5
|
+
// coalescingRefresh runs a background task at most once at a time, collapsing
|
|
6
|
+
// every request that arrives while a run is in flight into a single rerun.
|
|
7
|
+
//
|
|
8
|
+
// It exists because editor notifications arrive in bursts — a multi-file save,
|
|
9
|
+
// a watched-file rewrite, a settings change — while the task behind them costs a
|
|
10
|
+
// process spawn and a Program load. Running one per notification would stack
|
|
11
|
+
// those spawns; dropping the extras would leave the corpus a generation behind
|
|
12
|
+
// the edit that caused them. Coalescing keeps exactly one rerun, which is the
|
|
13
|
+
// smallest amount of work that still observes the newest state.
|
|
14
|
+
//
|
|
15
|
+
// Each run receives a strictly increasing generation so a writer can reject a
|
|
16
|
+
// result that a newer run has already superseded. The zero value is ready to
|
|
17
|
+
// use, and the task is supplied per schedule call so the owner does not have to
|
|
18
|
+
// wire it at construction.
|
|
19
|
+
type coalescingRefresh struct {
|
|
20
|
+
mu sync.Mutex
|
|
21
|
+
task func(generation uint64)
|
|
22
|
+
generation uint64
|
|
23
|
+
running bool
|
|
24
|
+
queued bool
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// schedule requests a run of task. It returns immediately: the run happens on
|
|
28
|
+
// its own goroutine, and a request made while a run is in flight becomes the one
|
|
29
|
+
// queued rerun rather than a second concurrent run.
|
|
30
|
+
func (r *coalescingRefresh) schedule(task func(generation uint64)) {
|
|
31
|
+
if task == nil {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
r.mu.Lock()
|
|
35
|
+
r.task = task
|
|
36
|
+
if r.running {
|
|
37
|
+
r.queued = true
|
|
38
|
+
r.mu.Unlock()
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
r.running = true
|
|
42
|
+
r.generation++
|
|
43
|
+
generation := r.generation
|
|
44
|
+
r.mu.Unlock()
|
|
45
|
+
go r.run(generation)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// run executes the task, then drains a queued request in the same goroutine so
|
|
49
|
+
// two cycles never overlap. Looping rather than spawning keeps the invariant the
|
|
50
|
+
// generation guard depends on: within one refresher, cycles are serial.
|
|
51
|
+
func (r *coalescingRefresh) run(generation uint64) {
|
|
52
|
+
for {
|
|
53
|
+
r.mu.Lock()
|
|
54
|
+
task := r.task
|
|
55
|
+
r.mu.Unlock()
|
|
56
|
+
if task != nil {
|
|
57
|
+
task(generation)
|
|
58
|
+
}
|
|
59
|
+
r.mu.Lock()
|
|
60
|
+
if !r.queued {
|
|
61
|
+
r.running = false
|
|
62
|
+
r.mu.Unlock()
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
r.queued = false
|
|
66
|
+
r.generation++
|
|
67
|
+
generation = r.generation
|
|
68
|
+
r.mu.Unlock()
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package lspserver
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"testing"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
// TestResidentFallsBackWhenServeUnsupported verifies a sidecar that cannot serve
|
|
9
|
+
// degrades to the spawn-per-verb path instead of losing the verb.
|
|
10
|
+
//
|
|
11
|
+
// Every sidecar built before lsp-serve rejects it, and a resident child can also
|
|
12
|
+
// fail to spawn; either way the read verb must still run. serveRun signals that
|
|
13
|
+
// by returning served=false so run() falls through to exec. It must also mark
|
|
14
|
+
// the binary unsupported after a first-spawn failure, or the source would
|
|
15
|
+
// spawn-and-fail per request forever.
|
|
16
|
+
//
|
|
17
|
+
// A binary that cannot be launched reaches the same spawn error as a sidecar
|
|
18
|
+
// that rejects the verb, so an unresolvable name is a faithful stand-in and
|
|
19
|
+
// keeps the test from needing a compiled fixture (mirrors the hint-absence
|
|
20
|
+
// test).
|
|
21
|
+
//
|
|
22
|
+
// 1. serveRun a read verb against a plugin whose binary cannot launch.
|
|
23
|
+
// 2. Assert it reports served=false (the caller falls back to exec).
|
|
24
|
+
// 3. Assert the binary is marked unsupported, and a second call short-circuits.
|
|
25
|
+
func TestResidentFallsBackWhenServeUnsupported(t *testing.T) {
|
|
26
|
+
source := &NativePluginSource{err: &bytes.Buffer{}}
|
|
27
|
+
plugin := NativeLSPPluginEntry{Binary: "ttsc-no-such-serve-binary", Name: "@ttsc/legacy"}
|
|
28
|
+
|
|
29
|
+
if _, served, _ := source.serveRun(plugin, serveVerbDiagnostics, []string{"--uri=file:///a.ts"}); served {
|
|
30
|
+
t.Fatal("a sidecar that cannot spawn must fall back to exec (served=false)")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
source.residentMu.Lock()
|
|
34
|
+
unsupported := source.serveUnsupported[plugin.Binary]
|
|
35
|
+
source.residentMu.Unlock()
|
|
36
|
+
if !unsupported {
|
|
37
|
+
t.Fatal("a first-spawn failure must mark lsp-serve unsupported so the source stops retrying")
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if _, served, _ := source.serveRun(plugin, serveVerbDiagnostics, []string{"--uri=file:///a.ts"}); served {
|
|
41
|
+
t.Fatal("a binary already marked unsupported must keep falling back")
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package lspserver
|
|
2
|
+
|
|
3
|
+
import "testing"
|
|
4
|
+
|
|
5
|
+
// TestResidentMapsVerbArgs verifies the resident client rebuilds a serve request
|
|
6
|
+
// from the same --flag=value argv the spawn-per-verb path passes.
|
|
7
|
+
//
|
|
8
|
+
// The two transports share one call shape at the source's verb methods:
|
|
9
|
+
// Diagnostics/CodeActions build `--uri=`, `--range-json=`, `--context-json=`
|
|
10
|
+
// argv, and serveRun must map those back into the request the daemon reads, or
|
|
11
|
+
// a code-action would arrive at the warm Program with no range and quietly
|
|
12
|
+
// offer nothing.
|
|
13
|
+
//
|
|
14
|
+
// 1. Map a code-actions argv carrying all three fields.
|
|
15
|
+
// 2. Assert each field lands, verbatim, including JSON payloads.
|
|
16
|
+
func TestResidentMapsVerbArgs(t *testing.T) {
|
|
17
|
+
req := serveRequestFromArgs("lsp-code-actions", []string{
|
|
18
|
+
"--uri=file:///a.ts",
|
|
19
|
+
`--range-json={"start":{"line":1,"character":2}}`,
|
|
20
|
+
`--context-json={"only":["quickfix.ttsc"]}`,
|
|
21
|
+
})
|
|
22
|
+
if req.Verb != "lsp-code-actions" {
|
|
23
|
+
t.Fatalf("verb = %q, want lsp-code-actions", req.Verb)
|
|
24
|
+
}
|
|
25
|
+
if req.URI != "file:///a.ts" {
|
|
26
|
+
t.Fatalf("uri = %q", req.URI)
|
|
27
|
+
}
|
|
28
|
+
if req.RangeJSON != `{"start":{"line":1,"character":2}}` {
|
|
29
|
+
t.Fatalf("rangeJson = %q", req.RangeJSON)
|
|
30
|
+
}
|
|
31
|
+
if req.ContextJSON != `{"only":["quickfix.ttsc"]}` {
|
|
32
|
+
t.Fatalf("contextJson = %q", req.ContextJSON)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -148,7 +148,10 @@ func defaultUpstreamRunner(ctx context.Context, in io.Reader, out io.Writer, opt
|
|
|
148
148
|
// RunLSPServer starts an upstream `tsgo --lsp --stdio` process and the byte-level
|
|
149
149
|
// proxy, blocking until either side returns. The first non-graceful
|
|
150
150
|
// error wins; ErrFrameClosed and context cancellation are treated as
|
|
151
|
-
// clean shutdown so editor close sequences do not look like crashes.
|
|
151
|
+
// clean shutdown so editor close sequences do not look like crashes. Once the
|
|
152
|
+
// editor has sent `exit`, an upstream runner failure joins that set: the
|
|
153
|
+
// upstream is required to terminate at that point, so its status no longer
|
|
154
|
+
// describes the session (see Proxy.editorRequestedExit).
|
|
152
155
|
//
|
|
153
156
|
// The lifecycle is:
|
|
154
157
|
//
|
|
@@ -231,6 +234,15 @@ func RunLSPServer(ctx context.Context, opts LSPServerOptions) error {
|
|
|
231
234
|
proxyErr = proxy.Run(serverCtx)
|
|
232
235
|
}()
|
|
233
236
|
wg.Wait()
|
|
237
|
+
proxy.shutdownResidentPlugins()
|
|
238
|
+
|
|
239
|
+
if proxy.editorRequestedExit() {
|
|
240
|
+
// The editor asked the server to quit, so the upstream process ending is
|
|
241
|
+
// the point rather than a fault. See Proxy.editorRequestedExit for why its
|
|
242
|
+
// status is not a reliable signal at that moment. Proxy errors still
|
|
243
|
+
// surface: those are ttsc's own.
|
|
244
|
+
serverErr = nil
|
|
245
|
+
}
|
|
234
246
|
|
|
235
247
|
for _, err := range []error{serverErr, proxyErr} {
|
|
236
248
|
if err == nil {
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
package lspserver
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"io"
|
|
6
|
+
"testing"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// watchedFilesSource records resident invalidations for the watched-file matrix.
|
|
10
|
+
type watchedFilesSource struct {
|
|
11
|
+
NullPluginSource
|
|
12
|
+
calls [][]string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func (s *watchedFilesSource) InvalidateResidentPrograms(uris ...string) {
|
|
16
|
+
s.calls = append(s.calls, append([]string(nil), uris...))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type watchedFilesSymbolProvider struct{ invalidations int }
|
|
20
|
+
|
|
21
|
+
func (p *watchedFilesSymbolProvider) DocumentSymbols(string) ([]LSPDocumentSymbol, error) {
|
|
22
|
+
return nil, nil
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func (p *watchedFilesSymbolProvider) References(string, LSPPosition, bool) ([]LSPLocation, error) {
|
|
26
|
+
return nil, nil
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func (p *watchedFilesSymbolProvider) Invalidate() { p.invalidations++ }
|
|
30
|
+
|
|
31
|
+
func watchedFilesEnvelope(t *testing.T, params string) Envelope {
|
|
32
|
+
t.Helper()
|
|
33
|
+
if !json.Valid([]byte(params)) {
|
|
34
|
+
t.Fatalf("invalid watched-file params: %s", params)
|
|
35
|
+
}
|
|
36
|
+
return Envelope{
|
|
37
|
+
JSONRPC: "2.0",
|
|
38
|
+
Method: methodDidChangeWatchedFiles,
|
|
39
|
+
Params: json.RawMessage(params),
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// TestLSPWatchedFileChangesReachCompilerCaches verifies that a
|
|
44
|
+
// workspace/didChangeWatchedFiles batch refreshes both compiler-backed caches,
|
|
45
|
+
// and that only a plain edit to a plain source file is refreshed incrementally.
|
|
46
|
+
//
|
|
47
|
+
// The repository's VS Code client watches `**/{tsconfig,jsconfig}*.json`, which
|
|
48
|
+
// its documentSelector excludes, so a config edit can reach ttsc through no other
|
|
49
|
+
// notification; before this the proxy had no arm for the method at all and the
|
|
50
|
+
// sidecar's documented full-reload fallback was unreachable. A created or deleted
|
|
51
|
+
// file and a config edit each reshape the root set or the compiler options, which
|
|
52
|
+
// tsgo's per-file UpdateProgram cannot express, so they must drop the warm
|
|
53
|
+
// Program rather than update it.
|
|
54
|
+
//
|
|
55
|
+
// 1. Send a `changed` event for one ordinary source file and assert the resident
|
|
56
|
+
// refresh carries exactly that URI.
|
|
57
|
+
// 2. Send a tsconfig edit, a created file, and a deleted file, and assert each
|
|
58
|
+
// drops the whole Program instead.
|
|
59
|
+
// 3. Send an undecodable batch (full reload) and an empty batch (no-op).
|
|
60
|
+
func TestLSPWatchedFileChangesReachCompilerCaches(t *testing.T) {
|
|
61
|
+
cases := []struct {
|
|
62
|
+
name string
|
|
63
|
+
params string
|
|
64
|
+
wantRes [][]string
|
|
65
|
+
wantSym int
|
|
66
|
+
}{
|
|
67
|
+
{
|
|
68
|
+
name: "changed source file is localized",
|
|
69
|
+
params: `{"changes":[{"uri":"file:///project/src/main.ts","type":2}]}`,
|
|
70
|
+
wantRes: [][]string{{"file:///project/src/main.ts"}},
|
|
71
|
+
wantSym: 1,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "several changed source files are localized together",
|
|
75
|
+
params: `{"changes":[{"uri":"file:///project/a.ts","type":2},{"uri":"file:///project/b.ts","type":2}]}`,
|
|
76
|
+
wantRes: [][]string{{"file:///project/a.ts", "file:///project/b.ts"}},
|
|
77
|
+
wantSym: 1,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
name: "tsconfig edit drops the whole program",
|
|
81
|
+
params: `{"changes":[{"uri":"file:///project/tsconfig.json","type":2}]}`,
|
|
82
|
+
wantRes: [][]string{{}},
|
|
83
|
+
wantSym: 1,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "scoped tsconfig edit drops the whole program",
|
|
87
|
+
params: `{"changes":[{"uri":"file:///project/tsconfig.build.json","type":2}]}`,
|
|
88
|
+
wantRes: [][]string{{}},
|
|
89
|
+
wantSym: 1,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: "jsconfig edit drops the whole program",
|
|
93
|
+
params: `{"changes":[{"uri":"file:///project/jsconfig.json","type":2}]}`,
|
|
94
|
+
wantRes: [][]string{{}},
|
|
95
|
+
wantSym: 1,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "created file drops the whole program",
|
|
99
|
+
params: `{"changes":[{"uri":"file:///project/src/added.ts","type":1}]}`,
|
|
100
|
+
wantRes: [][]string{{}},
|
|
101
|
+
wantSym: 1,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "deleted file drops the whole program",
|
|
105
|
+
params: `{"changes":[{"uri":"file:///project/src/gone.ts","type":3}]}`,
|
|
106
|
+
wantRes: [][]string{{}},
|
|
107
|
+
wantSym: 1,
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "one unlocalizable entry drops the whole batch",
|
|
111
|
+
params: `{"changes":[{"uri":"file:///project/a.ts","type":2},{"uri":"file:///project/tsconfig.json","type":2}]}`,
|
|
112
|
+
wantRes: [][]string{{}},
|
|
113
|
+
wantSym: 1,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: "a change with no type is not localizable",
|
|
117
|
+
params: `{"changes":[{"uri":"file:///project/a.ts"}]}`,
|
|
118
|
+
wantRes: [][]string{{}},
|
|
119
|
+
wantSym: 1,
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: "an undecodable batch drops the whole program",
|
|
123
|
+
params: `{"changes":"not-an-array"}`,
|
|
124
|
+
wantRes: [][]string{{}},
|
|
125
|
+
wantSym: 1,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: "an empty batch keeps every warm program",
|
|
129
|
+
params: `{"changes":[]}`,
|
|
130
|
+
wantRes: nil,
|
|
131
|
+
wantSym: 0,
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for _, testCase := range cases {
|
|
136
|
+
t.Run(testCase.name, func(t *testing.T) {
|
|
137
|
+
plugins := &watchedFilesSource{}
|
|
138
|
+
symbols := &watchedFilesSymbolProvider{}
|
|
139
|
+
proxy := NewProxy(ProxyOptions{
|
|
140
|
+
EditorOut: io.Discard,
|
|
141
|
+
UpstreamIn: io.Discard,
|
|
142
|
+
Source: plugins,
|
|
143
|
+
SymbolProvider: symbols,
|
|
144
|
+
})
|
|
145
|
+
handled, err := proxy.handleEditorEnvelope(watchedFilesEnvelope(t, testCase.params), nil)
|
|
146
|
+
if err != nil {
|
|
147
|
+
t.Fatalf("watched-file notification: %v", err)
|
|
148
|
+
}
|
|
149
|
+
if handled {
|
|
150
|
+
t.Fatal("watched-file notification was swallowed instead of forwarded to tsgo")
|
|
151
|
+
}
|
|
152
|
+
if symbols.invalidations != testCase.wantSym {
|
|
153
|
+
t.Errorf("symbol invalidations = %d, want %d", symbols.invalidations, testCase.wantSym)
|
|
154
|
+
}
|
|
155
|
+
if len(plugins.calls) != len(testCase.wantRes) {
|
|
156
|
+
t.Fatalf("resident invalidations = %v, want %v", plugins.calls, testCase.wantRes)
|
|
157
|
+
}
|
|
158
|
+
for index, want := range testCase.wantRes {
|
|
159
|
+
got := plugins.calls[index]
|
|
160
|
+
if len(got) != len(want) {
|
|
161
|
+
t.Fatalf("resident invalidation %d = %v, want %v", index, got, want)
|
|
162
|
+
}
|
|
163
|
+
for position := range want {
|
|
164
|
+
if got[position] != want[position] {
|
|
165
|
+
t.Errorf("resident invalidation %d = %v, want %v", index, got, want)
|
|
166
|
+
break
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
}
|
package/lib/TtscCompiler.d.ts
CHANGED
|
@@ -54,7 +54,9 @@ export declare class TtscCompiler {
|
|
|
54
54
|
* project-local caches. A user-provided `GOCACHE` is never removed. The cache
|
|
55
55
|
* location comes from this instance's `cacheDir` and environment
|
|
56
56
|
* (`TTSC_CACHE_DIR` / `TTSC_GO_CACHE_DIR`), defaulting to
|
|
57
|
-
* `<workspaceRoot>/node_modules/.cache/ttsc`.
|
|
57
|
+
* `<workspaceRoot>/node_modules/.cache/ttsc`. An explicit cache directory
|
|
58
|
+
* that equals or contains the project, or names a filesystem root, is
|
|
59
|
+
* rejected before any directory is removed.
|
|
58
60
|
*
|
|
59
61
|
* @returns Cache directories that were removed.
|
|
60
62
|
*/
|
package/lib/TtscCompiler.js
CHANGED
|
@@ -11,6 +11,7 @@ const resolveProjectConfig_1 = require("./compiler/internal/project/resolveProje
|
|
|
11
11
|
const resolveBinary_1 = require("./compiler/internal/resolveBinary");
|
|
12
12
|
const runBuild_1 = require("./compiler/internal/runBuild");
|
|
13
13
|
const transformProjectInMemory_1 = require("./compiler/internal/transformProjectInMemory");
|
|
14
|
+
const assertSafeExplicitCacheDirectory_1 = require("./internal/assertSafeExplicitCacheDirectory");
|
|
14
15
|
const buildSourcePlugin_1 = require("./plugin/internal/buildSourcePlugin");
|
|
15
16
|
const loadProjectPlugins_1 = require("./plugin/internal/loadProjectPlugins");
|
|
16
17
|
/**
|
|
@@ -87,7 +88,9 @@ class TtscCompiler {
|
|
|
87
88
|
* project-local caches. A user-provided `GOCACHE` is never removed. The cache
|
|
88
89
|
* location comes from this instance's `cacheDir` and environment
|
|
89
90
|
* (`TTSC_CACHE_DIR` / `TTSC_GO_CACHE_DIR`), defaulting to
|
|
90
|
-
* `<workspaceRoot>/node_modules/.cache/ttsc`.
|
|
91
|
+
* `<workspaceRoot>/node_modules/.cache/ttsc`. An explicit cache directory
|
|
92
|
+
* that equals or contains the project, or names a filesystem root, is
|
|
93
|
+
* rejected before any directory is removed.
|
|
91
94
|
*
|
|
92
95
|
* @returns Cache directories that were removed.
|
|
93
96
|
*/
|
|
@@ -99,6 +102,7 @@ class TtscCompiler {
|
|
|
99
102
|
];
|
|
100
103
|
const explicitCacheDir = this.resolveCacheDir();
|
|
101
104
|
if (explicitCacheDir !== undefined) {
|
|
105
|
+
(0, assertSafeExplicitCacheDirectory_1.assertSafeExplicitCacheDirectory)(projectRoot, explicitCacheDir);
|
|
102
106
|
// An explicit constructor `cacheDir` names the cache directory for this
|
|
103
107
|
// instance — exactly like `ttsc clean --cache-dir X` on the CLI — so
|
|
104
108
|
// remove it wholesale plus the legacy project-local caches. This keeps
|
package/lib/TtscCompiler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TtscCompiler.js","sourceRoot":"","sources":["../src/TtscCompiler.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAyB;AACzB,0DAA6B;AAE7B,uFAAoF;AACpF,2FAAwF;AACxF,qEAAkE;AAClE,2DAAuE;AACvE,2FAAwF;AACxF,2EAA0E;AAC1E,6EAA0E;AAO1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH;IACmB,OAAO,CAAuB;IAE/C;;;;;;OAMG;IACH,YAAmB,OAAO,GAAyB,EAAE;QACnD,IAAI,CAAC,OAAO,GAAG;YACb,GAAG,OAAO;YACV,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;YACjD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;gBACrC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;gBACtB,CAAC,CAAC,OAAO,CAAC,OAAO;SACpB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,OAAO;QACZ,MAAM,SAAS,GAAG,IAAI,CAAC,uBAAuB,EAAE,CAAC;QACjD,MAAM,MAAM,GAAG,IAAA,uCAAkB,EAAC;YAChC,MAAM,EAAE,IAAA,6BAAa,EAAC,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE;YACnD,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE;YACtC,GAAG,EAAE,SAAS,CAAC,GAAG;YAClB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC7B,GAAG,EAAE,IAAI,CAAC,mBAAmB,EAAE;YAC/B,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe;YAC7C,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,QAAQ,EAAE,SAAS,CAAC,QAAQ;SAC7B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"TtscCompiler.js","sourceRoot":"","sources":["../src/TtscCompiler.ts"],"names":[],"mappings":"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"}
|
package/lib/TtscService.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { ITtscCompilerContext } from "./structures/ITtscCompilerContext";
|
|
2
|
+
/** Construction controls for the resident transform request lifecycle. */
|
|
3
|
+
export interface TtscServiceOptions {
|
|
4
|
+
/** Maximum time one transform or update request may await the host's reply. */
|
|
5
|
+
requestTimeoutMs?: number;
|
|
6
|
+
}
|
|
7
|
+
/** Per-call controls for a resident transform or update request. */
|
|
8
|
+
export interface TtscServiceRequestOptions {
|
|
9
|
+
/** Abort this call before it receives a reply. */
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Resident, incremental transform service for the `ttsc` TypeScript-Go
|
|
4
14
|
* pipeline.
|
|
@@ -31,7 +41,7 @@ export declare class TtscService {
|
|
|
31
41
|
* host. The context is the same shape {@link TtscCompiler} accepts; it is not
|
|
32
42
|
* replaceable per call.
|
|
33
43
|
*/
|
|
34
|
-
constructor(context?: ITtscCompilerContext);
|
|
44
|
+
constructor(context?: ITtscCompilerContext, options?: TtscServiceOptions);
|
|
35
45
|
/**
|
|
36
46
|
* Return the transformed TypeScript source for one file, or `undefined` when
|
|
37
47
|
* the resident program does not contain it (for example a file excluded from
|
|
@@ -40,7 +50,7 @@ export declare class TtscService {
|
|
|
40
50
|
* Rejects when the resident host failed to compile the project; the rejection
|
|
41
51
|
* carries the host's diagnostics so callers can surface a real build error.
|
|
42
52
|
*/
|
|
43
|
-
transformFile(fileName: string): Promise<string | undefined>;
|
|
53
|
+
transformFile(fileName: string, options?: TtscServiceRequestOptions): Promise<string | undefined>;
|
|
44
54
|
/**
|
|
45
55
|
* Apply new in-memory content for one file and re-transform the project, so a
|
|
46
56
|
* subsequent {@link transformFile} reflects the edit without restarting the
|
|
@@ -48,7 +58,7 @@ export declare class TtscService {
|
|
|
48
58
|
* did not compile and the previous transform is still in effect. A relative
|
|
49
59
|
* `fileName` is resolved against the project root.
|
|
50
60
|
*/
|
|
51
|
-
updateFile(fileName: string, content: string): Promise<boolean>;
|
|
61
|
+
updateFile(fileName: string, content: string, options?: TtscServiceRequestOptions): Promise<boolean>;
|
|
52
62
|
/** Terminate the resident host and reject any in-flight requests. */
|
|
53
63
|
dispose(): void;
|
|
54
64
|
private absolutePath;
|
package/lib/TtscService.js
CHANGED
|
@@ -38,14 +38,14 @@ class TtscService {
|
|
|
38
38
|
* host. The context is the same shape {@link TtscCompiler} accepts; it is not
|
|
39
39
|
* replaceable per call.
|
|
40
40
|
*/
|
|
41
|
-
constructor(context = {}) {
|
|
41
|
+
constructor(context = {}, options = {}) {
|
|
42
42
|
const started = (0, startResidentTransform_1.startResidentTransform)({
|
|
43
43
|
...context,
|
|
44
44
|
env: context.env ? { ...context.env } : undefined,
|
|
45
45
|
plugins: Array.isArray(context.plugins)
|
|
46
46
|
? [...context.plugins]
|
|
47
47
|
: context.plugins,
|
|
48
|
-
});
|
|
48
|
+
}, options);
|
|
49
49
|
this.resident = started.process;
|
|
50
50
|
this.projectRoot = started.projectRoot;
|
|
51
51
|
}
|
|
@@ -57,8 +57,8 @@ class TtscService {
|
|
|
57
57
|
* Rejects when the resident host failed to compile the project; the rejection
|
|
58
58
|
* carries the host's diagnostics so callers can surface a real build error.
|
|
59
59
|
*/
|
|
60
|
-
async transformFile(fileName) {
|
|
61
|
-
const reply = await this.resident.request({ file: this.absolutePath(fileName) }, "transform");
|
|
60
|
+
async transformFile(fileName, options = {}) {
|
|
61
|
+
const reply = await this.resident.request({ file: this.absolutePath(fileName) }, "transform", options);
|
|
62
62
|
// The resident client already validated the reply shape (boolean `found`,
|
|
63
63
|
// string `typescript` when found), so a malformed or wrong-shape reply
|
|
64
64
|
// rejected instead of reaching here. `found: false` is the only path to
|
|
@@ -74,8 +74,8 @@ class TtscService {
|
|
|
74
74
|
* did not compile and the previous transform is still in effect. A relative
|
|
75
75
|
* `fileName` is resolved against the project root.
|
|
76
76
|
*/
|
|
77
|
-
async updateFile(fileName, content) {
|
|
78
|
-
const reply = await this.resident.request({ content, update: this.absolutePath(fileName) }, "update");
|
|
77
|
+
async updateFile(fileName, content, options = {}) {
|
|
78
|
+
const reply = await this.resident.request({ content, update: this.absolutePath(fileName) }, "update", options);
|
|
79
79
|
// The resident client validated the reply carries a boolean `updated`, so a
|
|
80
80
|
// malformed or wrong-shape reply rejected instead of collapsing to `false`.
|
|
81
81
|
// `false` here means only that the edit did not compile.
|
package/lib/TtscService.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TtscService.js","sourceRoot":"","sources":["../src/TtscService.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAG7B,uFAAoF;
|
|
1
|
+
{"version":3,"file":"TtscService.js","sourceRoot":"","sources":["../src/TtscService.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAG7B,uFAAoF;AAepF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;IACmB,QAAQ,CAA2B;IACnC,WAAW,CAAS;IAErC;;;;OAIG;IACH,YACE,OAAO,GAAyB,EAAE,EAClC,OAAO,GAAuB,EAAE;QAEhC,MAAM,OAAO,GAAG,IAAA,+CAAsB,EACpC;YACE,GAAG,OAAO;YACV,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;YACjD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;gBACrC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;gBACtB,CAAC,CAAC,OAAO,CAAC,OAAO;SACpB,EACD,OAAO,CACR,CAAC;QACF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACzC,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,aAAa,CACxB,QAAgB,EAChB,OAAO,GAA8B,EAAE;QAEvC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CACvC,EAAE,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,EACrC,WAAW,EACX,OAAO,CACR,CAAC;QACF,0EAA0E;QAC1E,uEAAuE;QACvE,wEAAwE;QACxE,uEAAuE;QACvE,OAAO,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;YACjE,CAAC,CAAC,KAAK,CAAC,UAAU;YAClB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,UAAU,CACrB,QAAgB,EAChB,OAAe,EACf,OAAO,GAA8B,EAAE;QAEvC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CACvC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,EAChD,QAAQ,EACR,OAAO,CACR,CAAC;QACF,4EAA4E;QAC5E,4EAA4E;QAC5E,yDAAyD;QACzD,OAAO,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC;IAChC,CAAC;IAED,qEAAqE;IAC9D,OAAO;QACZ,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC;IAEO,YAAY,CAAC,QAAgB;QACnC,OAAO,mBAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC9B,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,mBAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attributed JSON / JSONC readers for every configuration file ttsc owns.
|
|
3
|
+
*
|
|
4
|
+
* A bare `JSON.parse` failure reports a byte offset in an unnamed file, which
|
|
5
|
+
* is unusable exactly where attribution matters most: an `extends` chain, where
|
|
6
|
+
* any ancestor could be the source, and a watch session, which reprints the
|
|
7
|
+
* same line on every save. Every ttsc-owned configuration read goes through
|
|
8
|
+
* these helpers so the failure names its file and position in ttsc's own
|
|
9
|
+
* diagnostic voice, like the neighbouring `ttsc: extended tsconfig not found:
|
|
10
|
+
* …`.
|
|
11
|
+
*
|
|
12
|
+
* Comment, trailing-comma, and BOM removal is length-preserving (each removed
|
|
13
|
+
* character becomes a space, each removed newline stays a newline), so the line
|
|
14
|
+
* and column the JSON parser reports are the position in the file the user
|
|
15
|
+
* actually edited rather than in a shortened intermediate string.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Read and parse a strict-JSON configuration file (`package.json`), naming it
|
|
19
|
+
* on failure.
|
|
20
|
+
*
|
|
21
|
+
* A leading UTF-8 BOM is accepted, matching the tsconfig reader that closed
|
|
22
|
+
* issue #216: the two readers are consulted for the same project and
|
|
23
|
+
* disagreeing about a byte order mark would only surprise the user who hit it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function readJsonFile(file: string): unknown;
|
|
26
|
+
/**
|
|
27
|
+
* Read and parse a JSONC (JSON with comments and trailing commas) configuration
|
|
28
|
+
* file — tsconfig.json, jsconfig.json — naming it on failure.
|
|
29
|
+
*/
|
|
30
|
+
export declare function readJsoncFile(file: string): unknown;
|