Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 42 additions & 47 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,42 +70,23 @@
"column": 3,
"severity": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^Build Summary:",
"endsPattern": "^error: (\\d+ compilation errors|the following command failed with )"
}
}
],
"taskDefinitions": [
{
"type": "zig"
}
],
"configuration": {
"type": "object",
"title": "Zig",
"properties": {
"zig.buildOnSave": {
"type": "boolean",
"default": false,
"description": "Compiles code on file save using the settings specified in 'Build Option'. Should not be used with ZLS's build on save feature."
},
"zig.buildOption": {
"type": "string",
"default": "build",
"enum": [
"build",
"build-exe",
"build-lib",
"build-obj"
],
"description": "Which build command Zig should use to build the code."
},
"zig.buildArgs": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Extra arguments to passed to Zig."
},
"zig.buildFilePath": {
"type": "string",
"default": "${workspaceFolder}/build.zig",
"description": "The path to build.zig. This is only required if zig.buildOptions = build."
},
"zig.path": {
"scope": "machine-overridable",
"type": "string",
Expand Down Expand Up @@ -171,6 +152,38 @@
"default": "lldb",
"description": "The debug adapter command to run when starting a debug session"
},
"zig.buildOnSaveProvider": {
"scope": "resource",
"type": "string",
"description": "Specify how build on save diagnostics should be provided.",
"enum": [
"off",
"auto",
"extension",
"zls"
],
"enumItemLabels": [
"Disabled",
"Automatic",
"Extension",
"ZLS language server"
],
"enumDescriptions": [
"Disable build on save",
"Disabled unless ZLS has enabled [build on save](https://zigtools.org/zls/guides/build-on-save/) automatically.",
"Provide build on save by running `zig build --watch`",
"Provide build on save using ZLS"
],
"default": "auto"
},
"zig.buildOnSaveArgs": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"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."
},
"zig.zls.debugLog": {
"scope": "resource",
"type": "boolean",
Expand Down Expand Up @@ -222,18 +235,6 @@
"description": "Whether to show the function signature in completion results. May improve readability in some editors when disabled",
"default": true
},
"zig.zls.enableBuildOnSave": {
"scope": "resource",
"type": "boolean",
"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.",
"default": null
},
"zig.zls.buildOnSaveArgs": {
"scope": "resource",
"type": "array",
"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.",
"default": []
},
"zig.zls.semanticTokens": {
"scope": "resource",
"type": "string",
Expand Down Expand Up @@ -360,12 +361,6 @@
"category": "Zig",
"description": "Debug the current Zig project / file"
},
{
"command": "zig.build.workspace",
"title": "Build Workspace",
"category": "Zig",
"description": "Build the current project using 'zig build'"
},
{
"command": "zig.install",
"title": "Install Zig",
Expand Down
8 changes: 4 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import vscode from "vscode";

import { activate as activateZls, deactivate as deactivateZls } from "./zls";
import ZigDiagnosticsProvider from "./zigDiagnosticsProvider";
import ZigMainCodeLensProvider from "./zigMainCodeLens";
import ZigTestRunnerProvider from "./zigTestRunnerProvider";
import { registerBuildOnSaveProvider } from "./zigBuildOnSaveProvider";
import { registerDiagnosticsProvider } from "./zigDiagnosticsProvider";
import { registerDocumentFormatting } from "./zigFormat";
import { registerTerminalStateManagement } from "./terminalState";
import { setupZig } from "./zigSetup";

export async function activate(context: vscode.ExtensionContext) {
await setupZig(context).finally(() => {
const compiler = new ZigDiagnosticsProvider();
compiler.activate(context.subscriptions);

context.subscriptions.push(registerDiagnosticsProvider());
context.subscriptions.push(registerBuildOnSaveProvider());
context.subscriptions.push(registerDocumentFormatting());

const testRunner = new ZigTestRunnerProvider();
Expand Down
101 changes: 101 additions & 0 deletions src/zigBuildOnSaveProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import vscode from "vscode";

import { handleConfigOption } from "./zigUtil";

export function registerBuildOnSaveProvider(): vscode.Disposable {
return new BuildOnSaveProvider();
}

type BuildOnSaveProviderKind = "off" | "auto" | "extension" | "zls";

class BuildOnSaveProvider implements vscode.Disposable {
disposables: vscode.Disposable[] = [];
/** This may be replacable with `vscode.tasks.taskExecutions` */
tasks = new Map<string, vscode.TaskExecution | null>();

constructor() {
for (const folder of vscode.workspace.workspaceFolders ?? []) {
void this.addOrRestart(folder);
}

vscode.workspace.onDidChangeWorkspaceFolders(async (e) => {
for (const folder of e.added) {
await this.addOrRestart(folder);
}
for (const folder of e.removed) {
this.stop(folder);
}
}, this.disposables);

vscode.workspace.onDidChangeConfiguration(async (e) => {
if (!e.affectsConfiguration("zig.buildOnSaveProvider")) return;

for (const folder of vscode.workspace.workspaceFolders ?? []) {
await this.addOrRestart(folder);
}
}, this.disposables);
}

dispose() {
for (const disposable of this.disposables) {
disposable.dispose();
}
}

async addOrRestart(folder: vscode.WorkspaceFolder): Promise<void> {
this.stop(folder);

const zigConfig = vscode.workspace.getConfiguration("zig", folder);
const buildOnSaveProvider = zigConfig.get<BuildOnSaveProviderKind>("buildOnSaveProvider", "auto");
const buildOnSaveArgs = zigConfig
.get<string[]>("buildOnSaveArgs", [])
.map((unresolved) => handleConfigOption(unresolved, folder));

if (buildOnSaveProvider !== "extension") return;

if (buildOnSaveArgs.includes("--build-file")) {
// The build file has been explicitly provided through a command line argument
} else {
const workspaceBuildZigUri = vscode.Uri.joinPath(folder.uri, "build.zig");
try {
await vscode.workspace.fs.stat(workspaceBuildZigUri);
} catch {
return;
}
}

const task = new vscode.Task(
{
type: "zig",
},
folder,
"Zig Watch",
"zig",
new vscode.ShellExecution("zig", ["build", "--watch", ...buildOnSaveArgs], {}),
"zig",
);
task.isBackground = true;
task.presentationOptions.reveal = vscode.TaskRevealKind.Never;
task.presentationOptions.close = true;
const taskExecutor = await vscode.tasks.executeTask(task);
this.stop(folder); // Try to stop again just in case a task got started while we were suspended
this.tasks.set(folder.uri.toString(), taskExecutor);

vscode.workspace.onDidChangeConfiguration(async (e) => {
if (e.affectsConfiguration("zig.buildOnSaveProvider", folder)) {
// We previously checked that the build on save provider is "extension" so now it has to be something different
this.stop(folder);
return;
}
if (e.affectsConfiguration("zig.buildOnSaveArgs", folder)) {
await this.addOrRestart(folder);
}
}, this.disposables);
}

stop(folder: vscode.WorkspaceFolder): void {
const oldTask = this.tasks.get(folder.uri.toString());
if (oldTask) oldTask.terminate();
this.tasks.delete(folder.uri.toString());
}
}
Loading