dsh-vscode-mode 0.1.49 → 0.1.51

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/lib/index.js CHANGED
@@ -7537,7 +7537,13 @@ function candidateEmmyLua(home = dshHome()) {
7537
7537
  candidates.sort((a, b) => (b.version ?? "").localeCompare(a.version ?? "", void 0, { numeric: true }) || a.path.localeCompare(b.path));
7538
7538
  return candidates[0] ?? null;
7539
7539
  }
7540
- /** LuaLS 自动发现候选(VSCode 扩展目录 + extmgr 目录下 sumneko.lua-* 的 server/bin 可执行)。 */
7540
+ /**
7541
+ * LuaLS 自动发现候选(VSCode 扩展目录 + extmgr 目录下 sumneko.lua-* 的 server/bin 可执行)。
7542
+ * 多版本并存时按清单版本降序、路径升序排序(与 EmmyLua/DotRush 发现的排序策略一致)。
7543
+ * @author ddj 2026年09月03号
7544
+ * @param home DSH home(缺省真实;测试可注入临时目录)
7545
+ * @returns 排序后的候选列表(首个为建议选用者)
7546
+ */
7541
7547
  function candidateLuaServers(home = dshHome()) {
7542
7548
  const plat = platformServerDir();
7543
7549
  const suffix = exeSuffix();
@@ -7546,40 +7552,62 @@ function candidateLuaServers(home = dshHome()) {
7546
7552
  const binDir = join(extDir, "server", "bin");
7547
7553
  const binName = "lua-language-server" + suffix;
7548
7554
  const bin = existsSync(join(binDir, binName)) ? join(binDir, binName) : join(binDir, plat, binName);
7549
- if (existsSync(bin) && !out.includes(bin)) out.push(bin);
7555
+ if (existsSync(bin) && !out.some((c) => c.path === bin)) out.push({
7556
+ path: bin,
7557
+ version: manifestVersionOf(extDir)
7558
+ });
7550
7559
  }
7551
- return out;
7560
+ return out.sort((a, b) => (b.version ?? "").localeCompare(a.version ?? "", void 0, { numeric: true }) || a.path.localeCompare(b.path));
7552
7561
  }
7553
7562
  /**
7554
7563
  * C# 自动发现候选:ms-dotnettools.csharp 的 Roslyn dll(需 dotnet)/ OmniSharp 可执行,
7555
7564
  * 以及 DotRush 扩展自带服务器(extension/bin/LanguageServer/DotRush.dll,需对应 .NET 运行时)。
7565
+ * 同类多版本并存时取清单版本最高者(与 EmmyLua/DotRush 发现的排序策略一致)。
7556
7566
  * @author ddj 2026年09月03号
7557
7567
  * @param home DSH home(缺省真实;测试可注入临时目录)
7558
7568
  * @returns 发现结果
7559
7569
  */
7560
7570
  function candidateCSharpServers(home = dshHome()) {
7561
7571
  const out = {};
7572
+ /** 命中收集 → 清单版本降序取最高(平级按路径稳定排序)。 */
7573
+ const bestOf = (hits) => hits.sort((a, b) => (b.version ?? "").localeCompare(a.version ?? "", void 0, { numeric: true }) || a.entry.localeCompare(b.entry))[0] ?? null;
7574
+ const roslynHits = [];
7575
+ const omniHits = [];
7562
7576
  const dotrushHits = [];
7563
7577
  for (const dir of vscodeExtensionsDirs(home)) {
7564
7578
  for (const extDir of listMatchingDirs(dir, "ms-dotnettools.csharp-")) {
7579
+ const version = manifestVersionOf(extDir);
7565
7580
  const roslyn = join(extDir, ".roslyn", "Microsoft.CodeAnalysis.LanguageServer.dll");
7566
- if (!out.roslynDll && existsSync(roslyn)) out.roslynDll = roslyn;
7581
+ if (existsSync(roslyn)) roslynHits.push({
7582
+ entry: roslyn,
7583
+ version
7584
+ });
7567
7585
  const omni = join(extDir, ".omnisharp", "OmniSharp" + exeSuffix());
7568
- if (!out.omnisharpExe && existsSync(omni)) out.omnisharpExe = omni;
7586
+ if (existsSync(omni)) omniHits.push({
7587
+ entry: omni,
7588
+ version
7589
+ });
7569
7590
  }
7570
7591
  for (const extDir of listMatchingDirs(dir, "nromanov.dotrush-")) {
7571
7592
  const dll = join(extDir, "extension", "bin", "LanguageServer", "DotRush.dll");
7572
7593
  if (!existsSync(dll)) continue;
7573
7594
  dotrushHits.push({
7574
- dll,
7595
+ entry: dll,
7575
7596
  version: manifestVersionOf(extDir)
7576
7597
  });
7577
7598
  }
7578
7599
  }
7579
- const best = dotrushHits.sort((a, b) => (b.version ?? "").localeCompare(a.version ?? "", void 0, { numeric: true }) || a.dll.localeCompare(b.dll))[0];
7580
- if (best) {
7581
- out.dotrushDll = best.dll;
7582
- out.dotrushVersion = best.version;
7600
+ const roslynBest = bestOf(roslynHits);
7601
+ if (roslynBest) {
7602
+ out.roslynDll = roslynBest.entry;
7603
+ out.roslynVersion = roslynBest.version;
7604
+ }
7605
+ const omniBest = bestOf(omniHits);
7606
+ if (omniBest) out.omnisharpExe = omniBest.entry;
7607
+ const dotrushBest = bestOf(dotrushHits);
7608
+ if (dotrushBest) {
7609
+ out.dotrushDll = dotrushBest.entry;
7610
+ out.dotrushVersion = dotrushBest.version;
7583
7611
  }
7584
7612
  const dotnet = findDotnet();
7585
7613
  if (dotnet) out.dotnet = dotnet;
@@ -7683,13 +7711,15 @@ function resolveLuaProvider(manual, home = dshHome()) {
7683
7711
  version: emmy.version,
7684
7712
  providerName: "EmmyLua"
7685
7713
  };
7686
- const candidates = candidateLuaServers(h);
7687
- if (candidates.length) return {
7714
+ const best = candidateLuaServers(h)[0];
7715
+ if (best) return {
7688
7716
  ...base,
7689
7717
  kind: "discover",
7690
- argv: [candidates[0]],
7718
+ argv: [best.path],
7691
7719
  cwd: void 0,
7692
- ready: true
7720
+ ready: true,
7721
+ version: best.version,
7722
+ providerName: "LuaLS"
7693
7723
  };
7694
7724
  const inPath = findInPath("lua-language-server" + exeSuffix());
7695
7725
  if (inPath) return {
@@ -7785,6 +7815,67 @@ const PROVIDER_RESOLVERS = {
7785
7815
  lua: resolveLuaProvider,
7786
7816
  csharp: resolveCSharpProvider
7787
7817
  };
7818
+ /**
7819
+ * 汇总某语言当前检测到的候选服务器(每类服务器一条、取该类最高版本;设置页展示用)。
7820
+ * chosen 以候选路径命中 spec.argv 判定;未选用(kind=none/manual 不匹配)时不标记。
7821
+ * @author ddj 2026年09月03号
7822
+ * @param languageId 语言 id
7823
+ * @param spec 已解析的 provider 规格
7824
+ * @param home DSH home(缺省真实;测试可注入临时目录)
7825
+ * @returns 候选列表(不支持的语言/检测异常返回空)
7826
+ */
7827
+ function candidatesFor(languageId, spec, home = dshHome()) {
7828
+ /** 候选路径命中 spec.argv 时补 chosen 标记。 */
7829
+ const markChosen = (candidate) => spec.ready && candidate.path && spec.argv.includes(candidate.path) ? {
7830
+ ...candidate,
7831
+ chosen: true
7832
+ } : candidate;
7833
+ try {
7834
+ if (languageId === "lua") {
7835
+ const out = [];
7836
+ const emmy = candidateEmmyLua(home);
7837
+ if (emmy) out.push(markChosen({
7838
+ name: "EmmyLua",
7839
+ version: emmy.version,
7840
+ path: emmy.path
7841
+ }));
7842
+ const lua = candidateLuaServers(home)[0];
7843
+ if (lua) out.push(markChosen({
7844
+ name: "LuaLS(sumneko.lua)",
7845
+ version: lua.version,
7846
+ path: lua.path
7847
+ }));
7848
+ const inPath = findInPath("lua-language-server" + exeSuffix());
7849
+ if (inPath) out.push(markChosen({
7850
+ name: "lua-language-server(PATH)",
7851
+ path: inPath
7852
+ }));
7853
+ return out;
7854
+ }
7855
+ if (languageId === "csharp") {
7856
+ const out = [];
7857
+ const found = candidateCSharpServers(home);
7858
+ if (found.roslynDll) out.push(markChosen({
7859
+ name: "Roslyn(ms-dotnettools.csharp)",
7860
+ version: found.roslynVersion,
7861
+ path: found.roslynDll
7862
+ }));
7863
+ if (found.dotrushDll) out.push(markChosen({
7864
+ name: "DotRush",
7865
+ version: found.dotrushVersion,
7866
+ path: found.dotrushDll
7867
+ }));
7868
+ if (found.omnisharpExe) out.push(markChosen({
7869
+ name: "OmniSharp",
7870
+ path: found.omnisharpExe
7871
+ }));
7872
+ return out;
7873
+ }
7874
+ return [];
7875
+ } catch (error) {
7876
+ return [];
7877
+ }
7878
+ }
7788
7879
  /** 进程级缓存(home|languageId → 条目),同一 DSH home 的不同会话共享。 */
7789
7880
  const specCache = /* @__PURE__ */ new Map();
7790
7881
  /** 磁盘缓存是否已载入本进程(home → loaded),不同 profile 不串缓存。 */
@@ -8388,10 +8479,11 @@ function createLspRpc(deps) {
8388
8479
  ...location,
8389
8480
  root
8390
8481
  }));
8391
- /** 当前 provider 检测结论 → 设置页 idle 状态(不启动 server);附带未满足的环境需求。 */
8482
+ /** 当前 provider 检测结论 → 设置页 idle 状态(不启动 server);附带未满足的环境需求与候选服务器。 */
8392
8483
  const detectedStatus = (languageId, root) => {
8393
8484
  const spec = resolveProviderSpec(ctx, pluginConfig, languageId);
8394
8485
  const missingEnv = envRequirementsFor(languageId, dshHome());
8486
+ const candidates = candidatesFor(languageId, spec);
8395
8487
  return {
8396
8488
  languageId,
8397
8489
  source: spec.kind,
@@ -8400,7 +8492,8 @@ function createLspRpc(deps) {
8400
8492
  version: spec.version,
8401
8493
  providerName: spec.providerName,
8402
8494
  root,
8403
- missingEnv: missingEnv.length ? missingEnv : void 0
8495
+ missingEnv: missingEnv.length ? missingEnv : void 0,
8496
+ candidates: candidates.length ? candidates : void 0
8404
8497
  };
8405
8498
  };
8406
8499
  /**
@@ -8446,6 +8539,12 @@ function createLspRpc(deps) {
8446
8539
  servers: manager.statusAll().filter((status) => status.root === sc.root)
8447
8540
  };
8448
8541
  },
8542
+ "edrv.lsp.detect": async () => {
8543
+ return {
8544
+ ok: true,
8545
+ servers: LSP_LANGUAGES.map((lang) => detectedStatus(lang))
8546
+ };
8547
+ },
8449
8548
  "edrv.lsp.configGet": async () => {
8450
8549
  const settings = configFromSettings(ctx);
8451
8550
  const plugin = configFromPlugin(pluginConfig);
@@ -8461,7 +8560,7 @@ function createLspRpc(deps) {
8461
8560
  },
8462
8561
  "edrv.lsp.configUpdate": async (args) => {
8463
8562
  const lang = args.languageId;
8464
- if (!lang || !resolveProviderSpec(ctx, pluginConfig, lang).languageId) return {
8563
+ if (!lang || !LSP_LANGUAGES.includes(lang)) return {
8465
8564
  ok: false,
8466
8565
  error: "不支持的语言:" + lang
8467
8566
  };