feat: Proper debugger support and some minor cleanup

This commit is contained in:
FalsePattern 2023-08-20 18:19:51 +02:00
parent 5429a7034d
commit d6afb01d08
Signed by: falsepattern
GPG key ID: FDF7126A9E124447
19 changed files with 593 additions and 55 deletions

View file

@ -18,6 +18,16 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
### Added
- Toolchain
- Debugging Support
### Fixed
- Toolchain
- Zig run configurations now save properly
## [0.7.0] ## [0.7.0]
### Added ### Added

View file

@ -25,7 +25,13 @@ and the Eclipse LSP4J project
# Description # Description
<!-- Plugin description --> <!-- Plugin description -->
An LSP-powered language plugin for the Zig Programming Language. A multifunctional Zig Programming Language plugin for the IDEA platform.
Core features:
- Uses ZLS (Zig Language Server) for code assistance, syntax highlighting, and anything to do with smart coding
- Supports build.zig.zon files with autocomplete
- Per-project Zig toolchain integration
- Debugging support for CLion (builtin), and IDEA Ultimate [With this plugin](https://plugins.jetbrains.com/plugin/12775-native-debugging-support)
## Setting up the language server ## Setting up the language server
@ -47,19 +53,9 @@ LSP server is starting, please be patient.
Green (empty): Green (empty):
LSP server is running. LSP server is running.
## Setting Zig for debugging (CLion) ## Debugging
ZigBrains doesn't have a custom debug executor for zig (yet), so you will need to manually add it as an external tool: Currently, the debugger only works with the bundled LLDB debugger, so make sure you have that.
1. Go to `Run` -> `Edit Configuration` -> `Add new` -> `Custom Build Application`, name it "Zig Build"
2. Create an empty build target for the Target field
3. Set the Executable to your zig compiler executable
4. Set the program arguments to `run <your main.zig file>`
5. Set the working directory to `$ProjectFileDir$`
6. Remove the build stage from the Before launch task list
To see if this works, create a few breakpoints in your main.zig file, and then run this new run configuration as debug,
and it should stop at the breakpoints.
## Feature tracker: ## Feature tracker:
@ -89,7 +85,8 @@ and it should stop at the breakpoints.
### Toolchain: ### Toolchain:
- Basic per-project toolchain management - Basic per-project toolchain management
- Run configurations (not debuggable, see above) - Run configurations
- Debugging (CLion/IDEA Ultimate)
## The motivation ## The motivation
The other existing Zig language plugins for IntelliJ rely a lot on the PSI tree. The other existing Zig language plugins for IntelliJ rely a lot on the PSI tree.

View file

@ -154,6 +154,7 @@ project(":") {
project(":debugger") { project(":debugger") {
dependencies { dependencies {
implementation(project(":zig")) implementation(project(":zig"))
implementation(project(":project"))
} }
intellij { intellij {
version = clionVersion version = clionVersion

View file

@ -0,0 +1,50 @@
/*
* Copyright 2023 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.zig.debugger;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.RunParameters;
import com.jetbrains.cidr.execution.TrivialInstaller;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@RequiredArgsConstructor
public class ZigDebugRunParameters extends RunParameters {
private final GeneralCommandLine cmd;
@Override
public @NotNull Installer getInstaller() {
return new TrivialInstaller(cmd);
}
@Override
public @NotNull DebuggerDriverConfiguration getDebuggerDriverConfiguration() {
if (LLDBDriverConfiguration.hasBundledLLDB()) {
return new LLDBDriverConfiguration();
} else {
throw new IllegalStateException("The bundled LLDB debugger is missing from your IDE!");
}
}
@Override
public @Nullable String getArchitectureId() {
return null;
}
}

View file

@ -0,0 +1,32 @@
/*
* Copyright 2023 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.zig.debugger;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration;
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
import com.intellij.execution.configurations.RunProfile;
import org.jetbrains.annotations.NotNull;
public class ZigDebugRunner extends ZigDebugRunnerBase {
@Override
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
return super.canRun(executorId, profile) &&
(profile instanceof ZigRunExecutionConfiguration $prof) &&
(ZigProjectSettingsService.getInstance($prof.getProject()).getToolchain() instanceof LocalZigToolchain);
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright 2023 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.zig.debugger;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationRunProfileState;
import com.falsepattern.zigbrains.project.runconfig.ZigExecutableRunner;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessTerminatedListener;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import lombok.val;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ZigDebugRunnerBase extends ZigExecutableRunner {
public ZigDebugRunnerBase() {
super(DefaultDebugExecutor.EXECUTOR_ID, "Unable to run Zig debugger");
}
@Override
protected RunContentDescriptor showRunContent(ZigRunExecutionConfigurationRunProfileState state, ExecutionEnvironment environment, GeneralCommandLine runExecutable)
throws ExecutionException {
val runParameters = new ZigDebugRunParameters(runExecutable);
return XDebuggerManager.getInstance(environment.getProject())
.startSession(environment, new XDebugProcessStarter() {
@Override
public @NotNull XDebugProcess start(@NotNull XDebugSession session) throws ExecutionException {
val process = new ZigLocalDebugProcess(runParameters, session, state.getConsoleBuilder());
ProcessTerminatedListener.attach(process.getProcessHandler(), environment.getProject());
process.start();
return process;
}
}).getRunContentDescriptor();
}
@Override
public @NotNull @NonNls String getRunnerId() {
return "ZigDebugRunner";
}
}

View file

@ -0,0 +1,27 @@
/*
* Copyright 2023 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.zig.debugger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.xdebugger.XSourcePosition;
import com.jetbrains.cidr.execution.debugger.CidrDebuggerEditorsExtensionBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigDebuggerEditorsExtension extends CidrDebuggerEditorsExtensionBase {
}

View file

@ -0,0 +1,30 @@
/*
* Copyright 2023 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.zig.debugger;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ZigDebuggerLanguage implements DebuggerDriver.DebuggerLanguage {
public static final ZigDebuggerLanguage INSTANCE = new ZigDebuggerLanguage();
@Override
public String toString() {
return "Zig";
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright 2023 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.zig.debugger;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.jetbrains.cidr.execution.debugger.CidrDebuggerLanguageSupport;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class ZigDebuggerLanguageSupport extends CidrDebuggerLanguageSupport {
@Override
public @NotNull Set<DebuggerDriver.DebuggerLanguage> getSupportedDebuggerLanguages() {
return Set.of(ZigDebuggerLanguage.INSTANCE);
}
@Override
public @Nullable XDebuggerEditorsProvider createEditor(@Nullable RunProfile profile) {
if (!(profile instanceof ZigRunExecutionConfiguration)) {
return null;
}
return createEditorProvider();
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2023 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.zig.debugger;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilder;
import com.intellij.xdebugger.XDebugSession;
import com.jetbrains.cidr.execution.RunParameters;
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess;
import org.jetbrains.annotations.NotNull;
public class ZigLocalDebugProcess extends CidrLocalDebugProcess {
public ZigLocalDebugProcess(@NotNull RunParameters parameters, @NotNull XDebugSession session, @NotNull TextConsoleBuilder consoleBuilder)
throws ExecutionException {
super(parameters, session, consoleBuilder, (project) -> Filter.EMPTY_ARRAY, false);
}
@Override
public boolean isLibraryFrameFilterSupported() {
return false;
}
}

View file

@ -1,7 +1,14 @@
<idea-plugin package="com.falsepattern.zigbrains.zig.debugger"> <idea-plugin package="com.falsepattern.zigbrains.zig.debugger">
<depends>com.intellij.modules.cidr.debugger</depends> <depends>com.intellij.modules.cidr.debugger</depends>
<extensions defaultExtensionNs="com.intellij">
<programRunner implementation="com.falsepattern.zigbrains.zig.debugger.ZigDebugRunner"
id="ZigDebugRunner"/>
</extensions>
<extensions defaultExtensionNs="cidr.debugger"> <extensions defaultExtensionNs="cidr.debugger">
<languageSupport language="Zig" implementationClass="com.falsepattern.zigbrains.zig.debugger.ZigDebuggerLanguageSupport"/>
<editorsExtension language="Zig" implementationClass="com.falsepattern.zigbrains.zig.debugger.ZigDebuggerEditorsExtension"/>
<lineBreakpointFileTypesProvider implementation="com.falsepattern.zigbrains.zig.debugger.ZigLineBreakpointFileTypesProvider"/> <lineBreakpointFileTypesProvider implementation="com.falsepattern.zigbrains.zig.debugger.ZigLineBreakpointFileTypesProvider"/>
</extensions> </extensions>
</idea-plugin> </idea-plugin>

View file

@ -23,9 +23,11 @@ import com.intellij.execution.configurations.LocatableConfigurationBase;
import com.intellij.execution.configurations.RunProfileState; import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.NlsActions; import com.intellij.openapi.util.NlsActions;
import com.intellij.openapi.util.text.Strings; import com.intellij.openapi.util.text.Strings;
import lombok.val; import lombok.val;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -52,8 +54,6 @@ public abstract class AbstractZigExecutionConfiguration extends LocatableConfigu
} }
@Override @Override
public @Nullable RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) public abstract @Nullable RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment)
throws ExecutionException { throws ExecutionException;
return null;
}
} }

View file

@ -17,6 +17,7 @@
package com.falsepattern.zigbrains.project.execution.configurations; package com.falsepattern.zigbrains.project.execution.configurations;
import com.falsepattern.zigbrains.project.execution.configurations.ui.ZigRunExecutionConfigurationEditor; import com.falsepattern.zigbrains.project.execution.configurations.ui.ZigRunExecutionConfigurationEditor;
import com.falsepattern.zigbrains.project.util.ElementUtil;
import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor; import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory; import com.intellij.execution.configurations.ConfigurationFactory;
@ -25,8 +26,10 @@ import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -49,4 +52,23 @@ public class ZigRunExecutionConfiguration extends AbstractZigExecutionConfigurat
throws ExecutionException { throws ExecutionException {
return new ZigRunExecutionConfigurationRunProfileState(environment, this); return new ZigRunExecutionConfigurationRunProfileState(environment, this);
} }
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
super.readExternal(element);
var command = ElementUtil.readString(element, "command");
if (command != null) {
this.command = command;
}
}
@Override
public void writeExternal(@NotNull Element element) {
super.writeExternal(element);
ElementUtil.writeString(element, "command", command);
}
} }

View file

@ -17,46 +17,61 @@
package com.falsepattern.zigbrains.project.execution.configurations; package com.falsepattern.zigbrains.project.execution.configurations;
import com.falsepattern.zigbrains.project.execution.ZigCapturingProcessHandler; import com.falsepattern.zigbrains.project.execution.ZigCapturingProcessHandler;
import com.falsepattern.zigbrains.project.runconfig.ZigProcessHandler;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.util.ProjectUtil; import com.falsepattern.zigbrains.project.util.ProjectUtil;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.CommandLineState; import com.intellij.execution.configurations.CommandLineState;
import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.process.ProcessTerminatedListener;
import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ProgramRunner;
import lombok.val; import lombok.val;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Objects;
public record ZigRunExecutionConfigurationRunProfileState(ExecutionEnvironment environment, ZigRunExecutionConfiguration configuration) public final class ZigRunExecutionConfigurationRunProfileState extends CommandLineState {
implements RunProfileState { private final ZigRunExecutionConfiguration configuration;
@Override
public @NotNull ExecutionResult execute(Executor executor, @NotNull ProgramRunner<?> runner) public ZigRunExecutionConfigurationRunProfileState(ExecutionEnvironment environment, ZigRunExecutionConfiguration configuration) {
throws ExecutionException { super(environment);
val state = new CommandLineState(environment) { this.configuration = configuration;
}
@Override @Override
protected @NotNull ProcessHandler startProcess() throws ExecutionException { protected @NotNull ProcessHandler startProcess() throws ExecutionException {
val workingDirectory = configuration.workingDirectory; return new ZigCapturingProcessHandler(getCommandLine(ProjectUtil.getToolchain(getEnvironment().getProject())));
val zigExecutablePath = Objects.requireNonNull(ProjectUtil.getToolchain(environment.getProject())) }
.pathToExecutable("zig");
val commandLine = new GeneralCommandLine() public GeneralCommandLine getCommandLine(AbstractZigToolchain toolchain) {
.withExePath(zigExecutablePath.toString()) val workingDirectory = configuration.workingDirectory;
val zigExecutablePath = toolchain.pathToExecutable("zig");
return new GeneralCommandLine().withExePath(zigExecutablePath.toString())
.withWorkDirectory(workingDirectory.toString()) .withWorkDirectory(workingDirectory.toString())
.withCharset(StandardCharsets.UTF_8) .withCharset(StandardCharsets.UTF_8)
.withRedirectErrorStream(true) .withRedirectErrorStream(true)
.withParameters(configuration.command.split(" ")); .withParameters(configuration.command.split(" "));
}
return new ZigCapturingProcessHandler(commandLine); public ZigRunExecutionConfiguration configuration() {
return configuration;
} }
};
return state.execute(executor, runner); public DefaultExecutionResult executeCommandLine(GeneralCommandLine commandLine,
ExecutionEnvironment environment) throws ExecutionException {
val handler = startProcess(commandLine);
val console = getConsoleBuilder().getConsole();
console.attachToProcess(handler);
return new DefaultExecutionResult(console, handler);
} }
public static ProcessHandler startProcess(GeneralCommandLine commandLine) throws ExecutionException {
val handler = new ZigProcessHandler(commandLine);
ProcessTerminatedListener.attach(handler);
return handler;
}
} }

View file

@ -0,0 +1,48 @@
/*
* Copyright 2023 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.project.runconfig;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.runners.DefaultProgramRunnerKt;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.GenericProgramRunner;
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ZigDefaultProgramRunnerBase extends GenericProgramRunner<RunnerSettings> {
@Override
protected final void execute(@NotNull ExecutionEnvironment environment, @Nullable ProgramRunner.Callback callback, @NotNull RunProfileState state) {
super.execute(environment, callback, state);
}
@Override
protected void execute(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state) {
super.execute(environment, state);
}
@Nullable
@Override
protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment environment)
throws ExecutionException {
return DefaultProgramRunnerKt.executeState(state, environment, this);
}
}

View file

@ -0,0 +1,83 @@
/*
* Copyright 2023 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.project.runconfig;
import com.falsepattern.zigbrains.project.execution.configurations.AbstractZigExecutionConfiguration;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationRunProfileState;
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
import com.intellij.execution.DefaultExecutionResult;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.DefaultProgramRunnerKt;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ZigExecutableRunner extends ZigDefaultProgramRunnerBase {
protected final String executorId;
private final String errorMessageTitle;
public ZigExecutableRunner(String executorId, String errorMessageTitle) {
this.executorId = executorId;
this.errorMessageTitle = errorMessageTitle;
}
@Override
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
return executorId.equals(this.executorId) && profile instanceof AbstractZigExecutionConfiguration;
}
@Override
protected void execute(@NotNull ExecutionEnvironment environment, @NotNull RunProfileState state) {
super.execute(environment, state);
}
@Override
protected @Nullable RunContentDescriptor doExecute(@NotNull RunProfileState state$, @NotNull ExecutionEnvironment environment)
throws ExecutionException {
if (!(state$ instanceof ZigRunExecutionConfigurationRunProfileState state)) {
return null;
}
val toolchain = ZigProjectSettingsService.getInstance(environment.getProject()).getToolchain();
if (toolchain == null) {
return null;
}
val cli = state.getCommandLine(toolchain);
return showRunContent(state, environment, cli);
}
protected RunContentDescriptor showRunContent(ZigRunExecutionConfigurationRunProfileState state,
ExecutionEnvironment environment,
GeneralCommandLine runExecutable) throws ExecutionException {
return DefaultProgramRunnerKt.showRunContent(executeCommandLine(state, runExecutable, environment), environment);
}
private DefaultExecutionResult executeCommandLine(ZigRunExecutionConfigurationRunProfileState state,
GeneralCommandLine commandLine,
ExecutionEnvironment environment) throws ExecutionException {
return state.executeCommandLine(commandLine, environment);
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2023 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.project.runconfig;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.PtyCommandLine;
import com.intellij.execution.process.KillableProcessHandler;
import com.pty4j.PtyProcess;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.Charset;
public class ZigProcessHandler extends KillableProcessHandler {
public ZigProcessHandler(@NotNull GeneralCommandLine commandLine) throws ExecutionException {
super(commandLine);
setHasPty(commandLine instanceof PtyCommandLine);
setShouldDestroyProcessRecursively(!hasPty());
}
public ZigProcessHandler(@NotNull Process process, String commandLine, @NotNull Charset charset) {
super(process, commandLine, charset);
setHasPty(process instanceof PtyProcess);
setShouldDestroyProcessRecursively(!hasPty());
}
}

View file

@ -0,0 +1,43 @@
/*
* Copyright 2023 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.project.util;
import lombok.val;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
public class ElementUtil {
public static @Nullable String readString(Element element, String name) {
return element.getChildren()
.stream()
.filter(it -> it.getName()
.equals("ZigBrainsOption") &&
it.getAttributeValue("name")
.equals(name))
.findAny()
.map(it -> it.getAttributeValue("value"))
.orElse(null);
}
public static void writeString(Element element, String name, String value) {
val option = new Element("ZigBrainsOption");
option.setAttribute("name", name);
option.setAttribute("value", value);
element.addContent(option);
}
}

View file

@ -16,11 +16,9 @@
package com.falsepattern.zigbrains.zig.settings; package com.falsepattern.zigbrains.zig.settings;
import G.B.B.G.P;
import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.ui.TextBrowseFolderListener; import com.intellij.openapi.ui.TextBrowseFolderListener;
import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBLabel;
import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.FormBuilder;
@ -28,12 +26,6 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JPanel; import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
public class ZLSSettingsComponent { public class ZLSSettingsComponent {
private final JPanel myMainPanel; private final JPanel myMainPanel;