Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

Commit 81d2533

Browse files
TechatrixVexu
authored andcommitted
replace extension based build on save and unify config options with ZLS
1 parent c7cf4cf commit 81d2533

File tree

7 files changed

+291
-249
lines changed

7 files changed

+291
-249
lines changed

package.json

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -70,42 +70,23 @@
7070
"column": 3,
7171
"severity": 4,
7272
"message": 5
73+
},
74+
"background": {
75+
"activeOnStart": true,
76+
"beginsPattern": "^Build Summary:",
77+
"endsPattern": "^error: (\\d+ compilation errors|the following command failed with )"
7378
}
7479
}
7580
],
81+
"taskDefinitions": [
82+
{
83+
"type": "zig"
84+
}
85+
],
7686
"configuration": {
7787
"type": "object",
7888
"title": "Zig",
7989
"properties": {
80-
"zig.buildOnSave": {
81-
"type": "boolean",
82-
"default": false,
83-
"description": "Compiles code on file save using the settings specified in 'Build Option'. Should not be used with ZLS's build on save feature."
84-
},
85-
"zig.buildOption": {
86-
"type": "string",
87-
"default": "build",
88-
"enum": [
89-
"build",
90-
"build-exe",
91-
"build-lib",
92-
"build-obj"
93-
],
94-
"description": "Which build command Zig should use to build the code."
95-
},
96-
"zig.buildArgs": {
97-
"type": "array",
98-
"items": {
99-
"type": "string"
100-
},
101-
"default": [],
102-
"description": "Extra arguments to passed to Zig."
103-
},
104-
"zig.buildFilePath": {
105-
"type": "string",
106-
"default": "${workspaceFolder}/build.zig",
107-
"description": "The path to build.zig. This is only required if zig.buildOptions = build."
108-
},
10990
"zig.path": {
11091
"scope": "machine-overridable",
11192
"type": "string",
@@ -171,6 +152,38 @@
171152
"default": "lldb",
172153
"description": "The debug adapter command to run when starting a debug session"
173154
},
155+
"zig.buildOnSaveProvider": {
156+
"scope": "resource",
157+
"type": "string",
158+
"description": "Specify how build on save diagnostics should be provided.",
159+
"enum": [
160+
"off",
161+
"auto",
162+
"extension",
163+
"zls"
164+
],
165+
"enumItemLabels": [
166+
"Disabled",
167+
"Automatic",
168+
"Extension",
169+
"ZLS language server"
170+
],
171+
"enumDescriptions": [
172+
"Disable build on save",
173+
"Disabled unless ZLS has enabled [build on save](https://zigtools.org/zls/guides/build-on-save/) automatically.",
174+
"Provide build on save by running `zig build --watch`",
175+
"Provide build on save using ZLS"
176+
],
177+
"default": "auto"
178+
},
179+
"zig.buildOnSaveArgs": {
180+
"type": "array",
181+
"items": {
182+
"type": "string"
183+
},
184+
"default": [],
185+
"description": "Specify which additional arguments should be passed to `zig build` when running build on save. Use the `--build-file` argument to override which build file should be used."
186+
},
174187
"zig.zls.debugLog": {
175188
"scope": "resource",
176189
"type": "boolean",
@@ -222,18 +235,6 @@
222235
"description": "Whether to show the function signature in completion results. May improve readability in some editors when disabled",
223236
"default": true
224237
},
225-
"zig.zls.enableBuildOnSave": {
226-
"scope": "resource",
227-
"type": "boolean",
228-
"description": "Whether to enable build-on-save diagnostics. Will be automatically enabled if the `build.zig` has declared a 'check' step.\n\nFor more infromation, checkout the [Build-On-Save](https://zigtools.org/zls/guides/build-on-save/) Guide.",
229-
"default": null
230-
},
231-
"zig.zls.buildOnSaveArgs": {
232-
"scope": "resource",
233-
"type": "array",
234-
"description": "Specify which arguments should be passed to Zig when running build-on-save.\n\nIf the `build.zig` has declared a 'check' step, it will be preferred over the default 'install' step.",
235-
"default": []
236-
},
237238
"zig.zls.semanticTokens": {
238239
"scope": "resource",
239240
"type": "string",
@@ -360,12 +361,6 @@
360361
"category": "Zig",
361362
"description": "Debug the current Zig project / file"
362363
},
363-
{
364-
"command": "zig.build.workspace",
365-
"title": "Build Workspace",
366-
"category": "Zig",
367-
"description": "Build the current project using 'zig build'"
368-
},
369364
{
370365
"command": "zig.install",
371366
"title": "Install Zig",

src/extension.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import vscode from "vscode";
22

33
import { activate as activateZls, deactivate as deactivateZls } from "./zls";
4-
import ZigDiagnosticsProvider from "./zigDiagnosticsProvider";
54
import ZigMainCodeLensProvider from "./zigMainCodeLens";
65
import ZigTestRunnerProvider from "./zigTestRunnerProvider";
6+
import { registerBuildOnSaveProvider } from "./zigBuildOnSaveProvider";
7+
import { registerDiagnosticsProvider } from "./zigDiagnosticsProvider";
78
import { registerDocumentFormatting } from "./zigFormat";
89
import { registerTerminalStateManagement } from "./terminalState";
910
import { setupZig } from "./zigSetup";
1011

1112
export async function activate(context: vscode.ExtensionContext) {
1213
await setupZig(context).finally(() => {
13-
const compiler = new ZigDiagnosticsProvider();
14-
compiler.activate(context.subscriptions);
15-
14+
context.subscriptions.push(registerDiagnosticsProvider());
15+
context.subscriptions.push(registerBuildOnSaveProvider());
1616
context.subscriptions.push(registerDocumentFormatting());
1717

1818
const testRunner = new ZigTestRunnerProvider();

src/zigBuildOnSaveProvider.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import vscode from "vscode";
2+
3+
import { handleConfigOption } from "./zigUtil";
4+
5+
export function registerBuildOnSaveProvider(): vscode.Disposable {
6+
return new BuildOnSaveProvider();
7+
}
8+
9+
type BuildOnSaveProviderKind = "off" | "auto" | "extension" | "zls";
10+
11+
class BuildOnSaveProvider implements vscode.Disposable {
12+
disposables: vscode.Disposable[] = [];
13+
/** This may be replacable with `vscode.tasks.taskExecutions` */
14+
tasks = new Map<string, vscode.TaskExecution | null>();
15+
16+
constructor() {
17+
for (const folder of vscode.workspace.workspaceFolders ?? []) {
18+
void this.addOrRestart(folder);
19+
}
20+
21+
vscode.workspace.onDidChangeWorkspaceFolders(async (e) => {
22+
for (const folder of e.added) {
23+
await this.addOrRestart(folder);
24+
}
25+
for (const folder of e.removed) {
26+
this.stop(folder);
27+
}
28+
}, this.disposables);
29+
30+
vscode.workspace.onDidChangeConfiguration(async (e) => {
31+
if (!e.affectsConfiguration("zig.buildOnSaveProvider")) return;
32+
33+
for (const folder of vscode.workspace.workspaceFolders ?? []) {
34+
await this.addOrRestart(folder);
35+
}
36+
}, this.disposables);
37+
}
38+
39+
dispose() {
40+
for (const disposable of this.disposables) {
41+
disposable.dispose();
42+
}
43+
}
44+
45+
async addOrRestart(folder: vscode.WorkspaceFolder): Promise<void> {
46+
this.stop(folder);
47+
48+
const zigConfig = vscode.workspace.getConfiguration("zig", folder);
49+
const buildOnSaveProvider = zigConfig.get<BuildOnSaveProviderKind>("buildOnSaveProvider", "auto");
50+
const buildOnSaveArgs = zigConfig
51+
.get<string[]>("buildOnSaveArgs", [])
52+
.map((unresolved) => handleConfigOption(unresolved, folder));
53+
54+
if (buildOnSaveProvider !== "extension") return;
55+
56+
if (buildOnSaveArgs.includes("--build-file")) {
57+
// The build file has been explicitly provided through a command line argument
58+
} else {
59+
const workspaceBuildZigUri = vscode.Uri.joinPath(folder.uri, "build.zig");
60+
try {
61+
await vscode.workspace.fs.stat(workspaceBuildZigUri);
62+
} catch {
63+
return;
64+
}
65+
}
66+
67+
const task = new vscode.Task(
68+
{
69+
type: "zig",
70+
},
71+
folder,
72+
"Zig Watch",
73+
"zig",
74+
new vscode.ShellExecution("zig", ["build", "--watch", ...buildOnSaveArgs], {}),
75+
"zig",
76+
);
77+
task.isBackground = true;
78+
task.presentationOptions.reveal = vscode.TaskRevealKind.Never;
79+
task.presentationOptions.close = true;
80+
const taskExecutor = await vscode.tasks.executeTask(task);
81+
this.stop(folder); // Try to stop again just in case a task got started while we were suspended
82+
this.tasks.set(folder.uri.toString(), taskExecutor);
83+
84+
vscode.workspace.onDidChangeConfiguration(async (e) => {
85+
if (e.affectsConfiguration("zig.buildOnSaveProvider", folder)) {
86+
// We previously checked that the build on save provider is "extension" so now it has to be something different
87+
this.stop(folder);
88+
return;
89+
}
90+
if (e.affectsConfiguration("zig.buildOnSaveArgs", folder)) {
91+
await this.addOrRestart(folder);
92+
}
93+
}, this.disposables);
94+
}
95+
96+
stop(folder: vscode.WorkspaceFolder): void {
97+
const oldTask = this.tasks.get(folder.uri.toString());
98+
if (oldTask) oldTask.terminate();
99+
this.tasks.delete(folder.uri.toString());
100+
}
101+
}

0 commit comments

Comments
 (0)