mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-15 08:08:18 +00:00
fix(debugger): keep watches per project (#3293)
Watches were one list shared by every project, so a watch added while debugging one project showed up, and usually failed to evaluate, in all the others. Each project now keeps its own list; a project without one starts from the old shared list once, since that list doesn't record which project each watch came from. Co-authored-by: ntbang0901 <121003585+ntbang0901@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { addWatch, loadWatches, useDebug } from "../state";
|
||||
|
||||
const SHARED = "openidea.debugger.watches";
|
||||
const of = (root: string) => `${SHARED}:${root}`;
|
||||
const watches = () => useDebug.getState().watches;
|
||||
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
loadWatches(null);
|
||||
});
|
||||
|
||||
describe("watch storage", () => {
|
||||
it("loads a project's own watches", () => {
|
||||
localStorage.setItem(of("/a"), '["x"]');
|
||||
loadWatches("/a");
|
||||
expect(watches()).toEqual(["x"]);
|
||||
});
|
||||
|
||||
it("starts a project from the shared list once", () => {
|
||||
localStorage.setItem(SHARED, '["legacy"]');
|
||||
loadWatches("/b");
|
||||
expect(watches()).toEqual(["legacy"]);
|
||||
expect(localStorage.getItem(of("/b"))).toBe('["legacy"]');
|
||||
expect(localStorage.getItem(SHARED)).toBe('["legacy"]');
|
||||
});
|
||||
|
||||
it("keeps projects apart", () => {
|
||||
loadWatches("/a");
|
||||
addWatch("y");
|
||||
loadWatches("/b");
|
||||
expect(watches()).not.toContain("y");
|
||||
loadWatches("/a");
|
||||
expect(watches()).toContain("y");
|
||||
});
|
||||
|
||||
it("an emptied list stays empty", () => {
|
||||
localStorage.setItem(SHARED, '["legacy"]');
|
||||
localStorage.setItem(of("/a"), "[]");
|
||||
loadWatches("/a");
|
||||
expect(watches()).toEqual([]);
|
||||
});
|
||||
|
||||
it("without a project nothing is stored", () => {
|
||||
loadWatches(null);
|
||||
addWatch("z");
|
||||
expect(localStorage.length).toBe(0);
|
||||
});
|
||||
});
|
||||
@@ -57,7 +57,7 @@ export function activate(): () => void {
|
||||
useDebugRunSessions.setState({
|
||||
Console: lazyComponent(() => import("./ui/DebugConsole").then((m) => m.DebugServiceConsole)),
|
||||
});
|
||||
loadWatches();
|
||||
loadWatches(useProject.getState().project?.root ?? null);
|
||||
publishContext();
|
||||
loadBreakpoints(useProject.getState().project?.root ?? null);
|
||||
loadExceptionBreakpoints(useProject.getState().project?.root ?? null);
|
||||
@@ -136,6 +136,7 @@ export function activate(): () => void {
|
||||
const root = s.project?.root ?? null;
|
||||
if (root !== (prev.project?.root ?? null) || s.project?.trusted !== prev.project?.trusted) {
|
||||
resetSessions();
|
||||
loadWatches(root);
|
||||
loadBreakpoints(root);
|
||||
loadExceptionBreakpoints(root);
|
||||
loadSpecialBreakpoints(root);
|
||||
|
||||
@@ -1025,25 +1025,40 @@ export function removeWatch(expression: string) {
|
||||
persistWatches();
|
||||
}
|
||||
|
||||
const WATCH_KEY = "openidea.debugger.watches";
|
||||
/** Watches used to be one list for every project; it is only read now, as a project's first list. */
|
||||
const SHARED_WATCH_KEY = "openidea.debugger.watches";
|
||||
const watchKey = (root: string) => `${SHARED_WATCH_KEY}:${root}`;
|
||||
|
||||
/** The project whose watches are loaded; without one they aren't stored. */
|
||||
let watchRoot: string | null = null;
|
||||
|
||||
function persistWatches() {
|
||||
if (watchRoot == null) return;
|
||||
try {
|
||||
localStorage.setItem(WATCH_KEY, JSON.stringify(useDebug.getState().watches));
|
||||
localStorage.setItem(watchKey(watchRoot), JSON.stringify(useDebug.getState().watches));
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
export function loadWatches() {
|
||||
function storedWatches(key: string): string[] | null {
|
||||
try {
|
||||
const raw = JSON.parse(localStorage.getItem(WATCH_KEY) ?? "[]") as unknown;
|
||||
if (Array.isArray(raw)) useDebug.setState({ watches: raw.filter((w): w is string => typeof w === "string") });
|
||||
const stored = localStorage.getItem(key);
|
||||
const raw = stored == null ? null : (JSON.parse(stored) as unknown);
|
||||
return Array.isArray(raw) ? raw.filter((w): w is string => typeof w === "string") : null;
|
||||
} catch {
|
||||
// ignore
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The watches of the project at `root`. */
|
||||
export function loadWatches(root: string | null) {
|
||||
watchRoot = root;
|
||||
const own = root == null ? [] : storedWatches(watchKey(root));
|
||||
useDebug.setState({ watches: own ?? storedWatches(SHARED_WATCH_KEY) ?? [] });
|
||||
if (own == null) persistWatches();
|
||||
}
|
||||
|
||||
/**
|
||||
* "Set Value" (F2 in the variables tree): `setVariable` in `container`, or
|
||||
* `setExpression` on the evaluate name. Refreshes variables, watches and inline values.
|
||||
|
||||
Reference in New Issue
Block a user