@ripple-ts/language-server 0.3.104 → 0.3.106
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.
|
@@ -50,6 +50,8 @@ let path = require("path");
|
|
|
50
50
|
path = __toESM(path, 1);
|
|
51
51
|
let module$1 = require("module");
|
|
52
52
|
let url = require("url");
|
|
53
|
+
let node_path = require("node:path");
|
|
54
|
+
node_path = __toESM(node_path, 1);
|
|
53
55
|
let _tsrx_core = require("@tsrx/core");
|
|
54
56
|
let node_module = require("node:module");
|
|
55
57
|
let volar_service_css = require("volar-service-css");
|
|
@@ -713,6 +715,507 @@ var require_language_core = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
713
715
|
}
|
|
714
716
|
}));
|
|
715
717
|
|
|
718
|
+
//#endregion
|
|
719
|
+
//#region ../typescript-plugin/src/tsconfig-resolution.js
|
|
720
|
+
var import_language_core = require_language_core();
|
|
721
|
+
/**
|
|
722
|
+
* @typedef {object} TsconfigHost
|
|
723
|
+
* @property {(file_name: string) => boolean} fileExists
|
|
724
|
+
* @property {(file_name: string) => string | undefined} readFile
|
|
725
|
+
* @property {import('typescript').ParseConfigHost['readDirectory']} readDirectory
|
|
726
|
+
* @property {boolean | (() => boolean)} useCaseSensitiveFileNames
|
|
727
|
+
* @property {import('typescript').System['getModifiedTime']} [getModifiedTime]
|
|
728
|
+
*/
|
|
729
|
+
/**
|
|
730
|
+
* @typedef {object} TsconfigLayer
|
|
731
|
+
* @property {string} path
|
|
732
|
+
* @property {string} dir
|
|
733
|
+
* @property {Record<string, unknown>} config
|
|
734
|
+
* @property {string | undefined} raw_source
|
|
735
|
+
* @property {import('typescript').Diagnostic[]} parse_diagnostics
|
|
736
|
+
*/
|
|
737
|
+
/** @typedef {TsconfigLayer & { extends_values: unknown[] }} ParsedTsconfigLayer */
|
|
738
|
+
/**
|
|
739
|
+
* @typedef {object} TsconfigExtendsFailure
|
|
740
|
+
* @property {string} config_path
|
|
741
|
+
* @property {unknown} extends_value
|
|
742
|
+
* @property {string | undefined} resolved_path
|
|
743
|
+
* @property {import('typescript').Diagnostic[]} diagnostics
|
|
744
|
+
*/
|
|
745
|
+
/**
|
|
746
|
+
* @typedef {object} ResolvedTsconfigLayers
|
|
747
|
+
* @property {TsconfigLayer[]} layers
|
|
748
|
+
* @property {string[]} dependencies
|
|
749
|
+
* @property {import('typescript').Diagnostic[]} diagnostics
|
|
750
|
+
* @property {TsconfigExtendsFailure[]} extends_failures
|
|
751
|
+
*/
|
|
752
|
+
/**
|
|
753
|
+
* @template TValue
|
|
754
|
+
* @typedef {{state: 'absent'} | {state: 'found', value: TValue}} ConfigValueResult
|
|
755
|
+
*/
|
|
756
|
+
/** @typedef {{config_path: string, config_dir: string}} TsconfigValueOrigin */
|
|
757
|
+
const no_inputs_found_diagnostic_code = 18003;
|
|
758
|
+
const circularity_diagnostic_code = 18e3;
|
|
759
|
+
/**
|
|
760
|
+
* Load a tsconfig and its explicit inheritance graph from lowest to highest
|
|
761
|
+
* precedence. Parsed files are cached, but traversal intentionally does not
|
|
762
|
+
* deduplicate layers because a shared base must be reapplied in every branch.
|
|
763
|
+
*
|
|
764
|
+
* @param {typeof import('typescript')} ts
|
|
765
|
+
* @param {TsconfigHost} host
|
|
766
|
+
* @param {string} config_file_name
|
|
767
|
+
* @returns {ResolvedTsconfigLayers}
|
|
768
|
+
*/
|
|
769
|
+
function load_tsconfig_layers(ts, host, config_file_name) {
|
|
770
|
+
/** @type {Map<string, ParsedTsconfigLayer>} */
|
|
771
|
+
const parsed_file_cache = /* @__PURE__ */ new Map();
|
|
772
|
+
/** @type {TsconfigLayer[]} */
|
|
773
|
+
const layers = [];
|
|
774
|
+
/** @type {string[]} */
|
|
775
|
+
const dependencies = [];
|
|
776
|
+
const dependency_keys = /* @__PURE__ */ new Set();
|
|
777
|
+
/** @type {import('typescript').Diagnostic[]} */
|
|
778
|
+
const diagnostics = [];
|
|
779
|
+
/** @type {TsconfigExtendsFailure[]} */
|
|
780
|
+
const extends_failures = [];
|
|
781
|
+
const diagnostic_keys = /* @__PURE__ */ new Set();
|
|
782
|
+
const active_stack = /* @__PURE__ */ new Set();
|
|
783
|
+
const use_case_sensitive_file_names = typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames;
|
|
784
|
+
/** @type {import('typescript').ParseConfigHost} */
|
|
785
|
+
const parse_host = {
|
|
786
|
+
fileExists: host.fileExists,
|
|
787
|
+
readFile: host.readFile,
|
|
788
|
+
readDirectory: host.readDirectory,
|
|
789
|
+
useCaseSensitiveFileNames: use_case_sensitive_file_names
|
|
790
|
+
};
|
|
791
|
+
/** @param {string} file_name */
|
|
792
|
+
function normalize_path(file_name) {
|
|
793
|
+
return node_path.default.normalize(node_path.default.resolve(file_name));
|
|
794
|
+
}
|
|
795
|
+
/** @param {string} file_name */
|
|
796
|
+
function get_path_key(file_name) {
|
|
797
|
+
const normalized_path = normalize_path(file_name);
|
|
798
|
+
return use_case_sensitive_file_names ? normalized_path : normalized_path.toLowerCase();
|
|
799
|
+
}
|
|
800
|
+
/** @param {import('typescript').Diagnostic[]} next_diagnostics */
|
|
801
|
+
function add_diagnostics(next_diagnostics) {
|
|
802
|
+
for (const diagnostic of next_diagnostics) {
|
|
803
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
804
|
+
const key = `${diagnostic.code}\0${diagnostic.file?.fileName ?? ""}\0${diagnostic.start ?? ""}\0${message}`;
|
|
805
|
+
if (!diagnostic_keys.has(key)) {
|
|
806
|
+
diagnostic_keys.add(key);
|
|
807
|
+
diagnostics.push(diagnostic);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
/** @param {string} file_name */
|
|
812
|
+
function add_dependency(file_name) {
|
|
813
|
+
const normalized_path = normalize_path(file_name);
|
|
814
|
+
const key = get_path_key(normalized_path);
|
|
815
|
+
if (!dependency_keys.has(key)) {
|
|
816
|
+
dependency_keys.add(key);
|
|
817
|
+
dependencies.push(normalized_path);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* TypeScript does not expose a failed lookup path for extensionless relative
|
|
822
|
+
* extends entries. Preserve the conventional JSON candidate so creating it
|
|
823
|
+
* later invalidates both the mtime cache and the language-server project.
|
|
824
|
+
* @param {ParsedTsconfigLayer} parsed
|
|
825
|
+
* @param {unknown} extends_value
|
|
826
|
+
*/
|
|
827
|
+
function get_unresolved_relative_dependency(parsed, extends_value) {
|
|
828
|
+
if (typeof extends_value !== "string" || !node_path.default.isAbsolute(extends_value) && !extends_value.startsWith(".")) return;
|
|
829
|
+
const candidate_path = node_path.default.resolve(parsed.dir, extends_value);
|
|
830
|
+
return node_path.default.extname(candidate_path) === "" ? `${candidate_path}.json` : candidate_path;
|
|
831
|
+
}
|
|
832
|
+
/** @param {string} file_name */
|
|
833
|
+
function parse_file(file_name) {
|
|
834
|
+
const normalized_path = normalize_path(file_name);
|
|
835
|
+
const key = get_path_key(normalized_path);
|
|
836
|
+
const cached = parsed_file_cache.get(key);
|
|
837
|
+
if (cached) return cached;
|
|
838
|
+
const raw_source = host.readFile(normalized_path);
|
|
839
|
+
const source_file = ts.readJsonConfigFile(normalized_path, host.readFile);
|
|
840
|
+
/** @type {import('typescript').Diagnostic[]} */
|
|
841
|
+
const parse_diagnostics = [...source_file.parseDiagnostics];
|
|
842
|
+
const converted_config = ts.convertToObject(source_file, parse_diagnostics);
|
|
843
|
+
const config = converted_config !== null && typeof converted_config === "object" && !Array.isArray(converted_config) ? converted_config : {};
|
|
844
|
+
const extends_value = config.extends;
|
|
845
|
+
const extends_values = Array.isArray(extends_value) ? extends_value : extends_value !== void 0 ? [extends_value] : [];
|
|
846
|
+
const parsed = {
|
|
847
|
+
path: normalized_path,
|
|
848
|
+
dir: node_path.default.dirname(normalized_path),
|
|
849
|
+
config,
|
|
850
|
+
raw_source,
|
|
851
|
+
parse_diagnostics,
|
|
852
|
+
extends_values
|
|
853
|
+
};
|
|
854
|
+
parsed_file_cache.set(key, parsed);
|
|
855
|
+
add_diagnostics(parse_diagnostics);
|
|
856
|
+
return parsed;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Resolve one immediate extends entry with TypeScript's own config resolver.
|
|
860
|
+
* A synthetic config isolates the edge; inherited files remain available to
|
|
861
|
+
* TypeScript so relative, absolute, package, optional-suffix, and cycle
|
|
862
|
+
* semantics stay aligned with parseJsonSourceFileConfigFileContent.
|
|
863
|
+
*
|
|
864
|
+
* @param {ParsedTsconfigLayer} parsed
|
|
865
|
+
* @param {unknown} extends_value
|
|
866
|
+
*/
|
|
867
|
+
function resolve_extends_path(parsed, extends_value) {
|
|
868
|
+
const synthetic_source = JSON.stringify({
|
|
869
|
+
extends: extends_value,
|
|
870
|
+
files: []
|
|
871
|
+
});
|
|
872
|
+
const source_file = ts.readJsonConfigFile(parsed.path, () => synthetic_source);
|
|
873
|
+
const edge_diagnostics = ts.parseJsonSourceFileConfigFileContent(source_file, parse_host, parsed.dir, {}, parsed.path).errors.filter((diagnostic) => diagnostic.code !== no_inputs_found_diagnostic_code);
|
|
874
|
+
add_diagnostics(edge_diagnostics);
|
|
875
|
+
const resolved_path = source_file.extendedSourceFiles?.[0];
|
|
876
|
+
const dependency_path = resolved_path ?? get_unresolved_relative_dependency(parsed, extends_value);
|
|
877
|
+
if (dependency_path !== void 0) add_dependency(dependency_path);
|
|
878
|
+
const has_cycle = edge_diagnostics.some((diagnostic) => diagnostic.code === circularity_diagnostic_code);
|
|
879
|
+
const is_unresolved = resolved_path === void 0 || !host.fileExists(resolved_path);
|
|
880
|
+
if (is_unresolved || has_cycle) extends_failures.push({
|
|
881
|
+
config_path: parsed.path,
|
|
882
|
+
extends_value,
|
|
883
|
+
resolved_path: dependency_path,
|
|
884
|
+
diagnostics: edge_diagnostics
|
|
885
|
+
});
|
|
886
|
+
return is_unresolved ? void 0 : resolved_path;
|
|
887
|
+
}
|
|
888
|
+
/** @param {string} file_name */
|
|
889
|
+
function visit(file_name) {
|
|
890
|
+
const normalized_path = normalize_path(file_name);
|
|
891
|
+
const key = get_path_key(normalized_path);
|
|
892
|
+
if (active_stack.has(key)) return;
|
|
893
|
+
active_stack.add(key);
|
|
894
|
+
add_dependency(normalized_path);
|
|
895
|
+
const parsed = parse_file(normalized_path);
|
|
896
|
+
for (const extends_value of parsed.extends_values) {
|
|
897
|
+
const extended_path = resolve_extends_path(parsed, extends_value);
|
|
898
|
+
if (extended_path !== void 0) visit(extended_path);
|
|
899
|
+
}
|
|
900
|
+
layers.push({
|
|
901
|
+
path: parsed.path,
|
|
902
|
+
dir: parsed.dir,
|
|
903
|
+
config: parsed.config,
|
|
904
|
+
raw_source: parsed.raw_source,
|
|
905
|
+
parse_diagnostics: parsed.parse_diagnostics
|
|
906
|
+
});
|
|
907
|
+
active_stack.delete(key);
|
|
908
|
+
}
|
|
909
|
+
visit(config_file_name);
|
|
910
|
+
return {
|
|
911
|
+
layers,
|
|
912
|
+
dependencies,
|
|
913
|
+
diagnostics,
|
|
914
|
+
extends_failures
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Read a nested config value only when every segment is an own property.
|
|
919
|
+
*
|
|
920
|
+
* @param {unknown} config
|
|
921
|
+
* @param {readonly PropertyKey[]} path_parts
|
|
922
|
+
* @returns {ConfigValueResult<unknown>}
|
|
923
|
+
*/
|
|
924
|
+
function get_own_config_value(config, path_parts) {
|
|
925
|
+
let current = config;
|
|
926
|
+
for (const path_part of path_parts) {
|
|
927
|
+
if (current === null || typeof current !== "object" && typeof current !== "function" || !Object.prototype.hasOwnProperty.call(current, path_part)) return { state: "absent" };
|
|
928
|
+
current = current[path_part];
|
|
929
|
+
}
|
|
930
|
+
return {
|
|
931
|
+
state: "found",
|
|
932
|
+
value: current
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Resolve a caller-defined value across layers. The last result whose state is
|
|
937
|
+
* not absent wins and is annotated with the config that declared it.
|
|
938
|
+
*
|
|
939
|
+
* @template {{state: string}} TResult
|
|
940
|
+
* @param {readonly TsconfigLayer[]} layers
|
|
941
|
+
* @param {(layer: TsconfigLayer) => TResult} read_layer
|
|
942
|
+
* @returns {{state: 'absent'} | (TResult & TsconfigValueOrigin)}
|
|
943
|
+
*/
|
|
944
|
+
function resolve_inherited_config_value(layers, read_layer) {
|
|
945
|
+
/** @type {{state: 'absent'} | (TResult & TsconfigValueOrigin)} */
|
|
946
|
+
let resolved = { state: "absent" };
|
|
947
|
+
for (const layer of layers) {
|
|
948
|
+
const value = read_layer(layer);
|
|
949
|
+
if (value.state !== "absent") resolved = {
|
|
950
|
+
...value,
|
|
951
|
+
config_path: layer.path,
|
|
952
|
+
config_dir: layer.dir
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
return resolved;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
//#endregion
|
|
959
|
+
//#region ../typescript-plugin/src/consumer-compiler.js
|
|
960
|
+
/** @typedef {{actual_type: string, actual_value: string}} InvalidConfigValueDetails */
|
|
961
|
+
/**
|
|
962
|
+
* @typedef {
|
|
963
|
+
* | {state: 'absent'}
|
|
964
|
+
* | {state: 'declared', value: string}
|
|
965
|
+
* | ({state: 'invalid', target: 'tsrx' | 'compiler'} & InvalidConfigValueDetails)
|
|
966
|
+
* } CompilerDeclaration
|
|
967
|
+
*/
|
|
968
|
+
/**
|
|
969
|
+
* @typedef {object} CompilerResolutionOptions
|
|
970
|
+
* @property {typeof import('typescript')} [ts]
|
|
971
|
+
* @property {string} [configFileName]
|
|
972
|
+
* @property {import('./tsconfig-resolution.js').TsconfigHost} [configHost]
|
|
973
|
+
* @property {Set<string>} [dependencies]
|
|
974
|
+
*/
|
|
975
|
+
/**
|
|
976
|
+
* @typedef {object} ConfigHostResolutionCache
|
|
977
|
+
* @property {Map<string, string | null>} nearest_config_paths
|
|
978
|
+
* @property {Map<string, CachedTsconfigLayers>} resolved_config_layers
|
|
979
|
+
*/
|
|
980
|
+
/**
|
|
981
|
+
* @typedef {object} CachedTsconfigLayers
|
|
982
|
+
* @property {import('./tsconfig-resolution.js').ResolvedTsconfigLayers} value
|
|
983
|
+
* @property {Map<string, number | undefined> | undefined} dependency_modified_times
|
|
984
|
+
*/
|
|
985
|
+
const { log: log$10, logError: logError$5, logWarning: logWarning$1 } = createLogging("[Ripple Language]");
|
|
986
|
+
const bare_package_specifier_pattern = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*(?:\/[A-Za-z0-9][A-Za-z0-9._~-]*)*$/;
|
|
987
|
+
const tsrx_key_pattern = /["']tsrx["']\s*:/;
|
|
988
|
+
/** @type {WeakMap<object, ConfigHostResolutionCache>} */
|
|
989
|
+
let config_host_to_resolution_cache = /* @__PURE__ */ new WeakMap();
|
|
990
|
+
/** @type {Map<string, string | null>} */
|
|
991
|
+
const declared_compiler_path_map = /* @__PURE__ */ new Map();
|
|
992
|
+
/**
|
|
993
|
+
* @param {unknown} value
|
|
994
|
+
* @returns {{ actual_type: string, actual_value: string }}
|
|
995
|
+
*/
|
|
996
|
+
function describe_config_value(value) {
|
|
997
|
+
return {
|
|
998
|
+
actual_type: value === null ? "null" : Array.isArray(value) ? "array" : typeof value,
|
|
999
|
+
actual_value: JSON.stringify(value) ?? String(value)
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Keep filesystem-derived config caches isolated per TypeScript/Volar host.
|
|
1004
|
+
* Different hosts can expose different snapshots for the same absolute path.
|
|
1005
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1006
|
+
*/
|
|
1007
|
+
function get_config_host_cache(host) {
|
|
1008
|
+
let cache = config_host_to_resolution_cache.get(host);
|
|
1009
|
+
if (!cache) {
|
|
1010
|
+
cache = {
|
|
1011
|
+
nearest_config_paths: /* @__PURE__ */ new Map(),
|
|
1012
|
+
resolved_config_layers: /* @__PURE__ */ new Map()
|
|
1013
|
+
};
|
|
1014
|
+
config_host_to_resolution_cache.set(host, cache);
|
|
1015
|
+
}
|
|
1016
|
+
return cache;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* @param {string} file_name
|
|
1020
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1021
|
+
*/
|
|
1022
|
+
function get_config_cache_key(file_name, host) {
|
|
1023
|
+
const normalized_path = path.default.normalize(path.default.resolve(file_name));
|
|
1024
|
+
return (typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames) ? normalized_path : normalized_path.toLowerCase();
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* @param {unknown} config
|
|
1028
|
+
* @returns {CompilerDeclaration}
|
|
1029
|
+
*/
|
|
1030
|
+
function get_compiler_declaration(config) {
|
|
1031
|
+
const tsrx_result = get_own_config_value(config, ["tsrx"]);
|
|
1032
|
+
if (tsrx_result.state === "absent") return { state: "absent" };
|
|
1033
|
+
const tsrx_value = tsrx_result.value;
|
|
1034
|
+
if (tsrx_value === null || typeof tsrx_value !== "object" || Array.isArray(tsrx_value)) return {
|
|
1035
|
+
state: "invalid",
|
|
1036
|
+
target: "tsrx",
|
|
1037
|
+
...describe_config_value(tsrx_value)
|
|
1038
|
+
};
|
|
1039
|
+
const compiler_result = get_own_config_value(tsrx_value, ["compiler"]);
|
|
1040
|
+
if (compiler_result.state === "absent") return { state: "absent" };
|
|
1041
|
+
const compiler = compiler_result.value;
|
|
1042
|
+
if (typeof compiler === "string" && compiler.trim() !== "") return {
|
|
1043
|
+
state: "declared",
|
|
1044
|
+
value: compiler.trim()
|
|
1045
|
+
};
|
|
1046
|
+
return {
|
|
1047
|
+
state: "invalid",
|
|
1048
|
+
target: "compiler",
|
|
1049
|
+
...describe_config_value(compiler)
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Find the nearest tsconfig.json to use as the root of inheritance resolution.
|
|
1054
|
+
* @param {string} start_dir
|
|
1055
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1056
|
+
* @param {ConfigHostResolutionCache} cache
|
|
1057
|
+
* @returns {string | null}
|
|
1058
|
+
*/
|
|
1059
|
+
function get_nearest_root_tsconfig(start_dir, host, cache) {
|
|
1060
|
+
let current_dir = start_dir;
|
|
1061
|
+
/** @type {string[]} */
|
|
1062
|
+
const visited_dir_keys = [];
|
|
1063
|
+
while (current_dir) {
|
|
1064
|
+
const current_dir_key = get_config_cache_key(current_dir, host);
|
|
1065
|
+
if (cache.nearest_config_paths.has(current_dir_key)) {
|
|
1066
|
+
const cached_tsconfig = cache.nearest_config_paths.get(current_dir_key) ?? null;
|
|
1067
|
+
for (const visited_dir_key of visited_dir_keys) cache.nearest_config_paths.set(visited_dir_key, cached_tsconfig);
|
|
1068
|
+
return cached_tsconfig;
|
|
1069
|
+
}
|
|
1070
|
+
visited_dir_keys.push(current_dir_key);
|
|
1071
|
+
const tsconfig_path = path.default.join(current_dir, "tsconfig.json");
|
|
1072
|
+
if (host.fileExists(tsconfig_path)) {
|
|
1073
|
+
for (const visited_dir_key of visited_dir_keys) cache.nearest_config_paths.set(visited_dir_key, tsconfig_path);
|
|
1074
|
+
return tsconfig_path;
|
|
1075
|
+
}
|
|
1076
|
+
const parent_dir = path.default.dirname(current_dir);
|
|
1077
|
+
if (parent_dir === current_dir) break;
|
|
1078
|
+
current_dir = parent_dir;
|
|
1079
|
+
}
|
|
1080
|
+
for (const visited_dir_key of visited_dir_keys) cache.nearest_config_paths.set(visited_dir_key, null);
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* @param {typeof import('typescript')} typescript
|
|
1085
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1086
|
+
* @param {string} root_config_path
|
|
1087
|
+
* @param {ConfigHostResolutionCache} cache
|
|
1088
|
+
*/
|
|
1089
|
+
function get_tsconfig_layers(typescript$2, host, root_config_path, cache) {
|
|
1090
|
+
const cache_key = get_config_cache_key(root_config_path, host);
|
|
1091
|
+
const cached = cache.resolved_config_layers.get(cache_key);
|
|
1092
|
+
if (cached && (cached.dependency_modified_times === void 0 || [...cached.dependency_modified_times].every(([dependency, modified_time]) => host.getModifiedTime?.(dependency)?.valueOf() === modified_time))) return cached.value;
|
|
1093
|
+
const value = load_tsconfig_layers(typescript$2, host, root_config_path);
|
|
1094
|
+
const dependency_modified_times = host.getModifiedTime ? new Map(value.dependencies.map((dependency) => [dependency, host.getModifiedTime?.(dependency)?.valueOf()])) : void 0;
|
|
1095
|
+
cache.resolved_config_layers.set(cache_key, {
|
|
1096
|
+
value,
|
|
1097
|
+
dependency_modified_times
|
|
1098
|
+
});
|
|
1099
|
+
return value;
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* A declaration in the config that owns a failed extends entry, or in a child
|
|
1103
|
+
* config above it, has higher precedence than anything the missing base could
|
|
1104
|
+
* have declared and therefore makes that failure irrelevant to this value.
|
|
1105
|
+
* @param {readonly import('./tsconfig-resolution.js').TsconfigLayer[]} layers
|
|
1106
|
+
* @param {import('./tsconfig-resolution.js').TsconfigExtendsFailure} failure
|
|
1107
|
+
* @param {string} declaration_config_path
|
|
1108
|
+
*/
|
|
1109
|
+
function is_extends_failure_overridden(layers, failure, declaration_config_path) {
|
|
1110
|
+
const failure_owner_index = layers.findLastIndex((layer) => layer.path === failure.config_path);
|
|
1111
|
+
const declaration_index = layers.findLastIndex((layer) => layer.path === declaration_config_path);
|
|
1112
|
+
return failure_owner_index >= 0 && declaration_index >= failure_owner_index;
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* Resolve without a module-resolution cache. This is the recovery path when
|
|
1116
|
+
* Node retains a negative package lookup after a dependency is installed.
|
|
1117
|
+
* `noDtsResolution` ensures the runtime entry wins over a package's types.
|
|
1118
|
+
* @param {typeof import('typescript')} typescript
|
|
1119
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1120
|
+
* @param {string} config_path
|
|
1121
|
+
* @param {string} specifier
|
|
1122
|
+
*/
|
|
1123
|
+
function resolve_uncached_declared_compiler(typescript$3, host, config_path, specifier) {
|
|
1124
|
+
return typescript$3.resolveModuleName(specifier, config_path, {
|
|
1125
|
+
module: typescript$3.ModuleKind.Node16,
|
|
1126
|
+
moduleResolution: typescript$3.ModuleResolutionKind.Node16,
|
|
1127
|
+
noDtsResolution: true
|
|
1128
|
+
}, host, void 0, void 0, typescript$3.ModuleKind.CommonJS).resolvedModule?.resolvedFileName;
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Resolve the compiler explicitly selected by a consumer tsconfig. Invalid
|
|
1132
|
+
* specifiers are stable and cached, while missing packages are retried so
|
|
1133
|
+
* tsserver can recover after the dependency is installed.
|
|
1134
|
+
* @param {typeof import('typescript')} typescript
|
|
1135
|
+
* @param {import('./tsconfig-resolution.js').TsconfigHost} host
|
|
1136
|
+
* @param {string} config_path
|
|
1137
|
+
* @param {string} specifier
|
|
1138
|
+
* @returns {string | null}
|
|
1139
|
+
*/
|
|
1140
|
+
function resolve_declared_compiler(typescript$4, host, config_path, specifier) {
|
|
1141
|
+
const cache_key = `${config_path}\0${specifier}`;
|
|
1142
|
+
if (declared_compiler_path_map.has(cache_key)) return declared_compiler_path_map.get(cache_key) ?? null;
|
|
1143
|
+
if (!bare_package_specifier_pattern.test(specifier)) {
|
|
1144
|
+
declared_compiler_path_map.set(cache_key, null);
|
|
1145
|
+
logError$5("Declared TSRX compiler must be a bare package specifier:", specifier, `in ${config_path}`);
|
|
1146
|
+
return null;
|
|
1147
|
+
}
|
|
1148
|
+
try {
|
|
1149
|
+
const compiler_path = (0, module$1.createRequire)(config_path).resolve(specifier);
|
|
1150
|
+
declared_compiler_path_map.set(cache_key, compiler_path);
|
|
1151
|
+
log$10("Found declared tsrx compiler at:", compiler_path, "from tsconfig:", config_path);
|
|
1152
|
+
return compiler_path;
|
|
1153
|
+
} catch {
|
|
1154
|
+
const compiler_path = resolve_uncached_declared_compiler(typescript$4, host, config_path, specifier);
|
|
1155
|
+
if (compiler_path !== void 0) {
|
|
1156
|
+
declared_compiler_path_map.set(cache_key, compiler_path);
|
|
1157
|
+
log$10("Found declared tsrx compiler after uncached retry at:", compiler_path, "from tsconfig:", config_path);
|
|
1158
|
+
return compiler_path;
|
|
1159
|
+
}
|
|
1160
|
+
logError$5(`Unable to resolve declared TSRX compiler "${specifier}" from tsconfig`, config_path);
|
|
1161
|
+
return null;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Return undefined when there is no consumer declaration, null for a declared
|
|
1166
|
+
* hard stop, or the resolved compiler path for a valid declaration.
|
|
1167
|
+
* @param {string} normalized_file_name
|
|
1168
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1169
|
+
* @returns {string | null | undefined}
|
|
1170
|
+
*/
|
|
1171
|
+
function resolve_consumer_compiler_for_file(normalized_file_name, options = {}) {
|
|
1172
|
+
const typescript$5 = options.ts ?? typescript.default;
|
|
1173
|
+
const config_host = options.configHost ?? typescript$5.sys;
|
|
1174
|
+
const host_cache = get_config_host_cache(config_host);
|
|
1175
|
+
const root_config_path = options.configFileName ?? get_nearest_root_tsconfig(path.default.dirname(normalized_file_name), config_host, host_cache);
|
|
1176
|
+
if (root_config_path === null) return;
|
|
1177
|
+
const resolved_layers = get_tsconfig_layers(typescript$5, config_host, root_config_path, host_cache);
|
|
1178
|
+
for (const dependency of resolved_layers.dependencies) options.dependencies?.add(dependency);
|
|
1179
|
+
const unreadable_layers = resolved_layers.layers.filter((layer) => layer.raw_source === void 0);
|
|
1180
|
+
if (unreadable_layers.length > 0) {
|
|
1181
|
+
for (const layer of unreadable_layers) logError$5("Unable to read tsconfig layer:", layer.path);
|
|
1182
|
+
return null;
|
|
1183
|
+
}
|
|
1184
|
+
const malformed_layers = resolved_layers.layers.filter((layer) => layer.parse_diagnostics.length > 0);
|
|
1185
|
+
if (malformed_layers.length > 0) {
|
|
1186
|
+
const has_tsrx_intent = resolved_layers.layers.some((layer) => {
|
|
1187
|
+
if (get_own_config_value(layer.config, ["tsrx"]).state === "found") return true;
|
|
1188
|
+
if (layer.parse_diagnostics.length === 0 || layer.raw_source === void 0) return false;
|
|
1189
|
+
return tsrx_key_pattern.test(layer.raw_source);
|
|
1190
|
+
});
|
|
1191
|
+
const log_parse_error = has_tsrx_intent ? logError$5 : logWarning$1;
|
|
1192
|
+
for (const layer of malformed_layers) for (const diagnostic of layer.parse_diagnostics) log_parse_error("Unable to parse tsconfig layer:", layer.path, typescript$5.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
|
|
1193
|
+
return has_tsrx_intent ? null : void 0;
|
|
1194
|
+
}
|
|
1195
|
+
const declaration = resolve_inherited_config_value(resolved_layers.layers, (layer) => get_compiler_declaration(layer.config));
|
|
1196
|
+
if (declaration.state === "invalid") {
|
|
1197
|
+
logError$5(`Invalid TSRX ${declaration.target} declaration:`, declaration.actual_type, declaration.actual_value, `in ${declaration.config_path}`);
|
|
1198
|
+
return null;
|
|
1199
|
+
}
|
|
1200
|
+
const effective_extends_failures = resolved_layers.extends_failures.filter((failure) => declaration.state !== "declared" || !is_extends_failure_overridden(resolved_layers.layers, failure, declaration.config_path));
|
|
1201
|
+
if (effective_extends_failures.length > 0) {
|
|
1202
|
+
for (const failure of effective_extends_failures) {
|
|
1203
|
+
if (failure.diagnostics.length === 0) {
|
|
1204
|
+
logError$5("Unable to resolve tsconfig extends entry:", JSON.stringify(failure.extends_value), `in ${failure.config_path}`);
|
|
1205
|
+
continue;
|
|
1206
|
+
}
|
|
1207
|
+
for (const diagnostic of failure.diagnostics) logError$5("Unable to resolve tsconfig extends entry:", JSON.stringify(failure.extends_value), `in ${failure.config_path}`, typescript$5.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
|
|
1208
|
+
}
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
if (declaration.state === "declared") return resolve_declared_compiler(typescript$5, config_host, declaration.config_path, declaration.value);
|
|
1212
|
+
}
|
|
1213
|
+
/** Drop all filesystem-derived consumer compiler resolution state. */
|
|
1214
|
+
function reset_consumer_compiler_resolution_caches() {
|
|
1215
|
+
config_host_to_resolution_cache = /* @__PURE__ */ new WeakMap();
|
|
1216
|
+
declared_compiler_path_map.clear();
|
|
1217
|
+
}
|
|
1218
|
+
|
|
716
1219
|
//#endregion
|
|
717
1220
|
//#region ../typescript-plugin/src/language.js
|
|
718
1221
|
/** @import * as AST from 'estree'; */
|
|
@@ -725,9 +1228,9 @@ var require_language_core = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
725
1228
|
/** @typedef {import('@volar/language-core').VirtualCode} VirtualCode */
|
|
726
1229
|
/** @typedef {string | { fsPath: string }} ScriptId */
|
|
727
1230
|
/** @typedef {typeof import('@volar/typescript')} _VolarTypeScriptAugmentation */
|
|
1231
|
+
/** @typedef {import('./consumer-compiler.js').CompilerResolutionOptions} CompilerResolutionOptions */
|
|
728
1232
|
/** @typedef {import('@volar/language-core').LanguagePlugin<ScriptId, VirtualCode>} RippleLanguagePlugin */
|
|
729
1233
|
/** @typedef {InstanceType<typeof import('./language.js')["TSRXVirtualCode"]>} TSRXVirtualCodeInstance */
|
|
730
|
-
var import_language_core = require_language_core();
|
|
731
1234
|
const require$2 = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
732
1235
|
const root_dirname = path.default.dirname((0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
|
733
1236
|
const { log: log$9, logWarning, logError: logError$4 } = createLogging("[Ripple Language]");
|
|
@@ -812,10 +1315,18 @@ function is_ripple_file(file_name) {
|
|
|
812
1315
|
return RIPPLE_EXTENSIONS$1.some((extension) => file_name.endsWith(extension));
|
|
813
1316
|
}
|
|
814
1317
|
/**
|
|
1318
|
+
* @param {CompilerResolutionOptions} [options]
|
|
815
1319
|
* @returns {RippleLanguagePlugin}
|
|
816
1320
|
*/
|
|
817
|
-
function getRippleLanguagePlugin() {
|
|
1321
|
+
function getRippleLanguagePlugin(options = {}) {
|
|
818
1322
|
log$9("Creating Ripple language plugin...");
|
|
1323
|
+
const typescript$1 = options.ts ?? typescript.default;
|
|
1324
|
+
/** @type {CompilerResolutionOptions} */
|
|
1325
|
+
const compiler_resolution_options = {
|
|
1326
|
+
...options,
|
|
1327
|
+
ts: typescript$1,
|
|
1328
|
+
configHost: options.configHost ?? typescript$1.sys
|
|
1329
|
+
};
|
|
819
1330
|
return {
|
|
820
1331
|
getLanguageId(fileNameOrUri) {
|
|
821
1332
|
const file_name = typeof fileNameOrUri === "string" ? fileNameOrUri : fileNameOrUri.fsPath.replace(/\\/g, "/");
|
|
@@ -827,7 +1338,7 @@ function getRippleLanguagePlugin() {
|
|
|
827
1338
|
createVirtualCode(fileNameOrUri, languageId, snapshot) {
|
|
828
1339
|
if (languageId === "ripple") {
|
|
829
1340
|
const file_name = normalizeFileNameOrUri(fileNameOrUri);
|
|
830
|
-
const ripple = get_tsrx_compiler(file_name);
|
|
1341
|
+
const ripple = get_tsrx_compiler(file_name, compiler_resolution_options);
|
|
831
1342
|
if (!ripple) {
|
|
832
1343
|
logError$4(`Ripple compiler not found for file: ${file_name}`);
|
|
833
1344
|
return;
|
|
@@ -1370,9 +1881,9 @@ const resolveConfig = (config) => {
|
|
|
1370
1881
|
};
|
|
1371
1882
|
/** @type {Map<string, string | null>} */
|
|
1372
1883
|
const path2RipplePathMap = /* @__PURE__ */ new Map();
|
|
1373
|
-
/** @type {Map<string, string>} */
|
|
1884
|
+
/** @type {Map<string, { mtimeMs: number, size: number, content: string }>} */
|
|
1374
1885
|
const pathToTypesCache = /* @__PURE__ */ new Map();
|
|
1375
|
-
/** @type {Map<string, RegExpMatchArray>} */
|
|
1886
|
+
/** @type {Map<string, { text: string, matches: Map<string, RegExpMatchArray> }>} */
|
|
1376
1887
|
const typeNameMatchCache = /* @__PURE__ */ new Map();
|
|
1377
1888
|
/** @type {Map<string, { name: string | null, dependencies: Set<string> } | null>} */
|
|
1378
1889
|
const pathToPackageManifestCache = /* @__PURE__ */ new Map();
|
|
@@ -1440,18 +1951,24 @@ function package_manifest_matches_compiler(package_manifest, compiler_name, pack
|
|
|
1440
1951
|
}
|
|
1441
1952
|
/**
|
|
1442
1953
|
* @param {string} normalized_file_name
|
|
1954
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1443
1955
|
* @returns {TSRXCompilerModule | undefined}
|
|
1444
1956
|
*/
|
|
1445
|
-
function get_tsrx_compiler(normalized_file_name) {
|
|
1446
|
-
const compiler_path = get_compiler_entry_for_file(normalized_file_name);
|
|
1447
|
-
if (compiler_path)
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1957
|
+
function get_tsrx_compiler(normalized_file_name, options) {
|
|
1958
|
+
const compiler_path = get_compiler_entry_for_file(normalized_file_name, options);
|
|
1959
|
+
if (compiler_path) return normalize_tsrx_compiler_module(require$2(compiler_path));
|
|
1960
|
+
}
|
|
1961
|
+
/**
|
|
1962
|
+
* Normalize the compiler contract used by Octane and consumer-declared modules.
|
|
1963
|
+
* @param {TSRXCompilerModule & { compileToVolarMappings?: TSRXCompilerModule['compile_to_volar_mappings'] }} compiler_module
|
|
1964
|
+
* @returns {TSRXCompilerModule}
|
|
1965
|
+
*/
|
|
1966
|
+
function normalize_tsrx_compiler_module(compiler_module) {
|
|
1967
|
+
if (typeof compiler_module?.compile_to_volar_mappings !== "function" && typeof compiler_module?.compileToVolarMappings === "function") return {
|
|
1968
|
+
...compiler_module,
|
|
1969
|
+
compile_to_volar_mappings: compiler_module.compileToVolarMappings
|
|
1970
|
+
};
|
|
1971
|
+
return compiler_module;
|
|
1455
1972
|
}
|
|
1456
1973
|
/**
|
|
1457
1974
|
* @param {string} normalized_file_name
|
|
@@ -1495,10 +2012,13 @@ function find_workspace_compiler_entry_for_file(normalized_file_name, exists_syn
|
|
|
1495
2012
|
}
|
|
1496
2013
|
/**
|
|
1497
2014
|
* @param {string} normalized_file_name
|
|
2015
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1498
2016
|
* @returns {string | undefined}
|
|
1499
2017
|
*/
|
|
1500
|
-
function get_compiler_entry_for_file(normalized_file_name) {
|
|
2018
|
+
function get_compiler_entry_for_file(normalized_file_name, options) {
|
|
1501
2019
|
const ext = path.default.extname(normalized_file_name);
|
|
2020
|
+
const consumer_compiler_path = resolve_consumer_compiler_for_file(normalized_file_name, options);
|
|
2021
|
+
if (consumer_compiler_path !== void 0) return consumer_compiler_path ?? void 0;
|
|
1502
2022
|
const package_manifest = get_nearest_package_manifest(path.default.dirname(normalized_file_name));
|
|
1503
2023
|
const workspace_compiler_path = find_workspace_compiler_entry_for_file(normalized_file_name);
|
|
1504
2024
|
if (workspace_compiler_path) return workspace_compiler_path;
|
|
@@ -1529,16 +2049,18 @@ function get_compiler_entry_for_file(normalized_file_name) {
|
|
|
1529
2049
|
}
|
|
1530
2050
|
/**
|
|
1531
2051
|
* Resolve the tsrx compiler package that owns a `.tsrx` file (e.g. `'@tsrx/ripple'`,
|
|
1532
|
-
* `'@tsrx/react'`)
|
|
1533
|
-
* share the `.tsrx` extension, so this is how the editor layer tells them
|
|
1534
|
-
*
|
|
1535
|
-
* always agree on the platform. Returns `undefined` when no compiler resolves.
|
|
2052
|
+
* `'@tsrx/react'`) from the exact compiler entry selected for compilation. All
|
|
2053
|
+
* targets share the `.tsrx` extension, so this is how the editor layer tells them
|
|
2054
|
+
* apart. Returns `undefined` for an unresolved or unknown third-party compiler.
|
|
1536
2055
|
* @param {string} file_name
|
|
2056
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1537
2057
|
* @returns {string | undefined}
|
|
1538
2058
|
*/
|
|
1539
|
-
function get_tsrx_compiler_name_for_file(file_name) {
|
|
1540
|
-
const entry = get_compiler_entry_for_file(file_name.replace(/\\/g, "/"));
|
|
2059
|
+
function get_tsrx_compiler_name_for_file(file_name, options) {
|
|
2060
|
+
const entry = get_compiler_entry_for_file(file_name.replace(/\\/g, "/"), options);
|
|
1541
2061
|
if (!entry) return;
|
|
2062
|
+
const package_name = get_nearest_package_manifest(path.default.dirname(entry))?.name;
|
|
2063
|
+
if (COMPILER_CANDIDATES.some(([compiler_name]) => compiler_name === package_name)) return package_name ?? void 0;
|
|
1542
2064
|
const normalized_entry = entry.replace(/\\/g, "/");
|
|
1543
2065
|
for (const [compiler_name, compiler_dir_parts, , , entry_parts = DEFAULT_COMPILER_ENTRY_PARTS] of COMPILER_CANDIDATES) {
|
|
1544
2066
|
const suffix = "/" + [...compiler_dir_parts, ...entry_parts].join("/");
|
|
@@ -1549,53 +2071,116 @@ function get_tsrx_compiler_name_for_file(file_name) {
|
|
|
1549
2071
|
* Whether a `.tsrx` file is compiled by the Ripple target (as opposed to
|
|
1550
2072
|
* React/Solid/Preact/Vue). Used to gate Ripple-runtime-only editor suggestions.
|
|
1551
2073
|
* @param {string} file_name
|
|
2074
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1552
2075
|
* @returns {boolean}
|
|
1553
2076
|
*/
|
|
1554
|
-
function is_ripple_platform_file(file_name) {
|
|
1555
|
-
return get_tsrx_compiler_name_for_file(file_name) === "@tsrx/ripple";
|
|
2077
|
+
function is_ripple_platform_file(file_name, options) {
|
|
2078
|
+
return get_tsrx_compiler_name_for_file(file_name, options) === "@tsrx/ripple";
|
|
2079
|
+
}
|
|
2080
|
+
/**
|
|
2081
|
+
* Create a stable key for filesystem caches. Windows paths are case-insensitive
|
|
2082
|
+
* to TypeScript, while file URIs conventionally lowercase their drive letter.
|
|
2083
|
+
* @param {string} file_name
|
|
2084
|
+
*/
|
|
2085
|
+
function getPathCacheKey(file_name) {
|
|
2086
|
+
const is_windows_path = process.platform === "win32" || /^[a-z]:[\\/]/i.test(file_name) || file_name.startsWith("\\\\");
|
|
2087
|
+
const normalized = (is_windows_path ? path.default.win32 : path.default).normalize(file_name);
|
|
2088
|
+
return is_windows_path ? normalized.toLowerCase() : normalized;
|
|
1556
2089
|
}
|
|
1557
2090
|
/**
|
|
1558
2091
|
* @param {string} typesFilePath
|
|
1559
2092
|
* @returns {string | undefined}
|
|
1560
2093
|
*/
|
|
1561
2094
|
function getCachedTypeDefinitionFile(typesFilePath) {
|
|
1562
|
-
const
|
|
1563
|
-
|
|
1564
|
-
|
|
2095
|
+
const cache_key = getPathCacheKey(typesFilePath);
|
|
2096
|
+
let stat;
|
|
2097
|
+
try {
|
|
2098
|
+
stat = fs.default.statSync(typesFilePath);
|
|
2099
|
+
} catch {
|
|
1565
2100
|
logWarning(`Types file does not exist at path: ${typesFilePath}`);
|
|
1566
2101
|
return;
|
|
1567
2102
|
}
|
|
2103
|
+
const cached = pathToTypesCache.get(cache_key);
|
|
2104
|
+
if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) return cached.content;
|
|
1568
2105
|
log$9(`Found ripple types at: ${typesFilePath}`);
|
|
1569
2106
|
const fileContent = fs.default.readFileSync(typesFilePath, "utf8");
|
|
1570
2107
|
if (!fileContent) {
|
|
1571
2108
|
logWarning(`Failed to read content of types file at: ${typesFilePath}`);
|
|
1572
2109
|
return;
|
|
1573
2110
|
}
|
|
1574
|
-
pathToTypesCache.set(
|
|
2111
|
+
pathToTypesCache.set(cache_key, {
|
|
2112
|
+
mtimeMs: stat.mtimeMs,
|
|
2113
|
+
size: stat.size,
|
|
2114
|
+
content: fileContent
|
|
2115
|
+
});
|
|
1575
2116
|
return fileContent;
|
|
1576
2117
|
}
|
|
1577
2118
|
/**
|
|
1578
2119
|
* @param {string} typeName
|
|
1579
2120
|
* @param {string} text
|
|
2121
|
+
* @param {string} [sourceKey]
|
|
1580
2122
|
* @returns {RegExpMatchArray | undefined}
|
|
1581
2123
|
*/
|
|
1582
|
-
function getCachedTypeMatches(typeName, text) {
|
|
1583
|
-
const
|
|
2124
|
+
function getCachedTypeMatches(typeName, text, sourceKey = text) {
|
|
2125
|
+
const cache_key = sourceKey === text ? text : getPathCacheKey(sourceKey);
|
|
2126
|
+
let source_cache = typeNameMatchCache.get(cache_key);
|
|
2127
|
+
if (!source_cache || source_cache.text !== text) {
|
|
2128
|
+
source_cache = {
|
|
2129
|
+
text,
|
|
2130
|
+
matches: /* @__PURE__ */ new Map()
|
|
2131
|
+
};
|
|
2132
|
+
typeNameMatchCache.set(cache_key, source_cache);
|
|
2133
|
+
}
|
|
2134
|
+
const cached = source_cache.matches.get(typeName);
|
|
1584
2135
|
if (cached) return cached;
|
|
1585
2136
|
const searchPattern = new RegExp(`(?:export\\s+(?:declare\\s+)?|declare\\s+)(class|function)\\s+${typeName}`);
|
|
1586
2137
|
const match = text.match(searchPattern);
|
|
1587
2138
|
if (match && match.index !== void 0) {
|
|
1588
|
-
|
|
2139
|
+
source_cache.matches.set(typeName, match);
|
|
1589
2140
|
return match;
|
|
1590
2141
|
}
|
|
1591
2142
|
}
|
|
1592
2143
|
/**
|
|
1593
2144
|
* @param {string} normalized_file_name
|
|
2145
|
+
* @param {CompilerResolutionOptions} [options]
|
|
1594
2146
|
* @returns {string | undefined}
|
|
1595
2147
|
*/
|
|
1596
|
-
function get_compiler_dir_for_file(normalized_file_name) {
|
|
1597
|
-
const entry = get_compiler_entry_for_file(normalized_file_name);
|
|
1598
|
-
if (entry) return
|
|
2148
|
+
function get_compiler_dir_for_file(normalized_file_name, options) {
|
|
2149
|
+
const entry = get_compiler_entry_for_file(normalized_file_name, options);
|
|
2150
|
+
if (!entry) return;
|
|
2151
|
+
let current_dir = path.default.dirname(entry);
|
|
2152
|
+
while (current_dir) {
|
|
2153
|
+
if (fs.default.existsSync(path.default.join(current_dir, "package.json"))) return current_dir;
|
|
2154
|
+
if (path.default.basename(current_dir) === "node_modules") return;
|
|
2155
|
+
const parent_dir = path.default.dirname(current_dir);
|
|
2156
|
+
if (parent_dir === current_dir) return;
|
|
2157
|
+
current_dir = parent_dir;
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
/**
|
|
2161
|
+
* Drop compiler-selection state. Loaded ESM compiler graphs cannot be evicted
|
|
2162
|
+
* safely in-process; language-server package watchers restart the process.
|
|
2163
|
+
*/
|
|
2164
|
+
function invalidateCompilerResolutionCaches() {
|
|
2165
|
+
path2RipplePathMap.clear();
|
|
2166
|
+
pathToPackageManifestCache.clear();
|
|
2167
|
+
reset_consumer_compiler_resolution_caches();
|
|
2168
|
+
loggedCompilationFailures.clear();
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* Drop cached definition-file content and matches. A path invalidates only one
|
|
2172
|
+
* file; omitting it clears all definition state.
|
|
2173
|
+
* @param {string} [typesFilePath]
|
|
2174
|
+
*/
|
|
2175
|
+
function invalidateTypeDefinitionCaches(typesFilePath) {
|
|
2176
|
+
if (typesFilePath) {
|
|
2177
|
+
const cache_key = getPathCacheKey(typesFilePath);
|
|
2178
|
+
pathToTypesCache.delete(cache_key);
|
|
2179
|
+
typeNameMatchCache.delete(cache_key);
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
pathToTypesCache.clear();
|
|
2183
|
+
typeNameMatchCache.clear();
|
|
1599
2184
|
}
|
|
1600
2185
|
|
|
1601
2186
|
//#endregion
|
|
@@ -1715,15 +2300,30 @@ function is_ripple_document(document_uri) {
|
|
|
1715
2300
|
return RIPPLE_EXTENSIONS.some((extension) => document_uri.endsWith(extension));
|
|
1716
2301
|
}
|
|
1717
2302
|
/**
|
|
2303
|
+
* Reuse the TypeScript project selected by Volar when language-service plugins
|
|
2304
|
+
* perform compiler-dependent lookups outside virtual-code generation.
|
|
2305
|
+
* @param {LanguageServiceContext} context
|
|
2306
|
+
* @returns {import('@tsrx/typescript-plugin/src/consumer-compiler.js').CompilerResolutionOptions | undefined}
|
|
2307
|
+
*/
|
|
2308
|
+
function get_compiler_resolution_options(context) {
|
|
2309
|
+
const typescript_project = context.project.typescript;
|
|
2310
|
+
if (!typescript_project) return;
|
|
2311
|
+
return {
|
|
2312
|
+
configFileName: typescript_project.configFileName,
|
|
2313
|
+
configHost: typescript_project.sys
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
/**
|
|
1718
2317
|
* Whether a `.tsrx` document is compiled by the Ripple target (vs React/Solid/
|
|
1719
2318
|
* Preact/Vue). All targets share the `.tsrx` extension, so this resolves the
|
|
1720
|
-
* platform from the
|
|
2319
|
+
* platform from the active TypeScript project — used to gate Ripple-runtime-only
|
|
1721
2320
|
* editor suggestions.
|
|
1722
2321
|
* @param {string} document_uri
|
|
2322
|
+
* @param {import('@tsrx/typescript-plugin/src/consumer-compiler.js').CompilerResolutionOptions} [options]
|
|
1723
2323
|
* @returns {boolean}
|
|
1724
2324
|
*/
|
|
1725
|
-
function is_ripple_platform_document(document_uri) {
|
|
1726
|
-
return is_ripple_platform_file(vscode_uri.URI.parse(document_uri).fsPath);
|
|
2325
|
+
function is_ripple_platform_document(document_uri, options) {
|
|
2326
|
+
return is_ripple_platform_file(vscode_uri.URI.parse(document_uri).fsPath, options);
|
|
1727
2327
|
}
|
|
1728
2328
|
|
|
1729
2329
|
//#endregion
|
|
@@ -4639,7 +5239,7 @@ var require_main$4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4639
5239
|
exports.createMessageConnection = exports.createServerSocketTransport = exports.createClientSocketTransport = exports.createServerPipeTransport = exports.createClientPipeTransport = exports.generateRandomPipeName = exports.StreamMessageWriter = exports.StreamMessageReader = exports.SocketMessageWriter = exports.SocketMessageReader = exports.PortMessageWriter = exports.PortMessageReader = exports.IPCMessageWriter = exports.IPCMessageReader = void 0;
|
|
4640
5240
|
const ril_1 = require_ril();
|
|
4641
5241
|
ril_1.default.install();
|
|
4642
|
-
const path$
|
|
5242
|
+
const path$4 = require("path");
|
|
4643
5243
|
const os = require("os");
|
|
4644
5244
|
const crypto_1 = require("crypto");
|
|
4645
5245
|
const net_1 = require("net");
|
|
@@ -4763,8 +5363,8 @@ var require_main$4 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
4763
5363
|
const randomSuffix = (0, crypto_1.randomBytes)(21).toString("hex");
|
|
4764
5364
|
if (process.platform === "win32") return `\\\\.\\pipe\\vscode-jsonrpc-${randomSuffix}-sock`;
|
|
4765
5365
|
let result;
|
|
4766
|
-
if (XDG_RUNTIME_DIR) result = path$
|
|
4767
|
-
else result = path$
|
|
5366
|
+
if (XDG_RUNTIME_DIR) result = path$4.join(XDG_RUNTIME_DIR, `vscode-ipc-${randomSuffix}.sock`);
|
|
5367
|
+
else result = path$4.join(os.tmpdir(), `vscode-${randomSuffix}.sock`);
|
|
4768
5368
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
4769
5369
|
if (limit !== void 0 && result.length > limit) (0, ril_1.default)().console.warn(`WARNING: IPC handle "${result}" is longer than ${limit} characters.`);
|
|
4770
5370
|
return result;
|
|
@@ -11181,7 +11781,7 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11181
11781
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11182
11782
|
exports.resolveModulePath = exports.FileSystem = exports.resolveGlobalYarnPath = exports.resolveGlobalNodePath = exports.resolve = exports.uriToFilePath = void 0;
|
|
11183
11783
|
const url$1 = require("url");
|
|
11184
|
-
const path$
|
|
11784
|
+
const path$3 = require("path");
|
|
11185
11785
|
const fs$2 = require("fs");
|
|
11186
11786
|
const child_process_1 = require("child_process");
|
|
11187
11787
|
/**
|
|
@@ -11198,7 +11798,7 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11198
11798
|
let second = segments[1];
|
|
11199
11799
|
if (first.length === 0 && second.length > 1 && second[1] === ":") segments.shift();
|
|
11200
11800
|
}
|
|
11201
|
-
return path$
|
|
11801
|
+
return path$3.normalize(segments.join("/"));
|
|
11202
11802
|
}
|
|
11203
11803
|
exports.uriToFilePath = uriToFilePath;
|
|
11204
11804
|
function isWindows() {
|
|
@@ -11228,7 +11828,7 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11228
11828
|
let newEnv = Object.create(null);
|
|
11229
11829
|
Object.keys(env).forEach((key) => newEnv[key] = env[key]);
|
|
11230
11830
|
if (nodePath && fs$2.existsSync(nodePath)) {
|
|
11231
|
-
if (newEnv[nodePathKey]) newEnv[nodePathKey] = nodePath + path$
|
|
11831
|
+
if (newEnv[nodePathKey]) newEnv[nodePathKey] = nodePath + path$3.delimiter + newEnv[nodePathKey];
|
|
11232
11832
|
else newEnv[nodePathKey] = nodePath;
|
|
11233
11833
|
if (tracer) tracer(`NODE_PATH value is: ${newEnv[nodePathKey]}`);
|
|
11234
11834
|
}
|
|
@@ -11297,8 +11897,8 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11297
11897
|
}
|
|
11298
11898
|
let prefix = stdout.trim();
|
|
11299
11899
|
if (tracer) tracer(`'npm config get prefix' value is: ${prefix}`);
|
|
11300
|
-
if (prefix.length > 0) if (isWindows()) return path$
|
|
11301
|
-
else return path$
|
|
11900
|
+
if (prefix.length > 0) if (isWindows()) return path$3.join(prefix, "node_modules");
|
|
11901
|
+
else return path$3.join(prefix, "lib", "node_modules");
|
|
11302
11902
|
return;
|
|
11303
11903
|
} catch (err) {
|
|
11304
11904
|
return;
|
|
@@ -11333,7 +11933,7 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11333
11933
|
let lines = stdout.trim().split(/\r?\n/);
|
|
11334
11934
|
for (let line of lines) try {
|
|
11335
11935
|
let yarn = JSON.parse(line);
|
|
11336
|
-
if (yarn.type === "log") return path$
|
|
11936
|
+
if (yarn.type === "log") return path$3.join(yarn.data, "node_modules");
|
|
11337
11937
|
} catch (e) {}
|
|
11338
11938
|
return;
|
|
11339
11939
|
} catch (err) {
|
|
@@ -11354,14 +11954,14 @@ var require_files = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
11354
11954
|
}
|
|
11355
11955
|
FileSystem.isCaseSensitive = isCaseSensitive;
|
|
11356
11956
|
function isParent(parent, child) {
|
|
11357
|
-
if (isCaseSensitive()) return path$
|
|
11358
|
-
else return path$
|
|
11957
|
+
if (isCaseSensitive()) return path$3.normalize(child).indexOf(path$3.normalize(parent)) === 0;
|
|
11958
|
+
else return path$3.normalize(child).toLowerCase().indexOf(path$3.normalize(parent).toLowerCase()) === 0;
|
|
11359
11959
|
}
|
|
11360
11960
|
FileSystem.isParent = isParent;
|
|
11361
11961
|
})(FileSystem || (exports.FileSystem = FileSystem = {}));
|
|
11362
11962
|
function resolveModulePath(workspaceRoot, moduleName, nodePath, tracer) {
|
|
11363
11963
|
if (nodePath) {
|
|
11364
|
-
if (!path$
|
|
11964
|
+
if (!path$3.isAbsolute(nodePath)) nodePath = path$3.join(workspaceRoot, nodePath);
|
|
11365
11965
|
return resolve(moduleName, nodePath, nodePath, tracer).then((value) => {
|
|
11366
11966
|
if (FileSystem.isParent(nodePath, value)) return value;
|
|
11367
11967
|
else return Promise.reject(/* @__PURE__ */ new Error(`Failed to load ${moduleName} from node path location.`));
|
|
@@ -21019,8 +21619,6 @@ function get_start_offset_from_error(error) {
|
|
|
21019
21619
|
//#region src/definitionPlugin.js
|
|
21020
21620
|
init_main();
|
|
21021
21621
|
const { log: log$7 } = createLogging("[Ripple Definition Plugin]");
|
|
21022
|
-
/** @type {string | undefined} */
|
|
21023
|
-
let ripple_dir;
|
|
21024
21622
|
/**
|
|
21025
21623
|
* @returns {LanguageServicePlugin}
|
|
21026
21624
|
*/
|
|
@@ -21029,6 +21627,7 @@ function createDefinitionPlugin() {
|
|
|
21029
21627
|
name: "ripple-definition",
|
|
21030
21628
|
capabilities: { definitionProvider: true },
|
|
21031
21629
|
create(context) {
|
|
21630
|
+
const compiler_resolution_options = get_compiler_resolution_options(context);
|
|
21032
21631
|
return { async provideDefinition(document, position, token) {
|
|
21033
21632
|
/** @type {LocationLink[]} */
|
|
21034
21633
|
let tsDefinitions = [];
|
|
@@ -21051,7 +21650,7 @@ function createDefinitionPlugin() {
|
|
|
21051
21650
|
const { name: typeName, path: typePath } = customMapping.data.customData.definition.typeReplace;
|
|
21052
21651
|
log$7(`Found replace definition for ${typeName}`);
|
|
21053
21652
|
const filePath = sourceUri.fsPath || sourceUri.path;
|
|
21054
|
-
ripple_dir =
|
|
21653
|
+
const ripple_dir = get_compiler_dir_for_file(normalizeFileNameOrUri(filePath), compiler_resolution_options);
|
|
21055
21654
|
if (!ripple_dir) {
|
|
21056
21655
|
log$7(`Could not determine Ripple source directory for file: ${filePath}`);
|
|
21057
21656
|
return;
|
|
@@ -21059,7 +21658,7 @@ function createDefinitionPlugin() {
|
|
|
21059
21658
|
const typesFilePath = path.default.join(ripple_dir, ...typePath.split("/"));
|
|
21060
21659
|
const fileContent = getCachedTypeDefinitionFile(typesFilePath);
|
|
21061
21660
|
if (!fileContent) return;
|
|
21062
|
-
const match = getCachedTypeMatches(typeName, fileContent);
|
|
21661
|
+
const match = getCachedTypeMatches(typeName, fileContent, typesFilePath);
|
|
21063
21662
|
if (match && match.index !== void 0) {
|
|
21064
21663
|
const classStart = match.index + match[0].indexOf(typeName);
|
|
21065
21664
|
const classEnd = classStart + typeName.length;
|
|
@@ -21691,6 +22290,7 @@ function createCompletionPlugin() {
|
|
|
21691
22290
|
resolveProvider: false
|
|
21692
22291
|
} },
|
|
21693
22292
|
create(context) {
|
|
22293
|
+
const compiler_resolution_options = get_compiler_resolution_options(context);
|
|
21694
22294
|
return {
|
|
21695
22295
|
isAdditionalCompletion: true,
|
|
21696
22296
|
async provideCompletionItems(document, position, completionContext, _token) {
|
|
@@ -21724,7 +22324,7 @@ function createCompletionPlugin() {
|
|
|
21724
22324
|
});
|
|
21725
22325
|
const fullText = document.getText();
|
|
21726
22326
|
const cursorOffset = document.offsetAt(position);
|
|
21727
|
-
const is_ripple = is_ripple_platform_document(document.uri);
|
|
22327
|
+
const is_ripple = is_ripple_platform_document(document.uri, compiler_resolution_options);
|
|
21728
22328
|
if (isInsideImport(fullText, cursorOffset)) {
|
|
21729
22329
|
if (is_ripple) items.push(...RIPPLE_IMPORTS);
|
|
21730
22330
|
return {
|
|
@@ -22571,6 +23171,134 @@ function createTypeScriptServices(ts) {
|
|
|
22571
23171
|
return create(ts);
|
|
22572
23172
|
}
|
|
22573
23173
|
|
|
23174
|
+
//#endregion
|
|
23175
|
+
//#region src/workspaceState.js
|
|
23176
|
+
const WORKSPACE_FILE_PATTERNS = [
|
|
23177
|
+
"**/*.tsrx",
|
|
23178
|
+
"**/*.ts",
|
|
23179
|
+
"**/*.tsx",
|
|
23180
|
+
"**/*.cts",
|
|
23181
|
+
"**/*.mts",
|
|
23182
|
+
"**/*.js",
|
|
23183
|
+
"**/*.jsx",
|
|
23184
|
+
"**/*.cjs",
|
|
23185
|
+
"**/*.mjs",
|
|
23186
|
+
"**/*.json",
|
|
23187
|
+
"**/pnpm-lock.yaml",
|
|
23188
|
+
"**/pnpm-workspace.yaml",
|
|
23189
|
+
"**/yarn.lock",
|
|
23190
|
+
"**/bun.lock",
|
|
23191
|
+
"**/bun.lockb"
|
|
23192
|
+
];
|
|
23193
|
+
const PACKAGE_STATE_FILE_NAMES = new Set([
|
|
23194
|
+
"package.json",
|
|
23195
|
+
"package-lock.json",
|
|
23196
|
+
"pnpm-lock.yaml",
|
|
23197
|
+
"pnpm-workspace.yaml",
|
|
23198
|
+
"yarn.lock",
|
|
23199
|
+
"bun.lock",
|
|
23200
|
+
"bun.lockb"
|
|
23201
|
+
]);
|
|
23202
|
+
/**
|
|
23203
|
+
* @param {string} file_name
|
|
23204
|
+
*/
|
|
23205
|
+
function isTypeScriptConfigFile(file_name) {
|
|
23206
|
+
const base_name = node_path.default.basename(file_name).toLowerCase();
|
|
23207
|
+
return base_name.endsWith(".json") && (base_name.includes("tsconfig") || base_name.includes("jsconfig"));
|
|
23208
|
+
}
|
|
23209
|
+
/**
|
|
23210
|
+
* @param {string} file_name
|
|
23211
|
+
*/
|
|
23212
|
+
function isTypeDefinitionFile(file_name) {
|
|
23213
|
+
return /\.d\.[cm]?ts$/i.test(file_name);
|
|
23214
|
+
}
|
|
23215
|
+
/**
|
|
23216
|
+
* @param {string} file_name
|
|
23217
|
+
*/
|
|
23218
|
+
function isPackageStateFile(file_name) {
|
|
23219
|
+
return PACKAGE_STATE_FILE_NAMES.has(node_path.default.basename(file_name).toLowerCase());
|
|
23220
|
+
}
|
|
23221
|
+
/**
|
|
23222
|
+
* @param {string} file_name
|
|
23223
|
+
*/
|
|
23224
|
+
function normalizeFileName(file_name) {
|
|
23225
|
+
const is_windows_path = process.platform === "win32" || /^[a-z]:[\\/]/i.test(file_name) || file_name.startsWith("\\\\");
|
|
23226
|
+
const path_api = is_windows_path ? node_path.default.win32 : node_path.default;
|
|
23227
|
+
const normalized = path_api.normalize(path_api.resolve(file_name));
|
|
23228
|
+
return is_windows_path ? normalized.toLowerCase() : normalized;
|
|
23229
|
+
}
|
|
23230
|
+
/**
|
|
23231
|
+
* Record every config file that contributed to a parsed TypeScript project.
|
|
23232
|
+
* This set is intentionally additive across project reloads because Volar
|
|
23233
|
+
* recreates projects lazily. TypeScript allows both `extends` and
|
|
23234
|
+
* project-reference configs to use names other than tsconfig.json, so filename
|
|
23235
|
+
* matching alone is not sufficient.
|
|
23236
|
+
* @param {Set<string>} config_files
|
|
23237
|
+
* @param {{
|
|
23238
|
+
* configFileName?: string,
|
|
23239
|
+
* compilerOptions?: import('typescript').CompilerOptions,
|
|
23240
|
+
* projectReferences?: readonly import('typescript').ProjectReference[],
|
|
23241
|
+
* configDependencies?: Iterable<string>,
|
|
23242
|
+
* }} project
|
|
23243
|
+
*/
|
|
23244
|
+
function trackTypeScriptConfigDependencies(config_files, project) {
|
|
23245
|
+
if (project.configFileName) config_files.add(normalizeFileName(project.configFileName));
|
|
23246
|
+
const config_file = project.compilerOptions?.configFile;
|
|
23247
|
+
for (const extended_file of config_file?.extendedSourceFiles ?? []) config_files.add(normalizeFileName(extended_file));
|
|
23248
|
+
for (const reference of project.projectReferences ?? []) config_files.add(normalizeFileName(reference.path));
|
|
23249
|
+
for (const dependency of project.configDependencies ?? []) config_files.add(normalizeFileName(dependency));
|
|
23250
|
+
}
|
|
23251
|
+
/**
|
|
23252
|
+
* Classify watched changes before mutating project state. Package changes need
|
|
23253
|
+
* a process restart because Node does not expose a supported way to evict a
|
|
23254
|
+
* loaded ESM compiler and its transitive module graph.
|
|
23255
|
+
* @param {import('@volar/language-server').FileEvent[]} changes
|
|
23256
|
+
* @param {ReadonlySet<string>} [tracked_config_files]
|
|
23257
|
+
*/
|
|
23258
|
+
function classifyWorkspaceChanges(changes, tracked_config_files = /* @__PURE__ */ new Set()) {
|
|
23259
|
+
let reloadProjects = false;
|
|
23260
|
+
let restartLanguageServer = false;
|
|
23261
|
+
/** @type {Set<string>} */
|
|
23262
|
+
const changedTypeDefinitions = /* @__PURE__ */ new Set();
|
|
23263
|
+
for (const change of changes) {
|
|
23264
|
+
const uri = vscode_uri.URI.parse(change.uri);
|
|
23265
|
+
const file_name = uri.scheme === "file" ? uri.fsPath : uri.path;
|
|
23266
|
+
if (isTypeScriptConfigFile(file_name) || tracked_config_files.has(normalizeFileName(file_name))) reloadProjects = true;
|
|
23267
|
+
if (isPackageStateFile(file_name)) restartLanguageServer = true;
|
|
23268
|
+
else if (isTypeDefinitionFile(file_name)) changedTypeDefinitions.add(file_name);
|
|
23269
|
+
}
|
|
23270
|
+
return {
|
|
23271
|
+
restartLanguageServer,
|
|
23272
|
+
reloadProjects: reloadProjects && !restartLanguageServer,
|
|
23273
|
+
changedTypeDefinitions: restartLanguageServer ? [] : [...changedTypeDefinitions]
|
|
23274
|
+
};
|
|
23275
|
+
}
|
|
23276
|
+
/**
|
|
23277
|
+
* @param {import('@volar/language-server').FileEvent[]} changes
|
|
23278
|
+
* @param {{
|
|
23279
|
+
* restartLanguageServer: () => void,
|
|
23280
|
+
* invalidateCompilerResolutionCaches?: () => void,
|
|
23281
|
+
* reloadProjects: () => void,
|
|
23282
|
+
* requestRefresh: (clearDiagnostics: boolean) => unknown,
|
|
23283
|
+
* invalidateTypeDefinitions: (file_name?: string) => void,
|
|
23284
|
+
* }} hooks
|
|
23285
|
+
* @param {ReadonlySet<string>} [tracked_config_files]
|
|
23286
|
+
*/
|
|
23287
|
+
function handleWorkspaceChanges(changes, hooks, tracked_config_files) {
|
|
23288
|
+
const effects = classifyWorkspaceChanges(changes, tracked_config_files);
|
|
23289
|
+
if (effects.restartLanguageServer) {
|
|
23290
|
+
hooks.restartLanguageServer();
|
|
23291
|
+
return effects;
|
|
23292
|
+
}
|
|
23293
|
+
for (const file_name of effects.changedTypeDefinitions) hooks.invalidateTypeDefinitions(file_name);
|
|
23294
|
+
if (effects.reloadProjects) {
|
|
23295
|
+
hooks.invalidateCompilerResolutionCaches?.();
|
|
23296
|
+
hooks.reloadProjects();
|
|
23297
|
+
hooks.requestRefresh(true);
|
|
23298
|
+
}
|
|
23299
|
+
return effects;
|
|
23300
|
+
}
|
|
23301
|
+
|
|
22574
23302
|
//#endregion
|
|
22575
23303
|
//#region src/server.js
|
|
22576
23304
|
/** @import {CompilerOptions} from 'typescript' */
|
|
@@ -22603,10 +23331,20 @@ function createRippleLanguageServer() {
|
|
|
22603
23331
|
const connection = (0, import_node.createConnection)();
|
|
22604
23332
|
const server = (0, import_node.createServer)(connection);
|
|
22605
23333
|
connection.listen();
|
|
22606
|
-
const rippleLanguagePlugin = getRippleLanguagePlugin();
|
|
22607
|
-
log("Language plugin instance created");
|
|
22608
23334
|
/** @type {WeakSet<Function>} */
|
|
22609
23335
|
const wrappedFunctions = /* @__PURE__ */ new WeakSet();
|
|
23336
|
+
/** @type {Set<string>} */
|
|
23337
|
+
const trackedTypeScriptConfigFiles = /* @__PURE__ */ new Set();
|
|
23338
|
+
/** @type {Set<Set<string>>} */
|
|
23339
|
+
const compilerResolutionDependencySets = /* @__PURE__ */ new Set();
|
|
23340
|
+
let restartScheduled = false;
|
|
23341
|
+
/** Restart the process so Node drops the complete ESM compiler graph. */
|
|
23342
|
+
function restartLanguageServer() {
|
|
23343
|
+
if (restartScheduled) return;
|
|
23344
|
+
restartScheduled = true;
|
|
23345
|
+
log("Restarting after package state changed.");
|
|
23346
|
+
setTimeout(() => process.exit(0), 50);
|
|
23347
|
+
}
|
|
22610
23348
|
/**
|
|
22611
23349
|
* Ensure TypeScript hosts always see compiler options with Ripple defaults.
|
|
22612
23350
|
* @param {unknown} target
|
|
@@ -22639,12 +23377,25 @@ function createRippleLanguageServer() {
|
|
|
22639
23377
|
log("Initializing Ripple language server...");
|
|
22640
23378
|
log("Initialization options:", JSON.stringify(params.initializationOptions, null, 2));
|
|
22641
23379
|
const ts = require("typescript");
|
|
22642
|
-
const initResult = server.initialize(params, (0, import_node.createTypeScriptProject)(ts, void 0, ({ projectHost }) => {
|
|
23380
|
+
const initResult = server.initialize(params, (0, import_node.createTypeScriptProject)(ts, void 0, ({ configFileName, projectHost, sys }) => {
|
|
22643
23381
|
wrapCompilerOptionsProvider(projectHost, "getCompilationSettings");
|
|
23382
|
+
const compilerResolutionDependencies = /* @__PURE__ */ new Set();
|
|
23383
|
+
const languagePlugin = getRippleLanguagePlugin({
|
|
23384
|
+
ts,
|
|
23385
|
+
configFileName,
|
|
23386
|
+
configHost: sys,
|
|
23387
|
+
dependencies: compilerResolutionDependencies
|
|
23388
|
+
});
|
|
23389
|
+
compilerResolutionDependencySets.add(compilerResolutionDependencies);
|
|
22644
23390
|
return {
|
|
22645
|
-
languagePlugins: [
|
|
23391
|
+
languagePlugins: [languagePlugin],
|
|
22646
23392
|
setup({ project }) {
|
|
22647
23393
|
wrapCompilerOptionsProvider(project?.typescript?.languageServiceHost, "getCompilationSettings");
|
|
23394
|
+
trackTypeScriptConfigDependencies(trackedTypeScriptConfigFiles, {
|
|
23395
|
+
configFileName,
|
|
23396
|
+
compilerOptions: projectHost.getCompilationSettings(),
|
|
23397
|
+
projectReferences: projectHost.getProjectReferences?.()
|
|
23398
|
+
});
|
|
22648
23399
|
}
|
|
22649
23400
|
};
|
|
22650
23401
|
}), [
|
|
@@ -22669,21 +23420,21 @@ function createRippleLanguageServer() {
|
|
|
22669
23420
|
connection.onInitialized(async () => {
|
|
22670
23421
|
log("Server initialized.");
|
|
22671
23422
|
server.initialized();
|
|
23423
|
+
server.fileWatcher.onDidChangeWatchedFiles(({ changes }) => {
|
|
23424
|
+
for (const configDependencies of compilerResolutionDependencySets) trackTypeScriptConfigDependencies(trackedTypeScriptConfigFiles, { configDependencies });
|
|
23425
|
+
if (handleWorkspaceChanges(changes, {
|
|
23426
|
+
restartLanguageServer,
|
|
23427
|
+
invalidateCompilerResolutionCaches,
|
|
23428
|
+
invalidateTypeDefinitions: invalidateTypeDefinitionCaches,
|
|
23429
|
+
reloadProjects: () => {
|
|
23430
|
+
server.project.reload();
|
|
23431
|
+
},
|
|
23432
|
+
requestRefresh: (clearDiagnostics) => server.languageFeatures.requestRefresh(clearDiagnostics)
|
|
23433
|
+
}, trackedTypeScriptConfigFiles).reloadProjects) log("Reloaded TypeScript projects after workspace configuration changed.");
|
|
23434
|
+
});
|
|
22672
23435
|
try {
|
|
22673
|
-
await server.fileWatcher.watchFiles(
|
|
22674
|
-
|
|
22675
|
-
"**/*.tsx",
|
|
22676
|
-
"**/*.cts",
|
|
22677
|
-
"**/*.mts",
|
|
22678
|
-
"**/*.js",
|
|
22679
|
-
"**/*.jsx",
|
|
22680
|
-
"**/*.cjs",
|
|
22681
|
-
"**/*.mjs",
|
|
22682
|
-
"**/*.d.ts",
|
|
22683
|
-
"**/tsconfig.json",
|
|
22684
|
-
"**/jsconfig.json"
|
|
22685
|
-
]);
|
|
22686
|
-
log("File watchers registered for TypeScript/JavaScript files.");
|
|
23436
|
+
await server.fileWatcher.watchFiles(WORKSPACE_FILE_PATTERNS);
|
|
23437
|
+
log("Workspace file watchers registered.");
|
|
22687
23438
|
} catch (err) {
|
|
22688
23439
|
logError("Failed to register file watchers:", err);
|
|
22689
23440
|
}
|
|
@@ -22713,4 +23464,4 @@ Object.defineProperty(exports, 'createRippleLanguageServer', {
|
|
|
22713
23464
|
return createRippleLanguageServer;
|
|
22714
23465
|
}
|
|
22715
23466
|
});
|
|
22716
|
-
//# sourceMappingURL=server-
|
|
23467
|
+
//# sourceMappingURL=server-B91H_hpq.js.map
|