diff --git a/src/editor/lsp/outsideProject.test.ts b/src/editor/lsp/outsideProject.test.ts index df0514b27..72296903f 100644 --- a/src/editor/lsp/outsideProject.test.ts +++ b/src/editor/lsp/outsideProject.test.ts @@ -1,4 +1,5 @@ -import { expect, it } from "vitest"; +import { afterEach, expect, it } from "vitest"; +import { useProject } from "@/platform/project"; import { outsideProjectNotice } from "./outsideProject"; const text = (message: string) => outsideProjectNotice(message)?.text ?? null; @@ -36,7 +37,22 @@ it("recognizes each server's report that a file is outside its projects", () => expect(outsideProjectNotice("No packages found for open file x.go.")?.reload).toBeFalsy(); }); +afterEach(() => useProject.setState({ project: null })); + +const openProject = (root: string, projects?: string[]) => + useProject.setState({ + project: { + root, + name: "p", + trusted: true, + isGit: false, + settings: {}, + ...(projects && { workspace: { version: 1, name: "p", projects } }), + }, + }); + it("shows a banner while the server reports the file, with the build reloads available", async () => { + openProject("/p"); const { renderHook, act } = await import("@testing-library/react"); const { setFileDiagnostics } = await import("./diagnostics"); const { registerActions } = await import("@/platform/actions"); @@ -64,3 +80,39 @@ it("shows a banner while the server reports the file, with the build reloads ava setFileDiagnostics(path, "jdtls", []); } }); + +it("offers a build reload only for files of the open project", async () => { + const { renderHook, act } = await import("@testing-library/react"); + const { setFileDiagnostics } = await import("./diagnostics"); + const { registerActions } = await import("@/platform/actions"); + const { outsideProjectBanner } = await import("./outsideProject"); + const off = registerActions([{ id: "maven.reload", title: "Reload All Maven Projects", run: () => {} }]); + openProject("/ws", ["/p"]); + // A scratch lives in the app data dir; a module the import missed lives in the project. + const cases: [string, string[]][] = [ + ["/data/scratches/scratch.java", []], + ["/p/tools/Gen.java", ["Reload Maven Projects"]], + ["/ws/Gen.java", ["Reload Maven Projects"]], + ]; + try { + for (const [path, labels] of cases) { + const { result } = renderHook(() => outsideProjectBanner.useBanner(path)); + const warning = { + range: { start: { line: 0, col: 0 }, end: { line: 0, col: 1 } }, + severity: "warning" as const, + message: `${path.split("/").pop()} is a non-project file, only syntax errors are reported`, + source: "Java", + code: "32", + }; + act(() => setFileDiagnostics(path, "jdtls", [warning])); + expect(result.current?.text, path).toMatch(/only JDK classes resolve/); + expect( + result.current?.actions?.map((a) => a.label), + path, + ).toEqual(labels); + act(() => setFileDiagnostics(path, "jdtls", [])); + } + } finally { + off(); + } +}); diff --git a/src/editor/lsp/outsideProject.ts b/src/editor/lsp/outsideProject.ts index 7ce7ec885..9d8c8e85f 100644 --- a/src/editor/lsp/outsideProject.ts +++ b/src/editor/lsp/outsideProject.ts @@ -6,10 +6,15 @@ */ import { useSyncExternalStore } from "react"; import { executeAction, getAction, isActionEnabled } from "@/platform/actions"; +import { isSameOrInside } from "@/platform/paths"; +import { useProject } from "@/platform/project"; import type { EditorBannerContribution } from "@/workbench/contributions"; import { diagnosticsFor, subscribeDiagnostics } from "./diagnostics"; -/** `reload`: a build reload may bring the file into a project (a module the import missed). */ +/** + * `reload`: a build reload may bring the file into a project (a module the import missed); offered + * only for files inside the open project. + */ const NOTICES: readonly { test: RegExp; text: string; reload?: boolean }[] = [ // jdtls: "Foo.java is not on the classpath of project app, only syntax errors are reported" { @@ -17,10 +22,11 @@ const NOTICES: readonly { test: RegExp; text: string; reload?: boolean }[] = [ text: "This file is outside the source folders of its Java module: only syntax errors are reported, and navigation and completion don't work.", reload: true, }, - // jdtls: "Foo.java is a non-project file, only syntax errors are reported" + // jdtls: "Foo.java is a non-project file, only syntax errors are reported". jdtls still completes + // and navigates JDK classes in such a file (a scratch, a file opened from outside the project). { test: /is a non-project file, only syntax errors are reported/, - text: "This file does not belong to an imported Java project: only syntax errors are reported, and navigation and completion don't work.", + text: "This file does not belong to an imported Java project: only syntax errors are reported, and only JDK classes resolve.", reload: true, }, // gopls, before its generic "No packages found" below. @@ -73,13 +79,17 @@ export const outsideProjectBanner: EditorBannerContribution = { (l) => subscribeDiagnostics(path, l), () => noticeFor(path), ); + const inProject = useProject(({ project }) => + [project?.root, ...(project?.workspace?.projects ?? [])].some((root) => !!root && isSameOrInside(path, root)), + ); if (!notice) return null; - const actions = notice.reload - ? RELOADS.filter(({ id }) => { - const action = getAction(id); - return action && isActionEnabled(action); - }).map(({ id, label }) => ({ label, run: () => void executeAction(id) })) - : []; + const actions = + notice.reload && inProject + ? RELOADS.filter(({ id }) => { + const action = getAction(id); + return action && isActionEnabled(action); + }).map(({ id, label }) => ({ label, run: () => void executeAction(id) })) + : []; return { text: notice.text, level: "warning", actions }; }, }; diff --git a/src/platform/locales/text/fr.json b/src/platform/locales/text/fr.json index 2bfbaf8b4..dd7aea5f8 100644 --- a/src/platform/locales/text/fr.json +++ b/src/platform/locales/text/fr.json @@ -5494,7 +5494,7 @@ "oxfmt formatting failed": "Échec du formatage avec oxfmt", "oxfmt formatting timed out": "Le formatage avec oxfmt a expiré", "This file is outside the source folders of its Java module: only syntax errors are reported, and navigation and completion don't work.": "Ce fichier est en dehors des dossiers sources de son module Java : seules les erreurs de syntaxe sont signalées, et la navigation et la complétion ne fonctionnent pas.", - "This file does not belong to an imported Java project: only syntax errors are reported, and navigation and completion don't work.": "Ce fichier n'appartient à aucun projet Java importé : seules les erreurs de syntaxe sont signalées, et la navigation et la complétion ne fonctionnent pas.", + "This file does not belong to an imported Java project: only syntax errors are reported, and only JDK classes resolve.": "Ce fichier n'appartient à aucun projet Java importé : seules les erreurs de syntaxe sont signalées, et seules les classes du JDK sont résolues.", "This Go file belongs to no package of the workspace: code insight is limited.": "Ce fichier Go n'appartient à aucun paquet de l'espace de travail : l'analyse du code est limitée.", "This Rust file is not included in any crate: rust-analyzer can't offer code insight for it.": "Ce fichier Rust n'est inclus dans aucune crate : rust-analyzer ne peut pas proposer d'analyse du code pour celui-ci.", "Reload Maven Projects": "Recharger les projets Maven", diff --git a/src/platform/locales/text/ko.json b/src/platform/locales/text/ko.json index 6595d1a48..caa87c948 100644 --- a/src/platform/locales/text/ko.json +++ b/src/platform/locales/text/ko.json @@ -5627,7 +5627,7 @@ "Java project import failed": "Java 프로젝트 가져오기 실패", "The Java project cannot be imported because these files use a name Windows reserves for devices: {paths}. Delete or rename them, then restart the Java language server.": "다음 파일이 Windows에서 장치용으로 예약된 이름을 사용하므로 Java 프로젝트를 가져올 수 없습니다: {paths}. 파일을 삭제하거나 이름을 변경한 후 Java 언어 서버를 다시 시작하세요.", "This file is outside the source folders of its Java module: only syntax errors are reported, and navigation and completion don't work.": "이 파일은 해당 Java 모듈의 소스 폴더 밖에 있습니다. 구문 오류만 보고되며 탐색과 코드 완성이 작동하지 않습니다.", - "This file does not belong to an imported Java project: only syntax errors are reported, and navigation and completion don't work.": "이 파일은 가져온 Java 프로젝트에 속하지 않습니다. 구문 오류만 보고되며 탐색과 코드 완성이 작동하지 않습니다.", + "This file does not belong to an imported Java project: only syntax errors are reported, and only JDK classes resolve.": "이 파일은 가져온 Java 프로젝트에 속하지 않습니다. 구문 오류만 보고되며 JDK 클래스만 확인됩니다.", "This Go file belongs to no package of the workspace: code insight is limited.": "이 Go 파일은 작업 공간의 어떤 패키지에도 속하지 않습니다. 코드 인사이트가 제한됩니다.", "This Rust file is not included in any crate: rust-analyzer can't offer code insight for it.": "이 Rust 파일은 어떤 crate에도 포함되어 있지 않습니다. rust-analyzer가 코드 인사이트를 제공할 수 없습니다.", "Reload Maven Projects": "Maven 프로젝트 다시 로드", diff --git a/src/platform/locales/text/zh.json b/src/platform/locales/text/zh.json index 6f027b9ab..f38f73f68 100644 --- a/src/platform/locales/text/zh.json +++ b/src/platform/locales/text/zh.json @@ -5655,7 +5655,7 @@ "Java project import failed": "Java 项目导入失败", "The Java project cannot be imported because these files use a name Windows reserves for devices: {paths}. Delete or rename them, then restart the Java language server.": "无法导入 Java 项目,因为这些文件使用了 Windows 保留的设备名:{paths}。请删除或重命名这些文件,然后重启 Java 语言服务器。", "This file is outside the source folders of its Java module: only syntax errors are reported, and navigation and completion don't work.": "此文件不在所属 Java 模块的源码目录中:只报告语法错误,跳转和补全不可用。", - "This file does not belong to an imported Java project: only syntax errors are reported, and navigation and completion don't work.": "此文件不属于已导入的 Java 项目:只报告语法错误,跳转和补全不可用。", + "This file does not belong to an imported Java project: only syntax errors are reported, and only JDK classes resolve.": "此文件不属于已导入的 Java 项目:只报告语法错误,只能解析 JDK 中的类。", "This Go file belongs to no package of the workspace: code insight is limited.": "此 Go 文件不属于工作区中的任何包:代码洞察功能受限。", "This Rust file is not included in any crate: rust-analyzer can't offer code insight for it.": "此 Rust 文件未包含在任何 crate 中:rust-analyzer 无法为它提供代码洞察。", "Reload Maven Projects": "重新加载 Maven 项目",