feat: Proper debugger support and some minor cleanup
This commit is contained in:
parent
5429a7034d
commit
d6afb01d08
19 changed files with 593 additions and 55 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -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
|
||||||
|
|
25
README.md
25
README.md
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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>
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
throws ExecutionException {
|
|
||||||
val state = new CommandLineState(environment) {
|
|
||||||
|
|
||||||
@Override
|
public ZigRunExecutionConfigurationRunProfileState(ExecutionEnvironment environment, ZigRunExecutionConfiguration configuration) {
|
||||||
protected @NotNull ProcessHandler startProcess() throws ExecutionException {
|
super(environment);
|
||||||
val workingDirectory = configuration.workingDirectory;
|
this.configuration = configuration;
|
||||||
val zigExecutablePath = Objects.requireNonNull(ProjectUtil.getToolchain(environment.getProject()))
|
|
||||||
.pathToExecutable("zig");
|
|
||||||
|
|
||||||
val commandLine = new GeneralCommandLine()
|
|
||||||
.withExePath(zigExecutablePath.toString())
|
|
||||||
.withWorkDirectory(workingDirectory.toString())
|
|
||||||
.withCharset(StandardCharsets.UTF_8)
|
|
||||||
.withRedirectErrorStream(true)
|
|
||||||
.withParameters(configuration.command.split(" "));
|
|
||||||
|
|
||||||
return new ZigCapturingProcessHandler(commandLine);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return state.execute(executor, runner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull ProcessHandler startProcess() throws ExecutionException {
|
||||||
|
return new ZigCapturingProcessHandler(getCommandLine(ProjectUtil.getToolchain(getEnvironment().getProject())));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GeneralCommandLine getCommandLine(AbstractZigToolchain toolchain) {
|
||||||
|
val workingDirectory = configuration.workingDirectory;
|
||||||
|
val zigExecutablePath = toolchain.pathToExecutable("zig");
|
||||||
|
|
||||||
|
return new GeneralCommandLine().withExePath(zigExecutablePath.toString())
|
||||||
|
.withWorkDirectory(workingDirectory.toString())
|
||||||
|
.withCharset(StandardCharsets.UTF_8)
|
||||||
|
.withRedirectErrorStream(true)
|
||||||
|
.withParameters(configuration.command.split(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZigRunExecutionConfiguration configuration() {
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue