Skip to content

Commit 0f35e84

Browse files
authored
Merge branch 'Acode-Foundation:main' into main
2 parents f154a2c + e04f4d2 commit 0f35e84

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1257
-683
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cm/lsp/clientManager.ts

Lines changed: 92 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import lspStatusBar from "components/lspStatusBar";
1515
import NotificationManager from "lib/notificationManager";
1616
import Uri from "utils/Uri";
1717
import { clearDiagnosticsEffect } from "./diagnostics";
18-
import { documentHighlightsExtension } from "./documentHighlights";
1918
import { supportsBuiltinFormatting } from "./formattingSupport";
2019
import { inlayHintsExtension } from "./inlayHints";
2120
import { acodeRenameKeymap } from "./rename";
@@ -27,7 +26,7 @@ import type {
2726
BuiltinExtensionsConfig,
2827
ClientManagerOptions,
2928
ClientState,
30-
EnsureServerResult,
29+
DocumentUriContext,
3130
FileMetadata,
3231
FormattingOptions,
3332
LspServerDefinition,
@@ -160,7 +159,6 @@ function buildBuiltinExtensions(
160159
keymaps: includeKeymaps = true,
161160
diagnostics: includeDiagnostics = true,
162161
inlayHints: includeInlayHints = false,
163-
documentHighlights: includeDocumentHighlights = true,
164162
formatting: includeFormatting = true,
165163
} = config;
166164

@@ -190,10 +188,6 @@ function buildBuiltinExtensions(
190188
const hintsExt = inlayHintsExtension();
191189
extensions.push(hintsExt as LSPClientExtension as Extension);
192190
}
193-
if (includeDocumentHighlights) {
194-
const highlightsExt = documentHighlightsExtension();
195-
extensions.push(highlightsExt as LSPClientExtension as Extension);
196-
}
197191

198192
return { extensions, diagnosticsExtension };
199193
}
@@ -248,30 +242,23 @@ export class LspClientManager {
248242
const servers = serverRegistry.getServersForLanguage(effectiveLang);
249243
if (!servers.length) return [];
250244

251-
// Normalize the document URI for LSP (convert content:// to file://)
252-
let normalizedUri = normalizeDocumentUri(originalUri);
253-
if (!normalizedUri) {
254-
// Fall back to cache file path for unrecognized URIs
255-
// This allows LSP to work with any file system provider using the local cache
256-
const cacheFile = file?.cacheFile;
257-
if (cacheFile && typeof cacheFile === "string") {
258-
normalizedUri = buildFileUri(cacheFile.replace(/^file:\/\//, ""));
259-
if (normalizedUri) {
260-
console.info(
261-
`LSP using cache path for unrecognized URI: ${originalUri} -> ${normalizedUri}`,
262-
);
263-
}
264-
}
265-
if (!normalizedUri) {
266-
console.warn(`Cannot normalize document URI for LSP: ${originalUri}`);
267-
return [];
268-
}
269-
}
270-
271245
const lspExtensions: Extension[] = [];
272246
const diagnosticsUiExtension = this.options.diagnosticsUiExtension;
273247

274248
for (const server of servers) {
249+
const normalizedUri = await this.#resolveDocumentUri(server, {
250+
uri: originalUri,
251+
file,
252+
view,
253+
languageId: effectiveLang,
254+
rootUri,
255+
});
256+
if (!normalizedUri) {
257+
console.warn(
258+
`Cannot resolve document URI for LSP server ${server.id}: ${originalUri}`,
259+
);
260+
continue;
261+
}
275262
let targetLanguageId = effectiveLang;
276263
if (server.resolveLanguageId) {
277264
try {
@@ -302,7 +289,9 @@ export class LspClientManager {
302289
normalizedUri,
303290
targetLanguageId,
304291
);
305-
clientState.attach(normalizedUri, view as EditorView);
292+
const aliases =
293+
originalUri && originalUri !== normalizedUri ? [originalUri] : [];
294+
clientState.attach(normalizedUri, view as EditorView, aliases);
306295
lspExtensions.push(plugin);
307296
} catch (error) {
308297
const lspError = error as LSPError;
@@ -334,26 +323,25 @@ export class LspClientManager {
334323
const effectiveLang = safeString(languageId ?? languageName).toLowerCase();
335324
if (!effectiveLang || !view) return false;
336325

337-
let normalizedUri = normalizeDocumentUri(originalUri);
338-
if (!normalizedUri) {
339-
const cacheFile = file?.cacheFile;
340-
if (cacheFile && typeof cacheFile === "string") {
341-
normalizedUri = buildFileUri(cacheFile.replace(/^file:\/\//, ""));
342-
}
343-
if (!normalizedUri) {
344-
console.warn(
345-
`Cannot normalize document URI for formatting: ${originalUri}`,
346-
);
347-
return false;
348-
}
349-
}
350-
351326
const servers = serverRegistry.getServersForLanguage(effectiveLang);
352327
if (!servers.length) return false;
353328

354329
for (const server of servers) {
355330
if (!supportsBuiltinFormatting(server)) continue;
356331
try {
332+
const normalizedUri = await this.#resolveDocumentUri(server, {
333+
uri: originalUri,
334+
file,
335+
view,
336+
languageId: effectiveLang,
337+
rootUri: metadata.rootUri,
338+
});
339+
if (!normalizedUri) {
340+
console.warn(
341+
`Cannot resolve document URI for formatting with ${server.id}: ${originalUri}`,
342+
);
343+
continue;
344+
}
357345
const context: RootUriContext = {
358346
uri: normalizedUri,
359347
languageId: effectiveLang,
@@ -530,7 +518,6 @@ export class LspClientManager {
530518
keymaps: builtinConfig.keymaps !== false,
531519
diagnostics: builtinConfig.diagnostics !== false,
532520
inlayHints: builtinConfig.inlayHints === true,
533-
documentHighlights: builtinConfig.documentHighlights !== false,
534521
formatting: builtinConfig.formatting !== false,
535522
})
536523
: { extensions: [], diagnosticsExtension: null };
@@ -841,28 +828,44 @@ export class LspClientManager {
841828
originalRootUri,
842829
} = params;
843830
const fileRefs = new Map<string, Set<EditorView>>();
831+
const uriAliases = new Map<string, string>();
844832
const effectiveRoot = normalizedRootUri ?? originalRootUri ?? null;
845833

846-
const attach = (uri: string, view: EditorView): void => {
834+
const attach = (
835+
uri: string,
836+
view: EditorView,
837+
aliases: string[] = [],
838+
): void => {
847839
const existing = fileRefs.get(uri) ?? new Set();
848840
existing.add(view);
849841
fileRefs.set(uri, existing);
842+
uriAliases.set(uri, uri);
843+
for (const alias of aliases) {
844+
if (!alias || alias === uri) continue;
845+
uriAliases.set(alias, uri);
846+
}
850847
const suffix = effectiveRoot ? ` (root ${effectiveRoot})` : "";
851848
logLspInfo(`[LSP:${server.id}] attached to ${uri}${suffix}`);
852849
};
853850

854851
const detach = (uri: string, view?: EditorView): void => {
855-
const existing = fileRefs.get(uri);
852+
const actualUri = uriAliases.get(uri) ?? uri;
853+
const existing = fileRefs.get(actualUri);
856854
if (!existing) return;
857855
if (view) existing.delete(view);
858856
if (!view || !existing.size) {
859-
fileRefs.delete(uri);
857+
fileRefs.delete(actualUri);
858+
for (const [alias, target] of uriAliases.entries()) {
859+
if (target === actualUri) {
860+
uriAliases.delete(alias);
861+
}
862+
}
860863
try {
861864
// Only pass uri to closeFile - view is not needed for closing
862865
// and passing it may cause issues if the view is already disposed
863-
(client.workspace as AcodeWorkspace)?.closeFile?.(uri);
866+
(client.workspace as AcodeWorkspace)?.closeFile?.(actualUri);
864867
} catch (error) {
865-
console.warn(`Failed to close LSP file ${uri}`, error);
868+
console.warn(`Failed to close LSP file ${actualUri}`, error);
866869
}
867870
}
868871

@@ -904,8 +907,6 @@ export class LspClientManager {
904907
server: LspServerDefinition,
905908
context: RootUriContext,
906909
): Promise<string | null> {
907-
if (context?.rootUri) return context.rootUri;
908-
909910
if (typeof server.rootUri === "function") {
910911
try {
911912
const value = await server.rootUri(context?.uri ?? "", context);
@@ -915,6 +916,8 @@ export class LspClientManager {
915916
}
916917
}
917918

919+
if (context?.rootUri) return safeString(context.rootUri);
920+
918921
if (typeof this.options.resolveRoot === "function") {
919922
try {
920923
const value = await this.options.resolveRoot(context);
@@ -926,6 +929,45 @@ export class LspClientManager {
926929

927930
return null;
928931
}
932+
933+
async #resolveDocumentUri(
934+
server: LspServerDefinition,
935+
context: RootUriContext,
936+
): Promise<string | null> {
937+
const originalUri = context?.uri;
938+
if (!originalUri) return null;
939+
940+
let normalizedUri = normalizeDocumentUri(originalUri);
941+
if (!normalizedUri) {
942+
// Fall back to cache file path for providers that do not expose a file:// URI.
943+
const cacheFile = context.file?.cacheFile;
944+
if (cacheFile && typeof cacheFile === "string") {
945+
normalizedUri = buildFileUri(cacheFile.replace(/^file:\/\//, ""));
946+
if (normalizedUri) {
947+
console.info(
948+
`LSP using cache path for unrecognized URI: ${originalUri} -> ${normalizedUri}`,
949+
);
950+
}
951+
}
952+
}
953+
954+
if (typeof server.documentUri === "function") {
955+
try {
956+
const value = await server.documentUri(originalUri, {
957+
...context,
958+
normalizedUri,
959+
} as DocumentUriContext);
960+
if (value) return safeString(value);
961+
} catch (error) {
962+
console.warn(
963+
`Server document URI resolver failed for ${server.id}`,
964+
error,
965+
);
966+
}
967+
}
968+
969+
return normalizedUri;
970+
}
929971
}
930972

931973
interface Change {

0 commit comments

Comments
 (0)