backport: 14.3.0

This commit is contained in:
FalsePattern 2024-05-15 18:21:32 +02:00
parent ae660ccb1e
commit 2e949456b3
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
23 changed files with 342 additions and 123 deletions

View file

@ -17,6 +17,21 @@ Changelog structure reference:
## [Unreleased]
## [14.3.0]
### Added
- Project
- Extra compiler arguments field for zig test/run tasks
### Fixed
- Debugging
- The debugger no longer freezes the IDE while zig is compiling
- Project
- Exe args for zig run not visible in the GUI
## [14.2.0]
### Added

View file

@ -22,6 +22,11 @@ through the built-in plugin browser:
4. Click `OK`, and your IDE should now automatically detect the latest version
(both in the Installed tab and in the Marketplace tab), even if it's not yet verified on the official JetBrains marketplace yet.
(optional) If you want to access the latest development versions (`2024.1.*` ONLY), you can use this updater URL:
https://falsepattern.com/zigbrains/updatePlugins-dev.xml
These dev releases are based on the latest public commits on the `master` branch, so they're not backported to older IDE versions, only tagged releases are.
## Developer guide
### All platforms

View file

@ -9,7 +9,7 @@ fun environment(key: String) = providers.environmentVariable(key)
plugins {
id("java") // Java support
id("java-library")
id("org.jetbrains.intellij") version("1.17.2")
id("org.jetbrains.intellij") version("1.17.3")
id("org.jetbrains.changelog") version("2.2.0")
id("org.jetbrains.grammarkit") version("2022.3.2.2")
id("com.palantir.git-version") version("3.0.0")
@ -24,7 +24,7 @@ val rootPackage = "com.falsepattern.zigbrains"
val rootPackagePath = rootPackage.replace('.', '/')
// Keep these in sync with whatever the oldest IDE version we're targeting in gradle.properties needs
val javaLangVersion: JavaLanguageVersion? = JavaLanguageVersion.of(17)
val javaLangVersion: JavaLanguageVersion = JavaLanguageVersion.of(17)
val javaVersion = JavaVersion.VERSION_17
val baseIDE: String = properties("baseIDE").get()

View file

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View file

@ -18,6 +18,9 @@ package com.falsepattern.zigbrains.debugger;
import com.falsepattern.zigbrains.debugbridge.DebuggerDriverProvider;
import com.falsepattern.zigbrains.debugger.win.WinDebuggerDriverConfiguration;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
@ -25,6 +28,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.util.system.OS;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.jetbrains.annotations.Nullable;
@ -51,4 +55,23 @@ public class Utils {
return null;
}
}
public static void executeCommandLineWithErrorChecks(GeneralCommandLine cli) throws ExecutionException, ProcessException {
val outputOpt = CLIUtil.execute(cli, Integer.MAX_VALUE);
if (outputOpt.isEmpty()) {
throw new ExecutionException("Failed to execute \"" + cli.getCommandLineString() + "\"!");
}
val output = outputOpt.get();
if (output.getExitCode() != 0) {
throw new ProcessException(cli.getCommandLineString(), output.getStdout(), output.getStderr(), output.getExitCode());
}
}
@RequiredArgsConstructor
public static class ProcessException extends Exception {
public final String command;
public final String stdout;
public final String stderr;
public final int exitCode;
}
}

View file

@ -19,14 +19,121 @@ package com.falsepattern.zigbrains.debugger;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.openapi.util.Expirable;
import com.intellij.xdebugger.XDebugSession;
import com.jetbrains.cidr.execution.RunParameters;
import com.jetbrains.cidr.execution.debugger.CidrDebugProcess;
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
public class ZigLocalDebugProcess extends CidrLocalDebugProcess {
private final ReentrantLock lock = new ReentrantLock();
public enum SuppressionLevel {
PreStart,
PostStart,
Unsuppressed
}
private volatile SuppressionLevel suppressionLevel = SuppressionLevel.PreStart;
private final List<Runnable> preStart = new ArrayList<>();
private final List<Runnable> postStart = new ArrayList<>();
public ZigLocalDebugProcess(@NotNull RunParameters parameters, @NotNull XDebugSession session, @NotNull TextConsoleBuilder consoleBuilder)
throws ExecutionException {
super(parameters, session, consoleBuilder, (project) -> Filter.EMPTY_ARRAY, false);
}
public void doStart() {
start();
lock.lock();
try {
suppressionLevel = SuppressionLevel.PostStart;
} finally {
lock.unlock();
}
}
public void unSuppress(boolean runPreStart) {
lock.lock();
try {
suppressionLevel = SuppressionLevel.Unsuppressed;
if (runPreStart) {
for (val r: preStart)
r.run();
}
for (val r: postStart)
r.run();
preStart.clear();
postStart.clear();
} finally {
lock.unlock();
}
}
private <T> CompletableFuture<T> suppressedFuture(Supplier<CompletableFuture<T>> original) {
if (suppressionLevel == SuppressionLevel.Unsuppressed)
return original.get();
lock.lock();
try {
if (suppressionLevel == SuppressionLevel.Unsuppressed)
return original.get();
val bypass = new CompletableFuture<T>();
val task = (Runnable)() ->
original.get()
.thenAccept(bypass::complete)
.exceptionally((ex) -> {
bypass.completeExceptionally(ex);
return null;
});
switch (suppressionLevel) {
case PreStart -> preStart.add(task);
case PostStart -> postStart.add(task);
}
return bypass;
} finally {
lock.unlock();
}
}
@Override
public @NotNull CompletableFuture<Void> postCommand(@NotNull CidrDebugProcess.VoidDebuggerCommand command) {
return suppressedFuture(() -> super.postCommand(command));
}
@Override
public @NotNull CompletableFuture<Void> postCommand(
@Nullable Expirable expirable, @NotNull CidrDebugProcess.VoidDebuggerCommand command) {
return suppressedFuture(() -> super.postCommand(expirable, command));
}
@Override
public @NotNull CompletableFuture<Void> postCommand(
@NotNull CidrDebugProcess.VoidDebuggerCommand command, boolean useAlternativeDispatcher) {
return suppressedFuture(() -> super.postCommand(command, useAlternativeDispatcher));
}
@Override
public @NotNull <T> CompletableFuture<T> postCommand(@NotNull CidrDebugProcess.DebuggerCommand<T> command) {
return suppressedFuture(() -> super.postCommand(command));
}
@Override
public @NotNull <T> CompletableFuture<T> postCommand(
@Nullable Expirable expirable, @NotNull CidrDebugProcess.DebuggerCommand<T> command) {
return suppressedFuture(() -> super.postCommand(expirable, command));
}
@Override
public @NotNull <T> CompletableFuture<T> postCommand(
@NotNull CidrDebugProcess.DebuggerCommand<T> command, boolean useAlternativeDispatcher) {
return suppressedFuture(() -> super.postCommand(command, useAlternativeDispatcher));
}
}

View file

@ -17,7 +17,9 @@
package com.falsepattern.zigbrains.debugger.execution.binary;
import com.falsepattern.zigbrains.common.util.CollectionUtil;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ArgsConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.FilePathConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ZigConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
@ -32,8 +34,8 @@ import java.util.List;
@Getter
public class ZigExecConfigBinary extends ZigExecConfigBase<ZigExecConfigBinary> {
private ZigConfigEditor.FilePathConfigurable exePath = new ZigConfigEditor.FilePathConfigurable("exePath", "Executable program path (not the zig compiler)");
private ZigConfigEditor.ArgsConfigurable args = new ZigConfigEditor.ArgsConfigurable("args", "Command line arguments");
private FilePathConfigurable exePath = new FilePathConfigurable("exePath", "Executable program path (not the zig compiler)");
private ArgsConfigurable args = new ArgsConfigurable("args", "Command line arguments");
public ZigExecConfigBinary(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig-compiled native executable");
@ -59,7 +61,7 @@ public class ZigExecConfigBinary extends ZigExecConfigBase<ZigExecConfigBinary>
}
@Override
public @NotNull List<ZigConfigEditor.ZigConfigurable<?>> getConfigurables() {
public @NotNull List<ZigConfigurable<?>> getConfigurables() {
return CollectionUtil.concat(super.getConfigurables(), exePath, args);
}

View file

@ -0,0 +1,23 @@
/*
* Copyright 2023-2024 FalsePattern
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.falsepattern.zigbrains.debugger.runner.base;
import java.util.concurrent.CompletableFuture;
public interface PreLaunchAware {
void preLaunch() throws Exception;
}

View file

@ -16,8 +16,10 @@
package com.falsepattern.zigbrains.debugger.runner.base;
import com.falsepattern.zigbrains.common.util.Lazy;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.jetbrains.cidr.execution.Installer;
import lombok.RequiredArgsConstructor;

View file

@ -23,9 +23,12 @@ import com.jetbrains.cidr.ArchitectureType;
import com.jetbrains.cidr.execution.RunParameters;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public abstract class ZigDebugParametersBase<ProfileState extends ProfileStateBase<?>> extends RunParameters {

View file

@ -16,10 +16,12 @@
package com.falsepattern.zigbrains.debugger.runner.base;
import com.falsepattern.zigbrains.debugger.Utils;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.io.FileUtil;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.val;
@ -27,28 +29,29 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
public abstract class ZigDebugParametersEmitBinaryBase<ProfileState extends ProfileStateBase<?>> extends ZigDebugParametersBase<ProfileState> {
protected final File executableFile;
public ZigDebugParametersEmitBinaryBase(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileState profileState, String kind) throws ExecutionException {
public abstract class ZigDebugParametersEmitBinaryBase<ProfileState extends ProfileStateBase<?>> extends ZigDebugParametersBase<ProfileState> implements PreLaunchAware {
protected volatile File executableFile;
private final String kind;
public ZigDebugParametersEmitBinaryBase(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileState profileState, String kind) {
super(driverConfiguration, toolchain, profileState);
this.kind = kind;
}
private File compileExe()
throws ExecutionException, Utils.ProcessException {
final File executableFile;
val commandLine = profileState.getCommandLine(toolchain, true);
final Path tmpDir;
try {
tmpDir = Files.createTempDirectory("zigbrains_debug").toAbsolutePath();
tmpDir = FileUtil.createTempDirectory("zigbrains_debug", "", true).toPath();
} catch (IOException e) {
throw new ExecutionException("Failed to create temporary directory for " + kind + " binary", e);
}
val exe = tmpDir.resolve("executable").toFile();
commandLine.addParameters("-femit-bin=" + exe.getAbsolutePath());
val outputOpt = CLIUtil.execute(commandLine, Integer.MAX_VALUE);
if (outputOpt.isEmpty()) {
throw new ExecutionException("Failed to execute \"zig " + commandLine.getParametersList().getParametersString() + "\"!");
}
val output = outputOpt.get();
if (output.getExitCode() != 0) {
throw new ExecutionException("Zig compilation failed with exit code " + output.getExitCode() + "\nError output:\n" + output.getStdout() + "\n" + output.getStderr());
}
Utils.executeCommandLineWithErrorChecks(commandLine);
//Find our binary
try (val stream = Files.list(tmpDir)){
executableFile = stream.filter(file -> !file.getFileName().toString().endsWith(".o"))
@ -60,5 +63,12 @@ public abstract class ZigDebugParametersEmitBinaryBase<ProfileState extends Prof
} catch (Exception e) {
throw new ExecutionException("Failed to find compiled binary! " + e.getMessage(), e);
}
return executableFile;
}
@Override
public void preLaunch() throws Exception {
this.executableFile = compileExe();
}
}

View file

@ -16,13 +16,13 @@
package com.falsepattern.zigbrains.debugger.runner.base;
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.runconfig.ZigProgramRunnerBase;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.debugger.Utils;
import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.filters.Filter;
@ -40,16 +40,17 @@ import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.TrivialRunParameters;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?>> extends ZigProgramRunnerBase<ProfileState> {
public ZigDebugRunnerBase() {
@ -72,35 +73,12 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
Notifications.Bus.notify(new Notification("ZigBrains.Debugger.Error", "Couldn't find a working GDB or LLDB debugger! Please check your Toolchains! (Settings | Build, Execution, Deployment | Toolchains)", NotificationType.ERROR));
return null;
}
Either<ZigDebugParametersBase<ProfileState>, ExecutionException> runParameters;
try {
runParameters = ApplicationManager.getApplication().executeOnPooledThread(() -> getDebugParametersSafe(state, environment, debuggerDriver, toolchain)).get();
} catch (InterruptedException | java.util.concurrent.ExecutionException e) {
e.printStackTrace();
Notifications.Bus.notify(new Notification("ZigBrains.Debugger.Error", e.getMessage(), NotificationType.ERROR));
return null;
}
ZigDebugParametersBase<ProfileState> runParameters = getDebugParameters(state, environment, debuggerDriver, toolchain);
if (runParameters == null) {
//Assume that getDebugParameters reports the bug in a notification already
return null;
}
if (runParameters.isRight()) {
return startSession(environment, new ErrorProcessStarter(state, runParameters.getRight(), debuggerDriver));
} else if (runParameters.isLeft()) {
return startSession(environment, new ZigLocalDebugProcessStarter(runParameters.getLeft(), state, environment));
} else {
return null;
}
}
private Either<ZigDebugParametersBase<ProfileState>, ExecutionException> getDebugParametersSafe(ProfileState state, ExecutionEnvironment environment, DebuggerDriverConfiguration debuggerDriver, AbstractZigToolchain toolchain) {
try {
return Either.forLeft(getDebugParameters(state, environment, debuggerDriver, toolchain));
} catch (ExecutionException e) {
return Either.forRight(e);
}
return startSession(environment, new ZigLocalDebugProcessStarter(runParameters, state, environment));
}
@Override
@ -113,30 +91,33 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
private final ZigDebugParametersBase<ProfileState> params;
private final ProfileState state;
private final ExecutionEnvironment environment;
private static class Carrier {
volatile ConsoleView console;
final Map<ConsoleViewContentType, List<String>> outputs = new HashMap<>();
@Override
public @NotNull XDebugProcess start(@NotNull XDebugSession session) throws ExecutionException {
val process = new ZigLocalDebugProcess(params, session, state.getConsoleBuilder());
ProcessTerminatedListener.attach(process.getProcessHandler(), environment.getProject());
process.start();
return process;
void handleOutput(String text, ConsoleViewContentType type) {
if (console != null) {
console.print(text, type);
} else {
outputs.computeIfAbsent(type, (ignored) -> new ArrayList<>()).add(text);
}
}
}
}
@RequiredArgsConstructor
private class ErrorProcessStarter extends XDebugProcessStarter {
private final ProfileState state;
private final ExecutionException exception;
private final DebuggerDriverConfiguration debuggerDriver;
@Override
public @NotNull XDebugProcess start(@NotNull XDebugSession session) throws ExecutionException {
val cb = state.getConsoleBuilder();
val carrier = new Carrier();
val wrappedBuilder = new TextConsoleBuilder() {
@Override
public @NotNull ConsoleView getConsole() {
val console = cb.getConsole();
console.print(exception.getMessage(), ConsoleViewContentType.ERROR_OUTPUT);
for (val output: carrier.outputs.entrySet()) {
for (val line: output.getValue()) {
console.print(line + "\n", output.getKey());
}
}
carrier.console = console;
return console;
}
@ -150,18 +131,35 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
cb.setViewer(isViewer);
}
};
val process = new ZigLocalDebugProcess(new TrivialRunParameters(debuggerDriver, new Installer() {
@Override
public @NotNull GeneralCommandLine install() throws ExecutionException {
throw new ExecutionException("Failed to start debugging");
}
val process = new ZigLocalDebugProcess(params, session, wrappedBuilder);
ApplicationManager.getApplication().executeOnPooledThread(() -> {
ProcessTerminatedListener.attach(process.getProcessHandler(), environment.getProject());
@Override
public @NotNull File getExecutableFile() {
return null;
if (params instanceof PreLaunchAware pla) {
try {
pla.preLaunch();
} catch (Exception e) {
ApplicationUtil.invokeLater(() -> {
if (e instanceof Utils.ProcessException pe) {
carrier.handleOutput(pe.command + "\n", ConsoleViewContentType.SYSTEM_OUTPUT);
carrier.handleOutput("Compilation failure!\n", ConsoleViewContentType.SYSTEM_OUTPUT);
carrier.handleOutput(pe.stdout, ConsoleViewContentType.NORMAL_OUTPUT);
carrier.handleOutput(pe.stderr, ConsoleViewContentType.ERROR_OUTPUT);
process.handleTargetTerminated(new DebuggerDriver.ExitStatus(pe.exitCode));
} else {
carrier.handleOutput("Exception while compiling binary:\n", ConsoleViewContentType.SYSTEM_OUTPUT);
carrier.handleOutput(e.getMessage(), ConsoleViewContentType.ERROR_OUTPUT);
process.handleTargetTerminated(new DebuggerDriver.ExitStatus(-1));
}
process.stop();
ApplicationManager.getApplication().executeOnPooledThread(() -> process.unSuppress(false));
});
return;
}
}
}), session, wrappedBuilder);
process.start();
process.unSuppress(true);
});
process.doStart();
return process;
}
}

View file

@ -16,6 +16,8 @@
package com.falsepattern.zigbrains.debugger.runner.build;
import com.falsepattern.zigbrains.debugger.Utils;
import com.falsepattern.zigbrains.debugger.runner.base.PreLaunchAware;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
import com.falsepattern.zigbrains.project.execution.build.ProfileStateBuild;
@ -23,6 +25,7 @@ import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.application.ApplicationManager;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.Cleanup;
@ -35,22 +38,21 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
public class ZigDebugParametersBuild extends ZigDebugParametersBase<ProfileStateBuild> {
public class ZigDebugParametersBuild extends ZigDebugParametersBase<ProfileStateBuild> implements PreLaunchAware {
private static final String BoilerplateNotice = "\nPlease edit this intellij build configuration and specify the path of the executable created by \"zig build\" directly!";
private final File executableFile;
public ZigDebugParametersBuild(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateBuild profileStateBuild) throws ExecutionException {
super(driverConfiguration, toolchain, profileStateBuild);
val commandLine = profileState.getCommandLine(toolchain, true);
val outputOpt = CLIUtil.execute(commandLine, Integer.MAX_VALUE);
if (outputOpt.isEmpty()) {
throw new ExecutionException("Failed to execute \"zig " + commandLine.getParametersList().getParametersString() + "\"!");
}
val output = outputOpt.get();
if (output.getExitCode() != 0) {
throw new ExecutionException("Zig compilation failed with exit code " + output.getExitCode() + "\nError output:\n" + output.getStdout() + "\n" + output.getStderr());
}
private volatile File executableFile;
public ZigDebugParametersBuild(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateBuild profileStateBuild) {
super(driverConfiguration, toolchain, profileStateBuild);
}
private File compileExe() throws ExecutionException, Utils.ProcessException {
val commandLine = profileState.getCommandLine(toolchain, true);
Utils.executeCommandLineWithErrorChecks(commandLine);
val cfg = profileState.configuration();
val workingDir = cfg.getWorkingDirectory().getPath().orElse(null);
val exePath = profileState.configuration().getExePath().getPath();
@ -84,11 +86,17 @@ public class ZigDebugParametersBuild extends ZigDebugParametersBase<ProfileState
throw new ExecutionException("File " + exe + " is not executable!");
}
executableFile = exe.toFile();
return exe.toFile();
}
@Override
public void preLaunch() throws Exception {
this.executableFile = compileExe();
}
@Override
public @NotNull Installer getInstaller() {
assert executableFile != null;
return new ZigDebugEmitBinaryInstaller<>(profileState, toolchain, executableFile, profileState.configuration().getExeArgs().args);
}
}

View file

@ -17,23 +17,21 @@
package com.falsepattern.zigbrains.debugger.runner.run;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersEmitBinaryBase;
import com.falsepattern.zigbrains.project.execution.run.ProfileStateRun;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.intellij.execution.ExecutionException;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import org.jetbrains.annotations.NotNull;
public class ZigDebugParametersRun extends ZigDebugParametersEmitBinaryBase<ProfileStateRun> {
public ZigDebugParametersRun(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateRun profileState)
throws ExecutionException {
public ZigDebugParametersRun(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateRun profileState) {
super(driverConfiguration, toolchain, profileState, "run");
}
@Override
public @NotNull Installer getInstaller() {
assert executableFile != null;
return new ZigDebugEmitBinaryInstaller<>(profileState, toolchain, executableFile, profileState.configuration().getExeArgs().args);
}
}

View file

@ -20,20 +20,18 @@ import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersEmitBin
import com.falsepattern.zigbrains.project.execution.test.ProfileStateTest;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
import com.intellij.execution.ExecutionException;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import org.jetbrains.annotations.NotNull;
public class ZigDebugParametersTest extends ZigDebugParametersEmitBinaryBase<ProfileStateTest> {
public ZigDebugParametersTest(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateTest profileState)
throws ExecutionException {
public ZigDebugParametersTest(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateTest profileState) {
super(driverConfiguration, toolchain, profileState, "test");
}
@Override
public @NotNull Installer getInstaller() {
assert executableFile != null;
return new ZigDebugEmitBinaryInstaller<>(profileState, toolchain, executableFile, new String[0]);
}
}

View file

@ -96,7 +96,8 @@ public class WinDAPDriver extends DAPDriver<
return capabilitiesCompletableFuture.thenCombine(handshakeFuture, (res, hs) -> res);
}
@SuppressWarnings("unused")
//Weird nested generics interaction, not suppressing unchecked causes a linter error, I have no idea how to fix this
@SuppressWarnings({"unchecked", "RedundantSuppression"})
protected class WinDAPDebuggerClient extends DAPDebuggerClient {
@Override
public void output(OutputEventArguments args) {

View file

@ -218,6 +218,7 @@ public class LSPAnnotator extends ExternalAnnotator<Object, Object> {
annotation = annotation.highlightType(ProblemHighlightType.LIKE_DEPRECATED);
}
annotation.create();
@SuppressWarnings("unchecked")
var theList = (SmartList<Annotation>) holder;
annotations.add(theList.get(theList.size() - 1));
});

View file

@ -572,7 +572,7 @@ public class EditorEventManager {
try {
request.thenAccept(formatting -> {
if (formatting != null) {
invokeLater(() -> applyEdit(toEither((List<TextEdit>) formatting), "Reformat document", false));
invokeLater(() -> applyEdit(toEither(formatting), "Reformat document", false));
}
});
} catch (IndexOutOfBoundsException e) {
@ -614,7 +614,7 @@ public class EditorEventManager {
}
invokeLater(() -> {
if (!editor.isDisposed()) {
applyEdit(toEither((List<TextEdit>) formatting), "Reformat selection", false);
applyEdit(toEither(formatting), "Reformat selection", false);
}
});
});
@ -1347,13 +1347,15 @@ public class EditorEventManager {
.withFix(new LSPCodeActionFix(FileUtils.editorToURIString(editor), codeAction))
.create();
SmartList<Annotation> asList = (SmartList<Annotation>) this.anonHolder;
@SuppressWarnings("unchecked")
SmartList<? extends Annotation> asList = (SmartList<Annotation>) this.anonHolder;
this.annotations.add(asList.get(asList.size() - 1));
diagnosticSyncRequired = true;
} catch (IllegalArgumentException ignored) {
} catch (IllegalArgumentException e) {
//TODO Suppressed error, fix this somehow
e.printStackTrace();
}
}
}

View file

@ -163,7 +163,7 @@ public class DocumentUtils {
return computableReadAction(() -> !editor.getSettings().isUseTabCharacter(editor.getProject()));
}
public static List<Either<TextEdit, InsertReplaceEdit>> toEither(List<TextEdit> edits) {
public static List<Either<TextEdit, InsertReplaceEdit>> toEither(List<? extends TextEdit> edits) {
return edits.stream().map(Either::<TextEdit, InsertReplaceEdit>forLeft).collect(Collectors.toList());
}
}

View file

@ -18,7 +18,9 @@ package com.falsepattern.zigbrains.project.execution.build;
import com.falsepattern.zigbrains.common.ZBFeatures;
import com.falsepattern.zigbrains.common.util.CollectionUtil;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ArgsConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.CheckboxConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.FilePathConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.ExecutionException;
@ -34,13 +36,15 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.*;
@Getter
public class ZigExecConfigBuild extends ZigExecConfigBase<ZigExecConfigBuild> {
private ZigConfigEditor.ArgsConfigurable buildSteps = new ZigConfigEditor.ArgsConfigurable("buildSteps", "Build steps");
private ZigConfigEditor.ArgsConfigurable extraArgs = new ZigConfigEditor.ArgsConfigurable("extraArgs", "Extra command line arguments");
private ZigConfigEditor.CheckboxConfigurable colored = ZigConfigEditor.coloredConfigurable("colored");
private ZigConfigEditor.FilePathConfigurable exePath = new ZigConfigEditor.FilePathConfigurable("exePath", "Output executable created by the build (debugging, autodetect if empty)");
private ZigConfigEditor.ArgsConfigurable exeArgs = new ZigConfigEditor.ArgsConfigurable("exeArgs", "Command line arguments for executable (debugging)");
private ArgsConfigurable buildSteps = new ArgsConfigurable("buildSteps", "Build steps");
private ArgsConfigurable extraArgs = new ArgsConfigurable("extraArgs", "Extra command line arguments");
private CheckboxConfigurable colored = coloredConfigurable("colored");
private FilePathConfigurable exePath = new FilePathConfigurable("exePath", "Output executable created by the build (debugging, autodetect if empty)");
private ArgsConfigurable exeArgs = new ArgsConfigurable("exeArgs", "Command line arguments for executable (debugging)");
public ZigExecConfigBuild(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Build");
}
@ -75,7 +79,7 @@ public class ZigExecConfigBuild extends ZigExecConfigBase<ZigExecConfigBuild> {
}
@Override
public @NotNull List<ZigConfigEditor.ZigConfigurable<?>> getConfigurables() {
public @NotNull List<ZigConfigurable<?>> getConfigurables() {
val baseCfg = CollectionUtil.concat(super.getConfigurables(), buildSteps, extraArgs, colored);
if (ZBFeatures.debug()) {
return CollectionUtil.concat(baseCfg, exePath, exeArgs);

View file

@ -17,7 +17,11 @@
package com.falsepattern.zigbrains.project.execution.run;
import com.falsepattern.zigbrains.common.util.CollectionUtil;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ArgsConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.CheckboxConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.FilePathConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.OptimizationConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ZigConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.Executor;
@ -32,12 +36,15 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.coloredConfigurable;
@Getter
public class ZigExecConfigRun extends ZigExecConfigBase<ZigExecConfigRun> {
private ZigConfigEditor.FilePathConfigurable filePath = new ZigConfigEditor.FilePathConfigurable("filePath", "File Path");
private ZigConfigEditor.CheckboxConfigurable colored = ZigConfigEditor.coloredConfigurable("colored");
private ZigConfigEditor.OptimizationConfigurable optimization = new ZigConfigEditor.OptimizationConfigurable("optimization");
private ZigConfigEditor.ArgsConfigurable exeArgs = new ZigConfigEditor.ArgsConfigurable("exeArgs", "Arguments for the compile exe");
private FilePathConfigurable filePath = new FilePathConfigurable("filePath", "File Path");
private CheckboxConfigurable colored = coloredConfigurable("colored");
private OptimizationConfigurable optimization = new OptimizationConfigurable("optimization");
private ArgsConfigurable compilerArgs = new ArgsConfigurable("compilerArgs", "Extra compiler command line arguments");
private ArgsConfigurable exeArgs = new ArgsConfigurable("exeArgs", "Output program command line arguments");
public ZigExecConfigRun(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Run");
}
@ -51,6 +58,7 @@ public class ZigExecConfigRun extends ZigExecConfigBase<ZigExecConfigRun> {
if (!debug || optimization.forced) {
result.addAll(List.of("-O", optimization.level.name()));
}
result.addAll(List.of(compilerArgs.args));
if (!debug) {
result.add("--");
result.addAll(List.of(exeArgs.args));
@ -68,14 +76,15 @@ public class ZigExecConfigRun extends ZigExecConfigBase<ZigExecConfigRun> {
val clone = super.clone();
clone.filePath = filePath.clone();
clone.colored = colored.clone();
clone.compilerArgs = compilerArgs.clone();
clone.optimization = optimization.clone();
clone.exeArgs = exeArgs.clone();
return clone;
}
@Override
public @NotNull List<ZigConfigEditor.ZigConfigurable<?>> getConfigurables() {
return CollectionUtil.concat(super.getConfigurables(), filePath, optimization, colored);
public @NotNull List<ZigConfigurable<?>> getConfigurables() {
return CollectionUtil.concat(super.getConfigurables(), filePath, optimization, colored, compilerArgs, exeArgs);
}
@Override

View file

@ -18,7 +18,11 @@ package com.falsepattern.zigbrains.project.execution.test;
import com.falsepattern.zigbrains.common.util.CollectionUtil;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ArgsConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.CheckboxConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.FilePathConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.OptimizationConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ZigConfigurable;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.Executor;
@ -33,11 +37,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.coloredConfigurable;
@Getter
public class ZigExecConfigTest extends ZigExecConfigBase<ZigExecConfigTest> {
private ZigConfigEditor.FilePathConfigurable filePath = new ZigConfigEditor.FilePathConfigurable("filePath", "File path");
private ZigConfigEditor.CheckboxConfigurable colored = ZigConfigEditor.coloredConfigurable("colored");
private ZigConfigEditor.OptimizationConfigurable optimization = new ZigConfigEditor.OptimizationConfigurable("optimization");
private FilePathConfigurable filePath = new FilePathConfigurable("filePath", "File path");
private CheckboxConfigurable colored = coloredConfigurable("colored");
private OptimizationConfigurable optimization = new OptimizationConfigurable("optimization");
private ArgsConfigurable compilerArgs = new ArgsConfigurable("compilerArgs", "Extra compiler command line arguments");
public ZigExecConfigTest(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Test");
}
@ -51,6 +58,7 @@ public class ZigExecConfigTest extends ZigExecConfigBase<ZigExecConfigTest> {
if (!debug || optimization.forced) {
result.addAll(List.of("-O", optimization.level.name()));
}
result.addAll(List.of(compilerArgs.args));
if (debug) {
result.add("--test-no-exec");
}
@ -73,11 +81,12 @@ public class ZigExecConfigTest extends ZigExecConfigBase<ZigExecConfigTest> {
clone.filePath = filePath.clone();
clone.colored = colored.clone();
clone.optimization = optimization.clone();
clone.compilerArgs = compilerArgs.clone();
return clone;
}
@Override
public @NotNull List<ZigConfigEditor.ZigConfigurable<?>> getConfigurables() {
return CollectionUtil.concat(super.getConfigurables(), filePath, optimization, colored);
public @NotNull List<ZigConfigurable<?>> getConfigurables() {
return CollectionUtil.concat(super.getConfigurables(), filePath, optimization, colored, compilerArgs);
}
}

View file

@ -30,6 +30,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.ProjectActivity;
import com.intellij.openapi.util.io.FileUtil;
import kotlin.Unit;
import kotlin.coroutines.Continuation;
import lombok.val;
@ -75,7 +76,7 @@ public class ZLSStartupActivity implements ProjectActivity {
if (configPath == null || configPath.isBlank()) {
blk:
try {
val tmpFile = Files.createTempFile("zigbrains-zls-autoconf", ".json");
val tmpFile = FileUtil.createTempFile("zigbrains-zls-autoconf", ".json", true).toPath();
val config = ZLSConfigProvider.findEnvironment(project);
if (StringUtil.isEmpty(config.zig_exe_path()) && StringUtil.isEmpty(config.zig_lib_path())) {
// TODO this generates unnecessary noise in non-zig projects, find an alternative.