-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathkinds.ts
More file actions
99 lines (84 loc) · 3.38 KB
/
Copy pathkinds.ts
File metadata and controls
99 lines (84 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Handler logic for mdsmith.kinds.why and mdsmith.kinds.resolve.
// Both commands open a read-only virtual document populated from the
// JSON output of the corresponding kinds subcommand.
import { SpawnFn, defaultSpawn } from "./runner";
import { buildResolveUri, buildWhyUri, fetchKindsContent } from "./virtual-doc";
export interface DiagnosticLike {
code?: string | number | { value: string | number; target: unknown };
source?: string;
}
// extractRuleIds pulls the mdsmith rule IDs (e.g. "MDS001") out of an
// array of VS Code diagnostic objects. Only diagnostics whose source is
// "mdsmith" and whose code is a plain string are included.
export function extractRuleIds(diagnostics: DiagnosticLike[]): string[] {
const ids = new Set<string>();
for (const d of diagnostics) {
if (d.source !== "mdsmith") continue;
if (typeof d.code === "string" && d.code) ids.add(d.code);
}
return Array.from(ids).sort();
}
// KindsResolveHandlerDeps covers the resolve command, which needs no rule picker.
// binary/workspaceRoot/spawn are NOT included here — they belong to
// makeKindsContentProvider, which owns the spawning.
export interface KindsResolveHandlerDeps {
getActiveFilePath: () => string | undefined;
getDiagnostics: (filePath: string) => DiagnosticLike[];
openVirtualDoc: (uri: string) => Promise<void>;
showError: (msg: string) => Promise<void>;
isTrusted: () => boolean;
}
// KindsWhyHandlerDeps extends resolve deps with a rule picker for the why command.
export interface KindsWhyHandlerDeps extends KindsResolveHandlerDeps {
pickRule: (rules: string[]) => Promise<string | undefined>;
}
export async function runKindsResolve(deps: KindsResolveHandlerDeps): Promise<void> {
if (!deps.isTrusted()) {
await deps.showError("mdsmith: Show resolved config requires a trusted workspace.");
return;
}
const filePath = deps.getActiveFilePath();
if (!filePath) {
await deps.showError("mdsmith: Open a Markdown file first.");
return;
}
const uri = buildResolveUri(filePath);
await deps.openVirtualDoc(uri);
}
export async function runKindsWhy(deps: KindsWhyHandlerDeps): Promise<void> {
if (!deps.isTrusted()) {
await deps.showError("mdsmith: Explain rule requires a trusted workspace.");
return;
}
const filePath = deps.getActiveFilePath();
if (!filePath) {
await deps.showError("mdsmith: Open a Markdown file first.");
return;
}
const diagnostics = deps.getDiagnostics(filePath);
const ruleIds = extractRuleIds(diagnostics);
const rule = await deps.pickRule(ruleIds);
if (!rule) return;
const uri = buildWhyUri(filePath, rule);
await deps.openVirtualDoc(uri);
}
// KindsContentProvider is the structural interface for a VS Code
// TextDocumentContentProvider. Defined here so extension.ts can
// implement it without importing vscode in this module.
export interface KindsContentProvider {
provideTextDocumentContent(uri: string): Promise<string>;
}
// makeKindsContentProvider returns a content provider that fetches
// kinds output for the given binary and workspace. The spawn function
// is injectable for testing.
export function makeKindsContentProvider(
binary: string,
workspaceRoot: string | undefined,
spawn: SpawnFn = defaultSpawn
): KindsContentProvider {
return {
async provideTextDocumentContent(uri: string): Promise<string> {
return fetchKindsContent(uri, binary, workspaceRoot, spawn);
},
};
}