дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(usages): search Java usages in Project Files first, Project and Libraries on demand (#1837)
Цей коміт міститься в:
1 джерело
ef95cd1716
коміт
a6d17543fd
26 files changed
+963
-96
No files matched your search
@@ -5,12 +5,33 @@ vi.mock("@/workbench/contributions", async (orig) => ({
|
||||
...(await orig<typeof import("@/workbench/contributions")>()),
|
||||
toolWindowService: () => ({ show }),
|
||||
}));
|
||||
const referenceResponse = vi.fn();
|
||||
const lspReferences = vi.fn(async (..._args: unknown[]) => ({ status: "ok", data: null }));
|
||||
vi.mock("@/platform/ipc", async (orig) => {
|
||||
const actual = await orig<typeof import("@/platform/ipc")>();
|
||||
return { ...actual, commands: { ...actual.commands, lspReferences } };
|
||||
});
|
||||
vi.mock("./ipc", async (orig) => ({
|
||||
...(await orig<typeof import("./ipc")>()),
|
||||
readManyFileLines: async () => new Map([["/p/b.rs", ["", " used();"]]]),
|
||||
caretContext: () => ({ doc: 1, path: "/p/a.rs", line: 0, col: 0, word: "used", view: null }),
|
||||
lspRequest: (request: () => unknown) => {
|
||||
request();
|
||||
return referenceResponse();
|
||||
},
|
||||
readManyFileLines: async () => new Map([["/p/b.rs", ["", " used();", " used();"]]]),
|
||||
}));
|
||||
const channels: { onmessage: (refs: unknown) => void }[] = [];
|
||||
vi.mock("@tauri-apps/api/core", async (orig) => ({
|
||||
...(await orig<object>()),
|
||||
Channel: class {
|
||||
onmessage = () => {};
|
||||
constructor() {
|
||||
channels.push(this);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
const { activeUsageSearch, openUsageTab, pinUsageTab, resetUsages, showUsageResults, useUsages } =
|
||||
const { activeUsageSearch, findUsages, openUsageTab, pinUsageTab, resetUsages, showUsageResults, useUsages } =
|
||||
await import("./usages");
|
||||
|
||||
describe("showUsageResults", () => {
|
||||
@@ -25,6 +46,19 @@ describe("showUsageResults", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("shows the lines the server gave along for files it does not read", async () => {
|
||||
const lib = {
|
||||
path: "jdt://contents/lib/Lib.class",
|
||||
range: { start: { line: 3, col: 4 }, end: { line: 3, col: 8 } },
|
||||
};
|
||||
await showUsageResults({
|
||||
symbol: "used",
|
||||
locations: [lib],
|
||||
classified: [{ location: lib, kind: "unknown", text: " used();" }],
|
||||
});
|
||||
expect(activeUsageSearch(useUsages.getState())!.groups[0]!.usages[0]!.text).toBe(" used();");
|
||||
});
|
||||
|
||||
it("ignores malformed arguments", async () => {
|
||||
show.mockClear();
|
||||
await showUsageResults({ symbol: "x" });
|
||||
@@ -32,6 +66,47 @@ describe("showUsageResults", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("findUsages", () => {
|
||||
it("searches Project Files, then Project and Libraries on request", async () => {
|
||||
const at = { path: "/p/b.rs", range: { start: { line: 1, col: 4 }, end: { line: 1, col: 8 } } };
|
||||
lspReferences.mockClear();
|
||||
referenceResponse.mockResolvedValueOnce({ locations: [at], incomplete: null, librariesSkipped: true });
|
||||
await findUsages();
|
||||
const project = activeUsageSearch(useUsages.getState())!;
|
||||
expect(project).toMatchObject({ loading: false, scope: "project" });
|
||||
expect(lspReferences.mock.lastCall![5]).toBe(false);
|
||||
referenceResponse.mockResolvedValueOnce({ locations: [at], incomplete: null });
|
||||
project.searchLibraries!();
|
||||
await vi.waitFor(() => expect(activeUsageSearch(useUsages.getState())!.loading).toBe(false));
|
||||
expect(lspReferences.mock.lastCall![5]).toBe(true);
|
||||
const all = activeUsageSearch(useUsages.getState())!;
|
||||
expect(all.scope).toBe("libraries");
|
||||
// Rerun keeps the scope.
|
||||
referenceResponse.mockResolvedValueOnce({ locations: [at], incomplete: null });
|
||||
all.rerun!();
|
||||
await vi.waitFor(() => expect(lspReferences).toHaveBeenCalledTimes(3));
|
||||
expect(lspReferences.mock.lastCall![5]).toBe(true);
|
||||
resetUsages();
|
||||
});
|
||||
|
||||
it("shows the usages found first while it searches for the rest", async () => {
|
||||
const at = (line: number) => ({ path: "/p/b.rs", range: { start: { line, col: 4 }, end: { line, col: 8 } } });
|
||||
let resolve!: (refs: unknown) => void;
|
||||
referenceResponse.mockReturnValueOnce(new Promise((r) => (resolve = r)));
|
||||
const search = findUsages();
|
||||
await vi.waitFor(() => expect(channels).not.toHaveLength(0));
|
||||
channels.at(-1)!.onmessage({ locations: [at(1)], incomplete: null });
|
||||
await vi.waitFor(() => expect(activeUsageSearch(useUsages.getState())!.groups).toHaveLength(1));
|
||||
expect(activeUsageSearch(useUsages.getState())).toMatchObject({ loading: true, error: null });
|
||||
resolve({ locations: [at(1), at(2)], incomplete: null });
|
||||
await search;
|
||||
const done = activeUsageSearch(useUsages.getState())!;
|
||||
expect(done.loading).toBe(false);
|
||||
expect(done.groups[0]!.usages.map((u) => u.line)).toEqual([1, 2]);
|
||||
resetUsages();
|
||||
});
|
||||
});
|
||||
|
||||
describe("usage tabs", () => {
|
||||
const search = (id: number) => ({
|
||||
id,
|
||||
|
||||
Reference in new issue
Заблокувати користувача