mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 17:02:17 +00:00
Project & files - Project view modes (Project Files / Open Files / All Changed Files / Scratches); External Libraries for Python, JDK (src.zip), Node, Cargo, Go, Maven/Gradle jars; read-only jar/zip browsing - ⌘N New popup with type search and more file kinds; New Project, Rename Project, Reload All from Disk, Export/Import Settings, Power Save Mode - File type associations, extra content roots and exclude patterns (indexed and watched without reopening the project) Editor & navigation - Find bar: search scope (comments/strings), Preserve Case, Exclude, multiline, history; Find in Files: Module scope, custom pattern scopes, multiline - Search Everywhere filters, Assign Shortcut, settings results; named bookmark lists, file/folder bookmarks; Structure filters and Show Inherited; Recent Locations timestamps and breadcrumbs; Code Vision author - Completion options, editor tab placement/layout, inline completion (LSP 3.18) - Spell checking (Typo inspection, ide-spell) and Inspections settings with custom profiles; Code Style schemes, formatter markers, Do not format Run, VCS, services, database - Typed run configurations (Shell, Program, npm, Gradle, Maven, Docker, Compound), Modify options, Before launch, env dialog, Current File, Emulate terminal (PTY) - Git log graph/view options, Go to Hash/Branch/Tag, date filter keeps the graph; Pull/Merge/Rebase dialogs, Manage Remotes, Worktrees - Generic Services host (Docker connections/registries, run sessions); TODO scope/changes tabs with changelists; Coverage report import - Data sources: wire-compatible vendors, URL import, SSL certs, Options, Schemas and Advanced tabs, color and comment Workbench - Run Anything, Customize Main Toolbar, named tool window layouts, menu completeness, Code Cleanup, macros, "Don't Show Again", editor banners - Chinese translations for the new UI Claude-Session: https://claude.ai/code/session_01SaPPsVPuk6ZTNsoUCNCbMv
84 lines
3.3 KiB
TypeScript
84 lines
3.3 KiB
TypeScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import type { Diagnostic } from "@/bindings";
|
|
import {
|
|
applyDiagnosticsEvent,
|
|
clearProblems,
|
|
countSeverities,
|
|
fileDiagnostics,
|
|
mergeDiagnostics,
|
|
profiledProblems,
|
|
projectCounts,
|
|
useProblems,
|
|
worstSeverity,
|
|
} from "./problemsStore";
|
|
import { problemDecorations } from "./decorations";
|
|
|
|
const d = (line: number, severity: Diagnostic["severity"] = "error", source: string | null = null): Diagnostic => ({
|
|
range: { start: { line, col: 0 }, end: { line, col: 1 } },
|
|
severity,
|
|
message: `line ${line}`,
|
|
source,
|
|
code: null,
|
|
});
|
|
|
|
describe("mergeDiagnostics", () => {
|
|
it("replaces per (file, source) and keeps other sources", () => {
|
|
let map = mergeDiagnostics(new Map(), "/a", "ra", [d(3), d(1)]);
|
|
map = mergeDiagnostics(map, "/a", "clippy", [d(2, "warning")]);
|
|
expect(fileDiagnostics(map, "/a").map((x) => [x.range.start.line, x.source])).toEqual([
|
|
[1, "ra"],
|
|
[2, "clippy"],
|
|
[3, "ra"],
|
|
]);
|
|
map = mergeDiagnostics(map, "/a", "ra", [d(5, "info")]);
|
|
expect(fileDiagnostics(map, "/a").map((x) => x.range.start.line)).toEqual([2, 5]);
|
|
});
|
|
|
|
it("drops files whose sources are all empty and is a no-op for unknown clears", () => {
|
|
const a = mergeDiagnostics(new Map(), "/a", "ra", [d(1)]);
|
|
expect(mergeDiagnostics(a, "/a", "other", [])).toBe(a);
|
|
expect(mergeDiagnostics(a, "/b", "ra", [])).toBe(a);
|
|
const cleared = mergeDiagnostics(a, "/a", "ra", []);
|
|
expect(cleared.has("/a")).toBe(false);
|
|
});
|
|
|
|
it("keeps an item's own source", () => {
|
|
const map = mergeDiagnostics(new Map(), "/a", "eslint", [d(1, "error", "eslint/no-undef")]);
|
|
expect(fileDiagnostics(map, "/a")[0]!.source).toBe("eslint/no-undef");
|
|
});
|
|
});
|
|
|
|
describe("counts", () => {
|
|
it("counts per severity", () => {
|
|
let map = mergeDiagnostics(new Map(), "/a", "ra", [d(1), d(2, "warning")]);
|
|
map = mergeDiagnostics(map, "/b", "ra", [d(1, "warning"), d(2, "hint")]);
|
|
expect(projectCounts(map)).toEqual({ error: 1, warning: 2, info: 0, hint: 1 });
|
|
expect(countSeverities(fileDiagnostics(map, "/b"))).toEqual({ error: 0, warning: 1, info: 0, hint: 1 });
|
|
expect(worstSeverity(fileDiagnostics(map, "/b"))).toBe("warning");
|
|
expect(worstSeverity([])).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("store + decorations", () => {
|
|
beforeEach(() => clearProblems());
|
|
|
|
it("applies events and decorates only files with errors", () => {
|
|
applyDiagnosticsEvent("/p/src/a.rs", "ra", [d(1), d(2, "warning")]);
|
|
applyDiagnosticsEvent("/p/src/b.rs", "ra", [d(1, "warning")]);
|
|
const deco = problemDecorations(useProblems.getState().map);
|
|
expect([...deco.keys()]).toEqual(["/p/src/a.rs"]);
|
|
expect(deco.get("/p/src/a.rs")).toEqual({ error: true, propagate: true, tooltip: "1 error, 1 warning" });
|
|
});
|
|
});
|
|
|
|
describe("profiledProblems", () => {
|
|
it("applies the inspection profile per producer", () => {
|
|
let raw = mergeDiagnostics(new Map(), "/a", "ra", [d(1), d(2, "warning")]);
|
|
raw = mergeDiagnostics(raw, "/b", "eslint", [d(3)]);
|
|
const out = profiledProblems(raw, { "lsp:eslint": { enabled: false }, "lsp:ra": { severity: "weakWarning" } });
|
|
expect([...out.keys()]).toEqual(["/a"]);
|
|
expect(fileDiagnostics(out, "/a").map((x) => x.severity)).toEqual(["info", "info"]);
|
|
expect(fileDiagnostics(profiledProblems(raw, {}), "/b")).toHaveLength(1);
|
|
});
|
|
});
|