дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
fix(lsp): open library classes behind jar: URIs (#1048)
The official Kotlin LSP answers navigation into a dependency with a `jar:///…/lib.jar!/pkg/Name.class` URI but does not serve its contents through `workspace/textDocumentContent`, so opening the target failed with "no language server provides the contents of jar:…", locally and remotely. `jar:` URIs are now resolved by the backend, where the jars are: - An entry that is not a class (a sources jar entry, a resource) is read from its archive. - A class is shown as its source from the artifact's `-sources.jar` in the Maven repository or the Gradle cache (`Name.java`/`Name.kt`, an inner class's outer file, a `FileKt` facade's `File.kt`, a `@file:JvmName` file); Go to Declaration then lands on the declaration of the name it was invoked on. - Otherwise the server's `decompile` command is used when it offers one, and the error says that neither a source nor a decompiler is available. - Library tabs name the archive and package (`spring-boot-3.5.16.jar › org.springframework.boot`). Fixes #982
Цей коміт міститься в:
1 джерело
98517019e7
коміт
d54ef98a59
8 files changed
+504
-24
No files matched your search
@@ -19,6 +19,15 @@ describe("virtual document URIs", () => {
|
||||
expect(virtualName(JDT)).toBe("SpringApplication.class");
|
||||
expect(virtualParent(JDT)).toBe("jdt://contents/spring-boot-4.1.1.jar/org.springframework.boot");
|
||||
expect(virtualContainer(JDT)).toBe("spring-boot-4.1.1.jar › org.springframework.boot");
|
||||
// `jar:` targets (official Kotlin LSP, sources jars), in both URI forms.
|
||||
for (const prefix of ["jar:///", "jar:file:///"])
|
||||
expect(
|
||||
virtualContainer(
|
||||
`${prefix}home/me/.m2/repository/spring-boot-3.5.16-sources.jar!/org/springframework/boot/SpringApplicationExtensions.kt`,
|
||||
),
|
||||
).toBe("spring-boot-3.5.16-sources.jar › org.springframework.boot");
|
||||
expect(virtualContainer("jar:///tmp/my%20libs/a.jar!/Root.class")).toBe("a.jar");
|
||||
expect(virtualName("jar:///tmp/a.jar!/org/x/Y.class")).toBe("Y.class");
|
||||
});
|
||||
|
||||
it("makes path helpers URI-aware", () => {
|
||||
|
||||
@@ -37,6 +37,20 @@ export function virtualParent(uri: string): string {
|
||||
*/
|
||||
export function virtualContainer(uri: string): string {
|
||||
const scheme = uri.slice(0, uri.indexOf(":"));
|
||||
// `jar:///…/spring-boot-3.5.16.jar!/org/springframework/boot/X.class` → `spring-boot-3.5.16.jar › org.springframework.boot`
|
||||
const jar = scheme === "jar" ? /^jar:(?:file:)?(?:\/\/)?(.*?)!\/(.*)$/.exec(uri.split(/[?#]/)[0]!) : null;
|
||||
if (jar) {
|
||||
const decode = (s: string) => {
|
||||
try {
|
||||
return decodeURIComponent(s);
|
||||
} catch {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
const archive = decode(jar[1]!.split("/").pop() ?? jar[1]!);
|
||||
const pkg = jar[2]!.split("/").slice(0, -1).map(decode).join(".");
|
||||
return pkg ? `${archive} › ${pkg}` : archive;
|
||||
}
|
||||
const rest = uri.replace(/^[^:]+:(\/\/)?/, "").split(/[?#]/)[0]!;
|
||||
const segs = rest
|
||||
.split("/")
|
||||
|
||||
Reference in new issue
Заблокувати користувача