fix(spelling): Rename identifiers on Typo fixes, add inspection controls, cut false positives (#51)

Root causes: Typo "Change to" replaced one occurrence even for declared names (breaking references); inspections had no Disable / Edit settings controls anywhere; en_US Hunspell does not derive agent nouns like "checkpointer" and compound identifier words were flagged; local inspections (Typo, file references, SQL) never reached Problems.
Fix (IDEA): "Typo: Rename to…" renames via LSP rename, falling back to syntax-based local rename, never a silent single replace, and lists identifier-safe words only; intention submenu (→) with Edit inspection profile setting / Disable inspection for every inspection; Problems and Inspection Results get Disable Inspection, Change Severity, Edit Inspection Profile Setting; Typo options Process code / literals / comments; -er/-ers derivation and identifier compounds accepted, common misspellings still flagged.
Siblings covered: all LSP and built-in inspections' intentions, file reference and SQL inspections in Problems, severity counter.
Verified: ide-spell tests (issue examples + ~50 real misspellings), vitest (286), in-app on macOS: only 'mesage' flagged, submenu, Rename to → 'message' updated both occurrences.

Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-27 10:38:53 +08:00
1 джерело eda8cae0a1
коміт aa5821bb46
32 files changed
+1289 -61

No files matched your search

+22
Переглянути файл
@@ -81,3 +81,25 @@ describe("profiledProblems", () => {
expect(fileDiagnostics(profiledProblems(raw, {}), "/b")).toHaveLength(1);
});
});
describe("local inspections (issue #42)", () => {
it("reach Problems and clear there too, with their inspection known", async () => {
const { installProblemsEvents, producerFor } = await import("./problemsStore");
const { setFileDiagnostics } = await import("@/editor/lsp/diagnostics");
const { diagnosticInspection } = await import("@/platform/inspections");
clearProblems();
const off = installProblemsEvents();
try {
setFileDiagnostics("/p/a.py", "spelling", [{ ...d(0, "info"), message: "Typo: In word 'mesage'", source: "Spelling" }]);
const [typo] = fileDiagnostics(useProblems.getState().map, "/p/a.py");
expect(typo).toMatchObject({ message: "Typo: In word 'mesage'", typo: true });
const producer = producerFor(useProblems.getState().map, "/p/a.py", typo!);
expect(producer).toBe("spelling");
expect(diagnosticInspection(producer!, typo!)?.id).toBe("builtin:spelling");
setFileDiagnostics("/p/a.py", "spelling", []);
expect(useProblems.getState().map.size).toBe(0);
} finally {
off();
}
});
});