backport: 12.1.0-pre01

This commit is contained in:
FalsePattern 2024-03-04 01:53:52 +01:00
parent b8a448d7fe
commit ff29b663dc
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
65 changed files with 1547 additions and 730 deletions

View file

@ -18,6 +18,26 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
### Added
- Debugging
- Debugging support for tests when launched using the ZigTest task type (and with the gutter icons in the editor)
- Project
- Added `zig init` as a new project creation option
- New projects will now have the project name in the build files instead of "untitled"
- Zig
- Updated semantic highlighting to latest ZLS protocol
### Fixed
- Project
- Fixed build.zig and build.zig.zon getting placed in src/ during project creation
- Plugin
- Removed a bunch of write action locking, the editor should feel more responsive now
## [12.0.0] ## [12.0.0]
### Added ### Added

View file

@ -1,10 +1,7 @@
import groovy.xml.XmlParser import groovy.xml.XmlParser
import org.jetbrains.changelog.Changelog import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
import org.jetbrains.grammarkit.tasks.GenerateParserTask
import org.jetbrains.intellij.tasks.PatchPluginXmlTask import org.jetbrains.intellij.tasks.PatchPluginXmlTask
import org.jetbrains.intellij.tasks.RunPluginVerifierTask
fun properties(key: String) = providers.gradleProperty(key) fun properties(key: String) = providers.gradleProperty(key)
fun environment(key: String) = providers.environmentVariable(key) fun environment(key: String) = providers.environmentVariable(key)
@ -15,8 +12,11 @@ plugins {
id("org.jetbrains.intellij") version("1.17.2") id("org.jetbrains.intellij") version("1.17.2")
id("org.jetbrains.changelog") version("2.2.0") id("org.jetbrains.changelog") version("2.2.0")
id("org.jetbrains.grammarkit") version("2022.3.2.2") id("org.jetbrains.grammarkit") version("2022.3.2.2")
id("com.palantir.git-version") version("3.0.0")
} }
val gitVersion: groovy.lang.Closure<String> by extra
val grammarKitGenDir = "build/generated/sources/grammarkit/java" val grammarKitGenDir = "build/generated/sources/grammarkit/java"
val rootPackage = "com.falsepattern.zigbrains" val rootPackage = "com.falsepattern.zigbrains"
@ -43,8 +43,20 @@ tasks {
} }
} }
fun getPluginVersionFull(): Provider<String> { fun pluginVersion(): Provider<String> {
return properties("pluginVersion").map { it + "-" + properties("pluginSinceBuild").get() } return provider {
System.getenv("RELEASE_VERSION")
}.orElse(provider {
try {
gitVersion()
} catch (_: java.lang.Exception) {
error("Git version not found and RELEASE_VERSION environment variable is not set!")
}
})
}
fun pluginVersionFull(): Provider<String> {
return pluginVersion().map { it + "-" + properties("pluginSinceBuild").get() }
} }
allprojects { allprojects {
@ -86,7 +98,7 @@ allprojects {
} }
group = properties("pluginGroup").get() group = properties("pluginGroup").get()
version = getPluginVersionFull().get() version = pluginVersionFull().get()
tasks { tasks {
runIde { enabled = false } runIde { enabled = false }
@ -303,7 +315,7 @@ project(":plugin") {
} }
patchPluginXml { patchPluginXml {
version = getPluginVersionFull() version = pluginVersionFull()
// Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest // Extract the <!-- Plugin description --> section from README.md and provide for the plugin's manifest
pluginDescription = providers.fileContents(rootProject.layout.projectDirectory.file("README.md")).asText.map { pluginDescription = providers.fileContents(rootProject.layout.projectDirectory.file("README.md")).asText.map {
@ -320,7 +332,7 @@ project(":plugin") {
val changelog = rootProject.changelog // local variable for configuration cache compatibility val changelog = rootProject.changelog // local variable for configuration cache compatibility
// Get the latest available change notes from the changelog file // Get the latest available change notes from the changelog file
changeNotes = properties("pluginVersion").map { pluginVersion -> changeNotes = pluginVersion().map { pluginVersion ->
with(changelog) { with(changelog) {
renderItem( renderItem(
(getOrNull(pluginVersion) ?: getUnreleased()) (getOrNull(pluginVersion) ?: getUnreleased())

View file

@ -1,8 +1,6 @@
pluginGroup = com.falsepattern.zigbrains pluginGroup = com.falsepattern.zigbrains
pluginName = ZigBrains pluginName = ZigBrains
pluginRepositoryUrl = https://github.com/FalsePattern/ZigBrains pluginRepositoryUrl = https://github.com/FalsePattern/ZigBrains
# SemVer format -> https://semver.org
pluginVersion = 12.0.0
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 232 pluginSinceBuild = 232

View file

@ -1,32 +0,0 @@
/*
* 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.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

@ -16,7 +16,7 @@
package com.falsepattern.zigbrains.zig.debugger; package com.falsepattern.zigbrains.zig.debugger;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration; import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.configurations.RunProfile;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.jetbrains.cidr.execution.debugger.CidrDebuggerLanguageSupport; import com.jetbrains.cidr.execution.debugger.CidrDebuggerLanguageSupport;
@ -34,7 +34,7 @@ public class ZigDebuggerLanguageSupport extends CidrDebuggerLanguageSupport {
@Override @Override
public @Nullable XDebuggerEditorsProvider createEditor(@Nullable RunProfile profile) { public @Nullable XDebuggerEditorsProvider createEditor(@Nullable RunProfile profile) {
if (!(profile instanceof ZigRunExecutionConfiguration)) { if (!(profile instanceof ZigExecConfigBase<?>)) {
return null; return null;
} }
return createEditorProvider(); return createEditorProvider();

View file

@ -14,12 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.zig.debugger; package com.falsepattern.zigbrains.zig.debugger.base;
import com.intellij.execution.configurations.GeneralCommandLine; import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.jetbrains.cidr.execution.Installer; import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.jetbrains.cidr.execution.RunParameters; 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.DebuggerDriverConfiguration;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -27,14 +26,10 @@ import org.jetbrains.annotations.Nullable;
@RequiredArgsConstructor @RequiredArgsConstructor
public class ZigDebugRunParameters extends RunParameters { public abstract class ZigDebugParametersBase<ProfileState extends ProfileStateBase<?>> extends RunParameters {
private final GeneralCommandLine cmd;
private final DebuggerDriverConfiguration driverConfiguration; private final DebuggerDriverConfiguration driverConfiguration;
protected final AbstractZigToolchain toolchain;
@Override protected final ProfileState profileState;
public @NotNull Installer getInstaller() {
return new TrivialInstaller(cmd);
}
@Override @Override
public @NotNull DebuggerDriverConfiguration getDebuggerDriverConfiguration() { public @NotNull DebuggerDriverConfiguration getDebuggerDriverConfiguration() {

View file

@ -14,12 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.zig.debugger; package com.falsepattern.zigbrains.zig.debugger.base;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationRunProfileState; import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.runconfig.ZigExecutableRunner; import com.falsepattern.zigbrains.project.runconfig.ZigProgramRunnerBase;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.zig.debugger.Utils;
import com.falsepattern.zigbrains.zig.debugger.ZigLocalDebugProcess;
import com.intellij.execution.ExecutionException; 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.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessTerminatedListener; import com.intellij.execution.process.ProcessTerminatedListener;
import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ExecutionEnvironment;
@ -31,19 +34,18 @@ import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter; import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerManager;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.val; import lombok.val;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays; public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?>> extends ZigProgramRunnerBase<ProfileState> {
public class ZigDebugRunnerBase extends ZigExecutableRunner {
public ZigDebugRunnerBase() { public ZigDebugRunnerBase() {
super(DefaultDebugExecutor.EXECUTOR_ID, "Unable to run Zig debugger"); super(DefaultDebugExecutor.EXECUTOR_ID);
} }
@Override @Override
protected RunContentDescriptor showRunContent(ZigRunExecutionConfigurationRunProfileState state, ExecutionEnvironment environment, GeneralCommandLine runExecutable) protected RunContentDescriptor doExecute(ProfileState state, AbstractZigToolchain toolchain, ExecutionEnvironment environment)
throws ExecutionException { throws ExecutionException {
val project = environment.getProject(); val project = environment.getProject();
val debuggerDriver = Utils.getDebuggerConfiguration(project); val debuggerDriver = Utils.getDebuggerConfiguration(project);
@ -51,7 +53,11 @@ public class ZigDebugRunnerBase extends ZigExecutableRunner {
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)); 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; return null;
} }
val runParameters = new ZigDebugRunParameters(runExecutable, debuggerDriver); val runParameters = getDebugParameters(state, environment, debuggerDriver, toolchain);
if (runParameters == null) {
//Assume that getDebugParameters reports the bug in a notification already
return null;
}
val manager = XDebuggerManager.getInstance(project); val manager = XDebuggerManager.getInstance(project);
return manager.startSession(environment, return manager.startSession(environment,
new XDebugProcessStarter() { new XDebugProcessStarter() {
@ -66,7 +72,7 @@ public class ZigDebugRunnerBase extends ZigExecutableRunner {
} }
@Override @Override
public @NotNull @NonNls String getRunnerId() { public abstract boolean canRun(@NotNull String executorId, @NotNull RunProfile profile);
return "ZigDebugRunner";
} protected abstract @Nullable ZigDebugParametersBase<ProfileState> getDebugParameters(ProfileState state, ExecutionEnvironment environment, DebuggerDriverConfiguration debuggerDriver, AbstractZigToolchain toolchain);
} }

View file

@ -0,0 +1,36 @@
/*
* 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.zig.debugger.run;
import com.falsepattern.zigbrains.project.execution.run.ProfileStateRun;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.zig.debugger.base.ZigDebugParametersBase;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.TrivialInstaller;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import org.jetbrains.annotations.NotNull;
public class ZigDebugParametersRun extends ZigDebugParametersBase<ProfileStateRun> {
public ZigDebugParametersRun(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateRun profileState) {
super(driverConfiguration, toolchain, profileState);
}
@Override
public @NotNull Installer getInstaller() {
return new TrivialInstaller(profileState.getCommandLine(toolchain));
}
}

View file

@ -0,0 +1,60 @@
/*
* 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.zig.debugger.run;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.execution.run.ProfileStateRun;
import com.falsepattern.zigbrains.project.execution.run.ZigExecConfigRun;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
import com.falsepattern.zigbrains.zig.debugger.base.ZigDebugRunnerBase;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigDebugRunnerRun extends ZigDebugRunnerBase<ProfileStateRun> {
@Override
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
return this.executorId.equals(executorId) &&
(profile instanceof ZigExecConfigRun);
}
@Override
public @NotNull @NonNls String getRunnerId() {
return "ZigDebugRunnerRun";
}
@Override
protected ZigDebugParametersRun getDebugParameters(ProfileStateRun profileStateRun, ExecutionEnvironment environment, DebuggerDriverConfiguration debuggerDriver, AbstractZigToolchain toolchain$) {
if (!(toolchain$ instanceof LocalZigToolchain toolchain)) {
Notifications.Bus.notify(new Notification("ZigBrains.Debugger.Error", "The debugger only supports local zig toolchains!", NotificationType.ERROR));
return null;
}
return new ZigDebugParametersRun(debuggerDriver, toolchain, profileStateRun);
}
@Override
protected @Nullable ProfileStateRun castProfileState(ProfileStateBase<?> state) {
return state instanceof ProfileStateRun state$ ? state$ : null;
}
}

View file

@ -0,0 +1,100 @@
/*
* 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.zig.debugger.test;
import com.falsepattern.zigbrains.project.execution.test.ProfileStateTest;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.falsepattern.zigbrains.zig.debugger.base.ZigDebugParametersBase;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessListener;
import com.jetbrains.cidr.execution.Installer;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
import java.util.stream.Collectors;
public class ZigDebugParametersTest extends ZigDebugParametersBase<ProfileStateTest> {
public ZigDebugParametersTest(DebuggerDriverConfiguration driverConfiguration, AbstractZigToolchain toolchain, ProfileStateTest profileState) {
super(driverConfiguration, toolchain, profileState);
}
@Override
public @NotNull Installer getInstaller() {
return new ZigTestInstaller();
}
private class ZigTestInstaller implements Installer {
private File executableFile;
@Override
public @NotNull GeneralCommandLine install() throws ExecutionException {
val commandLine = profileState.getCommandLine(toolchain);
final Path tmpDir;
try {
tmpDir = Files.createTempDirectory("zigbrains_debug").toAbsolutePath();
} catch (IOException e) {
throw new ExecutionException("Failed to create temporary directory for test binary", e);
}
val exe = tmpDir.resolve("executable").toFile();
commandLine.addParameters("--test-no-exec", "-femit-bin=" + exe.getAbsolutePath());
val outputOpt = CLIUtil.execute(commandLine, Integer.MAX_VALUE);
if (outputOpt.isEmpty()) {
throw new ExecutionException("Failed to start \"zig test\"!");
}
val output = outputOpt.get();
if (output.getExitCode() != 0) {
throw new ExecutionException("Zig test compilation failed with exit code " + output.getExitCode() + "\nError output:\n" + output.getStdout() + "\n" + output.getStderr());
}
//Find our binary
try (val stream = Files.list(tmpDir)){
executableFile = stream.filter(file -> !file.getFileName().toString().endsWith(".o"))
.map(Path::toFile)
.filter(File::canExecute)
.findFirst()
.orElseThrow(() -> new IOException("No executable file present in temporary directory \"" +
tmpDir + "\""));
} catch (Exception e) {
throw new ExecutionException("Failed to find compiled test binary", e);
}
//Construct new command line
val cfg = profileState.configuration();
val cli = new GeneralCommandLine().withExePath(executableFile.getAbsolutePath());
if (cfg.workingDirectory != null) {
cli.withWorkDirectory(cfg.workingDirectory.toString());
}
cli.withCharset(StandardCharsets.UTF_8);
cli.withRedirectErrorStream(true);
return cli;
}
@Override
public @NotNull File getExecutableFile() {
return executableFile;
}
}
}

View file

@ -0,0 +1,61 @@
/*
* 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.zig.debugger.test;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.execution.test.ProfileStateTest;
import com.falsepattern.zigbrains.project.execution.test.ZigExecConfigTest;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
import com.falsepattern.zigbrains.zig.debugger.base.ZigDebugParametersBase;
import com.falsepattern.zigbrains.zig.debugger.base.ZigDebugRunnerBase;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigDebugRunnerTest extends ZigDebugRunnerBase<ProfileStateTest> {
@Override
public @NotNull @NonNls String getRunnerId() {
return "ZigDebugRunnerTest";
}
@Override
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
return this.executorId.equals(executorId) &&
(profile instanceof ZigExecConfigTest);
}
@Override
protected @Nullable ZigDebugParametersBase<ProfileStateTest> getDebugParameters(ProfileStateTest profileStateTest, ExecutionEnvironment environment, DebuggerDriverConfiguration debuggerDriver, AbstractZigToolchain toolchain$) {
if (!(toolchain$ instanceof LocalZigToolchain toolchain)) {
Notifications.Bus.notify(new Notification("ZigBrains.Debugger.Error", "The debugger only supports local zig toolchains!", NotificationType.ERROR));
return null;
}
return new ZigDebugParametersTest(debuggerDriver, toolchain, profileStateTest);
}
@Override
protected @Nullable ProfileStateTest castProfileState(ProfileStateBase<?> state) {
return state instanceof ProfileStateTest state$ ? state$ : null;
}
}

View file

@ -19,8 +19,10 @@
<resource-bundle>zigbrains.zig.debugger.Bundle</resource-bundle> <resource-bundle>zigbrains.zig.debugger.Bundle</resource-bundle>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<programRunner implementation="com.falsepattern.zigbrains.zig.debugger.ZigDebugRunner" <programRunner implementation="com.falsepattern.zigbrains.zig.debugger.run.ZigDebugRunnerRun"
id="ZigDebugRunner"/> id="ZigDebugRunnerRun"/>
<programRunner implementation="com.falsepattern.zigbrains.zig.debugger.test.ZigDebugRunnerTest"
id="ZigDebugRunnerTest"/>
<notificationGroup displayType="BALLOON" <notificationGroup displayType="BALLOON"
bundle="zigbrains.zig.debugger.Bundle" bundle="zigbrains.zig.debugger.Bundle"

View file

@ -23,11 +23,8 @@ import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.completion.PlainPrefixMatcher; import com.intellij.codeInsight.completion.PlainPrefixMatcher;
import com.intellij.openapi.application.ex.ApplicationUtil;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.util.ProcessingContext; import com.intellij.util.ProcessingContext;
import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Position;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -40,23 +37,18 @@ class LSPCompletionContributor extends CompletionContributor {
@Override @Override
public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) {
CompletionProvider<CompletionParameters> provider = new CompletionProvider<CompletionParameters>() { CompletionProvider<CompletionParameters> provider = new CompletionProvider<>() {
@Override @Override
protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) { protected void addCompletions(@NotNull CompletionParameters parameters, @NotNull ProcessingContext context, @NotNull CompletionResultSet result) {
try { try {
ApplicationUtil.runWithCheckCanceled(() -> { Editor editor = parameters.getEditor();
Editor editor = parameters.getEditor(); int offset = parameters.getOffset();
int offset = parameters.getOffset(); Position serverPos = DocumentUtils.offsetToLSPPos(editor, offset);
Position serverPos = DocumentUtils.offsetToLSPPos(editor, offset);
EditorEventManager manager = EditorEventManagerBase.forEditor(editor); EditorEventManager manager = EditorEventManagerBase.forEditor(editor);
if (manager != null) { if (manager != null) {
result.addAllElements(manager.completion(serverPos)); result.addAllElements(manager.completion(serverPos));
} }
return null;
}, ProgressIndicatorProvider.getGlobalProgressIndicator());
} catch (ProcessCanceledException ignored) {
// ProcessCanceledException can be ignored.
} catch (Exception e) { } catch (Exception e) {
LOG.warn("LSP Completions ended with an error", e); LOG.warn("LSP Completions ended with an error", e);
} }

View file

@ -1302,13 +1302,7 @@ public class EditorEventManager {
val sourceOffset = element.getTextOffset(); val sourceOffset = element.getTextOffset();
val loc = requestDefinition(DocumentUtils.offsetToLSPPos(editor, sourceOffset)); val loc = requestDefinition(DocumentUtils.offsetToLSPPos(editor, sourceOffset));
invokeLater(() -> { gotoLocation(loc);
if (editor.isDisposed()) {
return;
}
gotoLocation(loc);
});
} }
// Tries to go to declaration / show usages based on the element which is // Tries to go to declaration / show usages based on the element which is
@ -1328,25 +1322,19 @@ public class EditorEventManager {
return; return;
} }
invokeLater(() -> { String locUri = FileUtils.sanitizeURI(loc.getUri());
if (editor.isDisposed()) {
return;
}
String locUri = FileUtils.sanitizeURI(loc.getUri()); if (identifier.getUri().equals(locUri)
&& sourceOffset >= DocumentUtils.LSPPosToOffset(editor, loc.getRange().getStart())
if (identifier.getUri().equals(locUri) && sourceOffset <= DocumentUtils.LSPPosToOffset(editor, loc.getRange().getEnd())) {
&& sourceOffset >= DocumentUtils.LSPPosToOffset(editor, loc.getRange().getStart()) LSPReferencesAction referencesAction = (LSPReferencesAction) ActionManager.getInstance()
&& sourceOffset <= DocumentUtils.LSPPosToOffset(editor, loc.getRange().getEnd())) { .getAction("LSPFindUsages");
LSPReferencesAction referencesAction = (LSPReferencesAction) ActionManager.getInstance() if (referencesAction != null) {
.getAction("LSPFindUsages"); referencesAction.forManagerAndOffset(this, sourceOffset);
if (referencesAction != null) {
referencesAction.forManagerAndOffset(this, sourceOffset);
}
} else {
gotoLocation(loc);
} }
}); } else {
gotoLocation(loc);
}
} }
public void gotoLocation(Location loc) { public void gotoLocation(Location loc) {
@ -1359,7 +1347,7 @@ public class EditorEventManager {
if (file != null) { if (file != null) {
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file); OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
VirtualFile finalFile = file; VirtualFile finalFile = file;
writeAction(() -> { invokeLater(() -> {
FileEditorManager.getInstance(project).openTextEditor(descriptor, true); FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
Editor srcEditor = FileUtils.editorFromVirtualFile(finalFile, project); Editor srcEditor = FileUtils.editorFromVirtualFile(finalFile, project);
if (srcEditor != null) { if (srcEditor != null) {

1
modules/project/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
!src/**/build/

View file

@ -1,31 +0,0 @@
/*
* 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.project.execution.actions;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationType;
import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractZigRunExecutionConfigurationProducer extends LazyRunConfigurationProducer<ZigRunExecutionConfiguration> {
@NotNull
@Override
public ConfigurationFactory getConfigurationFactory() {
return ZigRunExecutionConfigurationType.getInstance().getFactory();
}
}

View file

@ -14,34 +14,26 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.actions; package com.falsepattern.zigbrains.project.execution.base;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration; import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationType;
import com.falsepattern.zigbrains.zig.parser.ZigFile; import com.falsepattern.zigbrains.zig.parser.ZigFile;
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.falsepattern.zigbrains.zig.util.PsiUtil;
import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.ConfigurationFromContext; import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory; import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import lombok.val; import lombok.val;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Objects; public abstract class ConfigProducerBase<T extends ZigExecConfigBase<T>> extends LazyRunConfigurationProducer<T> {
@NotNull
public class ZigRunExecutionConfigurationProducer extends AbstractZigRunExecutionConfigurationProducer{
@Override @Override
public @NotNull ConfigurationFactory getConfigurationFactory() { public abstract ConfigurationFactory getConfigurationFactory();
return Objects.requireNonNull(
ConfigurationTypeUtil.findConfigurationType(ZigRunExecutionConfigurationType.IDENTIFIER))
.getConfigurationFactories()[0];
}
@Override @Override
protected boolean setupConfigurationFromContext(@NotNull ZigRunExecutionConfiguration configuration, @NotNull ConfigurationContext context, @NotNull Ref<PsiElement> sourceElement) { protected final boolean setupConfigurationFromContext(@NotNull T configuration, @NotNull ConfigurationContext context, @NotNull Ref<PsiElement> sourceElement) {
var loc = context.getLocation(); var loc = context.getLocation();
if (loc == null) { if (loc == null) {
return false; return false;
@ -56,21 +48,11 @@ public class ZigRunExecutionConfigurationProducer extends AbstractZigRunExecutio
} }
var theFile = psiFile.getVirtualFile(); var theFile = psiFile.getVirtualFile();
var filePath = theFile.getPath(); var filePath = theFile.getPath();
if (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) { return setupConfigurationFromContext(configuration, element, filePath, theFile);
configuration.command = "test " + filePath;
configuration.setName("Test " + theFile.getPresentableName());
} else if ("build.zig".equals(theFile.getName())) {
configuration.command = "build";
configuration.setName("Build");
} else {
configuration.command = "run " + filePath;
configuration.setName(theFile.getPresentableName());
}
return true;
} }
@Override @Override
public boolean isConfigurationFromContext(@NotNull ZigRunExecutionConfiguration configuration, @NotNull ConfigurationContext context) { public final boolean isConfigurationFromContext(@NotNull T configuration, @NotNull ConfigurationContext context) {
if (context.getLocation() == null) { if (context.getLocation() == null) {
return false; return false;
} }
@ -84,14 +66,35 @@ public class ZigRunExecutionConfigurationProducer extends AbstractZigRunExecutio
} }
val vFile = file.getVirtualFile(); val vFile = file.getVirtualFile();
val filePath = vFile.getPath(); val filePath = vFile.getPath();
return isConfigurationFromContext(configuration, filePath, vFile, element);
}
/*
TODO implement these
@Override
protected boolean setupConfigurationFromContext(@NotNull ZigExecConfigRun configuration, PsiElement element, String filePath, VirtualFile theFile) {
if (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) {
configuration.command = "test " + filePath;
configuration.setName("Test " + theFile.getPresentableName());
} else if ("build.zig".equals(theFile.getName())) {
configuration.command = "build";
configuration.setName("Build");
} else {
configuration.extraArgs = filePath;
configuration.setName(theFile.getPresentableName());
}
return true;
}
@Override
protected boolean isConfigurationFromContext(@NotNull ZigExecConfigRun configuration, String filePath, VirtualFile vFile, PsiElement element) {
if (!configuration.command.contains(filePath)) { if (!configuration.command.contains(filePath)) {
return configuration.command.startsWith("build") && vFile.getName().equals("build.zig"); return configuration.command.startsWith("build") && vFile.getName().equals("build.zig");
} }
return (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) == configuration.command.startsWith("test "); return (PsiUtil.getElementType(element) == ZigTypes.KEYWORD_TEST) == configuration.command.startsWith("test ");
} }
*/
@Override protected abstract boolean setupConfigurationFromContext(@NotNull T configuration, PsiElement element, String filePath, VirtualFile theFile);
public boolean shouldReplace(@NotNull ConfigurationFromContext self, @NotNull ConfigurationFromContext other) { protected abstract boolean isConfigurationFromContext(@NotNull T configuration, String filePath, VirtualFile vFile, PsiElement element);
return self.getConfigurationType() instanceof ZigRunExecutionConfigurationType;
}
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.configurations; package com.falsepattern.zigbrains.project.execution.base;
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.runconfig.ZigProcessHandler;
@ -32,10 +32,10 @@ import org.jetbrains.annotations.NotNull;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public final class ZigRunExecutionConfigurationRunProfileState extends CommandLineState { public abstract class ProfileStateBase<T extends ZigExecConfigBase<T>> extends CommandLineState {
private final ZigRunExecutionConfiguration configuration; protected final T configuration;
public ZigRunExecutionConfigurationRunProfileState(ExecutionEnvironment environment, ZigRunExecutionConfiguration configuration) { public ProfileStateBase(ExecutionEnvironment environment, T configuration) {
super(environment); super(environment);
this.configuration = configuration; this.configuration = configuration;
} }
@ -53,15 +53,15 @@ public final class ZigRunExecutionConfigurationRunProfileState extends CommandLi
.withWorkDirectory(workingDirectory.toString()) .withWorkDirectory(workingDirectory.toString())
.withCharset(StandardCharsets.UTF_8) .withCharset(StandardCharsets.UTF_8)
.withRedirectErrorStream(true) .withRedirectErrorStream(true)
.withParameters(configuration.command.split(" ")); .withParameters(configuration.buildCommandLineArgs());
} }
public ZigRunExecutionConfiguration configuration() { public T configuration() {
return configuration; return configuration;
} }
public DefaultExecutionResult executeCommandLine(GeneralCommandLine commandLine, public DefaultExecutionResult executeCommandLine(GeneralCommandLine commandLine, ExecutionEnvironment environment)
ExecutionEnvironment environment) throws ExecutionException { throws ExecutionException {
val handler = startProcess(commandLine); val handler = startProcess(commandLine);
val console = getConsoleBuilder().getConsole(); val console = getConsoleBuilder().getConsole();
console.attachToProcess(handler); console.attachToProcess(handler);
@ -73,5 +73,4 @@ public final class ZigRunExecutionConfigurationRunProfileState extends CommandLi
ProcessTerminatedListener.attach(handler); ProcessTerminatedListener.attach(handler);
return handler; return handler;
} }
} }

View file

@ -0,0 +1,92 @@
/*
* 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.project.execution.base;
import com.falsepattern.zigbrains.project.ui.WorkingDirectoryComponent;
import com.falsepattern.zigbrains.project.ui.ZigFilePathPanel;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.ui.dsl.builder.AlignX;
import com.intellij.ui.dsl.builder.AlignY;
import com.intellij.ui.dsl.builder.Panel;
import org.jetbrains.annotations.NotNull;
import javax.swing.JComponent;
import java.nio.file.Paths;
import java.util.Objects;
import static com.intellij.ui.dsl.builder.BuilderKt.panel;
public class ZigConfigEditor<T extends ZigExecConfigBase<T>> extends SettingsEditor<T> {
protected final LabeledComponent<TextFieldWithBrowseButton> workingDirectoryComponent =
new WorkingDirectoryComponent();
@Override
protected void applyEditorTo(@NotNull T s) throws ConfigurationException {
s.workingDirectory = Paths.get(workingDirectoryComponent.getComponent().getText());
}
@Override
protected void resetEditorFrom(@NotNull T s) {
workingDirectoryComponent.getComponent().setText(Objects.requireNonNullElse(s.workingDirectory, "").toString());
}
@Override
protected final @NotNull JComponent createEditor() {
return panel((p) -> {
constructPanel(p);
return null;
});
}
protected void constructPanel(Panel p) {
p.row(workingDirectoryComponent.getLabel(), (r) -> {
r.cell(workingDirectoryComponent).resizableColumn().align(AlignX.FILL).align(AlignY.FILL);
return null;
});
}
public static abstract class WithFilePath<T extends ZigExecConfigBase<T>> extends ZigConfigEditor<T> {
private final ZigFilePathPanel filePathPanel = new ZigFilePathPanel();
@Override
protected void applyEditorTo(@NotNull T s) throws ConfigurationException {
super.applyEditorTo(s);
setFilePath(s, filePathPanel.getText());
}
@Override
protected void resetEditorFrom(@NotNull T s) {
super.resetEditorFrom(s);
filePathPanel.setText(Objects.requireNonNullElse(getFilePath(s), ""));
}
@Override
protected void constructPanel(Panel p) {
super.constructPanel(p);
p.row("Target file", (r) -> {
r.cell(filePathPanel).resizableColumn().align(AlignX.FILL).align(AlignY.FILL);
return null;
});
}
protected abstract String getFilePath(T config);
protected abstract void setFilePath(T config, String path);
}
}

View file

@ -14,44 +14,37 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.configurations; package com.falsepattern.zigbrains.project.execution.base;
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;
import com.intellij.execution.configurations.LocatableConfigurationBase; import com.intellij.execution.configurations.LocatableConfigurationBase;
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.NlsActions; import com.intellij.openapi.util.NlsActions;
import com.intellij.openapi.util.text.Strings;
import lombok.val;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Optional; import java.util.Optional;
public abstract class AbstractZigExecutionConfiguration extends LocatableConfigurationBase<RunProfileState> { public abstract class ZigExecConfigBase<T extends ZigExecConfigBase<T>> extends LocatableConfigurationBase<ProfileStateBase<T>> {
public @Nullable Path workingDirectory; public @Nullable Path workingDirectory;
public AbstractZigExecutionConfiguration(@NotNull Project project, @NotNull ConfigurationFactory factory, @Nullable String name) { public ZigExecConfigBase(@NotNull Project project, @NotNull ConfigurationFactory factory, @Nullable String name) {
super(project, factory, name); super(project, factory, name);
workingDirectory = project.isDefault() ? null : Optional.ofNullable(project.getBasePath()) workingDirectory = project.isDefault() ? null : Optional.ofNullable(project.getBasePath())
.map(Path::of) .map(Path::of)
.orElse(null); .orElse(null);
} }
public abstract String getCommand(); public abstract String[] buildCommandLineArgs();
public abstract void setCommand(String value);
@Override @Override
public @Nullable @NlsActions.ActionText String suggestedName() { public abstract @Nullable @NlsActions.ActionText String suggestedName();
val cmd = getCommand();
var spaceIndex = cmd.indexOf(' ');
return Strings.capitalize(spaceIndex > 0 ? cmd.substring(0, spaceIndex) : cmd);
}
@Override @Override
public abstract @Nullable RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) public abstract @Nullable ProfileStateBase<T> getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment)
throws ExecutionException; throws ExecutionException;
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.linemarker; package com.falsepattern.zigbrains.project.execution.base;
import com.falsepattern.zigbrains.zig.psi.ZigTypes; import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.falsepattern.zigbrains.zig.util.PsiUtil; import com.falsepattern.zigbrains.zig.util.PsiUtil;
@ -28,9 +28,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Icon; import javax.swing.Icon;
public abstract class ZigTopLevelDeclarationLineMarkerContributorBase extends RunLineMarkerContributor { public abstract class ZigTopLevelLineMarkerBase extends RunLineMarkerContributor {
@Override private @Nullable PsiElement getParentIfTopLevel(@NotNull PsiElement element) {
public @Nullable Info getInfo(@NotNull PsiElement element) {
PsiElement parent = getDeclaration(element); PsiElement parent = getDeclaration(element);
int nestingLevel = 0; int nestingLevel = 0;
@ -44,7 +43,18 @@ public abstract class ZigTopLevelDeclarationLineMarkerContributorBase extends Ru
if (nestingLevel != 1) { if (nestingLevel != 1) {
return null; return null;
} }
return parent;
}
public boolean elementMatches(@NotNull PsiElement element) {
return getParentIfTopLevel(element) != null;
}
@Override
public @Nullable Info getInfo(@NotNull PsiElement element) {
val parent = getParentIfTopLevel(element);
if (parent == null)
return null;
val actions = ExecutorAction.getActions(0); val actions = ExecutorAction.getActions(0);
return new Info(getIcon(element), actions, null); return new Info(getIcon(element), actions, null);
} }

View file

@ -0,0 +1,44 @@
/*
* 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.project.execution.build;
import com.falsepattern.zigbrains.project.execution.base.ConfigProducerBase;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
public class ConfigProducerBuild extends ConfigProducerBase<ZigExecConfigBuild> {
@Override
public @NotNull ConfigurationFactory getConfigurationFactory() {
return ConfigTypeBuild.getInstance().getConfigurationFactories()[0];
}
@Override
protected boolean setupConfigurationFromContext(@NotNull ZigExecConfigBuild configuration, PsiElement element, String filePath, VirtualFile theFile) {
if (ZigLineMarkerBuild.UTILITY_INSTANCE.elementMatches(element)) {
configuration.setName("Build");
return true;
}
return false;
}
@Override
protected boolean isConfigurationFromContext(@NotNull ZigExecConfigBuild configuration, String filePath, VirtualFile vFile, PsiElement element) {
return true;
}
}

View file

@ -0,0 +1,55 @@
/*
* 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.project.execution.build;
import com.falsepattern.zigbrains.zig.Icons;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ConfigTypeBuild extends ConfigurationTypeBase {
public static final String IDENTIFIER = "ZIGBRAINS_BUILD";
public static ConfigTypeBuild getInstance() {
return ConfigurationTypeUtil.findConfigurationType(ConfigTypeBuild.class);
}
public ConfigTypeBuild() {
super(IDENTIFIER, "ZigBuild", "Zig Build", Icons.ZIG);
addFactory(new ConfigFactoryBuild());
}
public class ConfigFactoryBuild extends ConfigurationFactory {
public ConfigFactoryBuild() {
super(ConfigTypeBuild.this);
}
@Override
public @NotNull RunConfiguration createTemplateConfiguration(@NotNull Project project) {
return new ZigExecConfigBuild(project, this);
}
@Override
public @NotNull @NonNls String getId() {
return IDENTIFIER;
}
}
}

View file

@ -0,0 +1,26 @@
/*
* 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.project.execution.build;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.intellij.execution.runners.ExecutionEnvironment;
public class ProfileStateBuild extends ProfileStateBase<ZigExecConfigBuild> {
public ProfileStateBuild(ExecutionEnvironment environment, ZigExecConfigBuild configuration) {
super(environment, configuration);
}
}

View file

@ -0,0 +1,112 @@
/*
* 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.project.execution.build;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.util.ElementUtil;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.ui.components.JBTextField;
import com.intellij.ui.dsl.builder.AlignX;
import com.intellij.ui.dsl.builder.AlignY;
import com.intellij.ui.dsl.builder.Panel;
import lombok.val;
import org.apache.groovy.util.Arrays;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
public class ZigExecConfigBuild extends ZigExecConfigBase<ZigExecConfigBuild> {
public String extraArguments = "";
public ZigExecConfigBuild(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Build");
}
@Override
public String[] buildCommandLineArgs() {
val base = new String[]{"build"};
if (extraArguments.isBlank()) {
return base;
} else {
return Arrays.concat(base, extraArguments.split(" "));
}
}
@Override
public @Nullable String suggestedName() {
return "Build";
}
@Override
public @NotNull Editor getConfigurationEditor() {
return new Editor();
}
@Override
public @Nullable ProfileStateBuild getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
return new ProfileStateBuild(environment, this);
}
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
super.readExternal(element);
val extraArguments = ElementUtil.readString(element, "extraArguments");
if (extraArguments != null) {
this.extraArguments = extraArguments;
}
}
@Override
public void writeExternal(@NotNull Element element) {
super.writeExternal(element);
ElementUtil.writeString(element, "extraArguments", extraArguments);
}
public static class Editor extends ZigConfigEditor<ZigExecConfigBuild> {
private final JBTextField extraArgs = new JBTextField();
@Override
protected void applyEditorTo(@NotNull ZigExecConfigBuild s) throws ConfigurationException {
super.applyEditorTo(s);
s.extraArguments = extraArgs.getText();
}
@Override
protected void resetEditorFrom(@NotNull ZigExecConfigBuild s) {
super.resetEditorFrom(s);
extraArgs.setText(Objects.requireNonNullElse(s.extraArguments, ""));
}
@Override
protected void constructPanel(Panel p) {
super.constructPanel(p);
p.row("Extra arguments", (r) -> {
r.cell(extraArgs).resizableColumn().align(AlignX.FILL).align(AlignY.FILL);
return null;
});
}
}
}

View file

@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.linemarker; package com.falsepattern.zigbrains.project.execution.build;
import com.falsepattern.zigbrains.project.execution.base.ZigTopLevelLineMarkerBase;
import com.falsepattern.zigbrains.zig.psi.ZigTypes; import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.falsepattern.zigbrains.zig.util.PsiUtil; import com.falsepattern.zigbrains.zig.util.PsiUtil;
import com.intellij.icons.AllIcons; import com.intellij.icons.AllIcons;
@ -25,7 +26,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Icon; import javax.swing.Icon;
public class ZigBuildLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase { public class ZigLineMarkerBuild extends ZigTopLevelLineMarkerBase {
public static final ZigLineMarkerBuild UTILITY_INSTANCE = new ZigLineMarkerBuild();
@Override @Override
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) { protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) { if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) {

View file

@ -1,74 +0,0 @@
/*
* 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.project.execution.configurations;
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.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import lombok.Getter;
import lombok.Setter;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigRunExecutionConfiguration extends AbstractZigExecutionConfiguration{
@Getter
@Setter
public String command = "run";
public ZigRunExecutionConfiguration(@NotNull Project project, @NotNull ConfigurationFactory factory, @Nullable String name) {
super(project, factory, name);
}
@Override
public @NotNull SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new ZigRunExecutionConfigurationEditor();
}
@Override
public @Nullable RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment)
throws ExecutionException {
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

@ -1,39 +0,0 @@
/*
* 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.project.execution.configurations;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ZigRunExecutionConfigurationFactory extends ConfigurationFactory {
public ZigRunExecutionConfigurationFactory(ZigRunExecutionConfigurationType type) {
super(type);
}
@Override
public @NotNull RunConfiguration createTemplateConfiguration(@NotNull Project project) {
return new ZigRunExecutionConfiguration(project, this, "Zig Run");
}
@Override
public @NotNull @NonNls String getId() {
return "ZIG_RUN";
}
}

View file

@ -1,40 +0,0 @@
/*
* 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.project.execution.configurations;
import com.falsepattern.zigbrains.zig.Icons;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
public class ZigRunExecutionConfigurationType extends ConfigurationTypeBase {
public static final String IDENTIFIER = "ZIG_RUN_CONFIGURATION";
public static ZigRunExecutionConfigurationType getInstance() {
return ConfigurationTypeUtil.findConfigurationType(ZigRunExecutionConfigurationType.class);
}
public ZigRunExecutionConfigurationType() {
super(IDENTIFIER, "ZigRun", "Zig Run", Icons.ZIG);
addFactory(new ZigRunExecutionConfigurationFactory(this));
}
public ConfigurationFactory getFactory() {
return getConfigurationFactories()[0];
}
}

View file

@ -1,49 +0,0 @@
/*
* 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.project.execution.configurations.ui;
import com.falsepattern.zigbrains.project.execution.configurations.AbstractZigExecutionConfiguration;
import com.falsepattern.zigbrains.project.ui.ZigCommandLinePanel;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Paths;
public abstract class AbstractZigExecutionConfigurationEditor<T extends AbstractZigExecutionConfiguration> extends
SettingsEditor<T> {
public abstract ZigCommandLinePanel getCommandLinePanel();
protected final LabeledComponent<TextFieldWithBrowseButton> workingDirectoryComponent = new WorkingDirectoryComponent();
@Override
protected void applyEditorTo(@NotNull T s) throws ConfigurationException {
s.setCommand(getCommandLinePanel().getText());
s.workingDirectory = Paths.get(workingDirectoryComponent.getComponent().getText());
}
@Override
protected void resetEditorFrom(@NotNull T s) {
getCommandLinePanel().setText(s.getCommand());
if (s.workingDirectory == null) {
workingDirectoryComponent.getComponent().setText("");
} else {
workingDirectoryComponent.getComponent().setText(s.workingDirectory.toString());
}
}
}

View file

@ -1,56 +0,0 @@
/*
* 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.project.execution.configurations.ui;
import com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfiguration;
import com.falsepattern.zigbrains.project.ui.ZigCommandLinePanel;
import com.intellij.ui.dsl.builder.AlignX;
import com.intellij.ui.dsl.builder.AlignY;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import javax.swing.JComponent;
import javax.swing.JPanel;
import static com.intellij.ui.dsl.builder.BuilderKt.panel;
public class ZigRunExecutionConfigurationEditor extends AbstractZigExecutionConfigurationEditor<ZigRunExecutionConfiguration> {
private JPanel panel = null;
@Getter
private final ZigCommandLinePanel commandLinePanel = new ZigCommandLinePanel();
@Override
protected @NotNull JComponent createEditor() {
return panel = panel((p) -> {
p.row("Run Config Command", (r) -> {
r.cell(commandLinePanel)
.resizableColumn()
.align(AlignX.FILL)
.align(AlignY.FILL);
return null;
});
p.row(workingDirectoryComponent.getLabel(), (r) -> {
r.cell(workingDirectoryComponent)
.resizableColumn()
.align(AlignX.FILL)
.align(AlignY.FILL);
return null;
});
return null;
});
}
}

View file

@ -1,42 +0,0 @@
/*
* 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.project.execution.linemarker;
import com.intellij.execution.lineMarker.RunLineMarkerContributor;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ZigAggregateLineMarkerContributor extends RunLineMarkerContributor {
private final List<RunLineMarkerContributor> contributors = List.of(
new ZigExecutableRunLineMarkerContributor(),
new ZigTestLineMarkerContributor(),
new ZigBuildLineMarkerContributor()
);
@Override
public @Nullable Info getInfo(@NotNull PsiElement element) {
for (var contributor: contributors) {
var info = contributor.getInfo(element);
if (info != null) {
return info;
}
}
return null;
}
}

View file

@ -0,0 +1,51 @@
/*
* 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.project.execution.run;
import com.falsepattern.zigbrains.project.execution.base.ConfigProducerBase;
import com.intellij.execution.actions.ConfigurationFromContext;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
public class ConfigProducerRun extends ConfigProducerBase<ZigExecConfigRun> {
@Override
public @NotNull ConfigurationFactory getConfigurationFactory() {
return ConfigTypeRun.getInstance().getConfigurationFactories()[0];
}
@Override
protected boolean setupConfigurationFromContext(@NotNull ZigExecConfigRun configuration, PsiElement element, String filePath, VirtualFile theFile) {
if (ZigLineMarkerRun.UTILITY_INSTANCE.elementMatches(element)) {
configuration.filePath = filePath;
configuration.setName(theFile.getPresentableName());
return true;
}
return false;
}
@Override
protected boolean isConfigurationFromContext(@NotNull ZigExecConfigRun configuration, String filePath, VirtualFile vFile, PsiElement element) {
return configuration.filePath.equals(filePath);
}
@Override
public boolean shouldReplace(@NotNull ConfigurationFromContext self, @NotNull ConfigurationFromContext other) {
return self.getConfigurationType() instanceof ConfigTypeRun;
}
}

View file

@ -0,0 +1,55 @@
/*
* 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.project.execution.run;
import com.falsepattern.zigbrains.zig.Icons;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ConfigTypeRun extends ConfigurationTypeBase {
public static final String IDENTIFIER = "ZIGBRAINS_RUN";
public static ConfigTypeRun getInstance() {
return ConfigurationTypeUtil.findConfigurationType(ConfigTypeRun.class);
}
public ConfigTypeRun() {
super(IDENTIFIER, "ZigRun", "Zig Run", Icons.ZIG);
addFactory(new ConfigFactoryRun());
}
public class ConfigFactoryRun extends ConfigurationFactory {
public ConfigFactoryRun() {
super(ConfigTypeRun.this);
}
@Override
public @NotNull RunConfiguration createTemplateConfiguration(@NotNull Project project) {
return new ZigExecConfigRun(project, this);
}
@Override
public @NotNull @NonNls String getId() {
return IDENTIFIER;
}
}
}

View file

@ -0,0 +1,26 @@
/*
* 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.project.execution.run;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.intellij.execution.runners.ExecutionEnvironment;
public final class ProfileStateRun extends ProfileStateBase<ZigExecConfigRun> {
public ProfileStateRun(ExecutionEnvironment environment, ZigExecConfigRun configuration) {
super(environment, configuration);
}
}

View file

@ -0,0 +1,90 @@
/*
* 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.project.execution.run;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.falsepattern.zigbrains.project.util.ElementUtil;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import lombok.Getter;
import lombok.Setter;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Setter
@Getter
public class ZigExecConfigRun extends ZigExecConfigBase<ZigExecConfigRun> {
public String filePath = "";
public ZigExecConfigRun(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Run");
}
@Override
public String[] buildCommandLineArgs() {
return new String[]{"run", filePath};
}
@Override
public @Nullable String suggestedName() {
return "Run";
}
@Override
public @NotNull Editor getConfigurationEditor() {
return new Editor();
}
@Override
public @Nullable ProfileStateRun getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
return new ProfileStateRun(environment, this);
}
@Override
public void readExternal(@NotNull Element element) throws InvalidDataException {
super.readExternal(element);
var filePath = ElementUtil.readString(element, "filePath");
if (filePath != null) {
this.filePath = filePath;
}
}
@Override
public void writeExternal(@NotNull Element element) {
super.writeExternal(element);
ElementUtil.writeString(element, "filePath", filePath);
}
public static class Editor extends ZigConfigEditor.WithFilePath<ZigExecConfigRun> {
@Override
protected String getFilePath(ZigExecConfigRun config) {
return config.filePath;
}
@Override
protected void setFilePath(ZigExecConfigRun config, String path) {
config.filePath = path;
}
}
}

View file

@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.linemarker; package com.falsepattern.zigbrains.project.execution.run;
import com.falsepattern.zigbrains.project.execution.base.ZigTopLevelLineMarkerBase;
import com.falsepattern.zigbrains.zig.psi.ZigTypes; import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.falsepattern.zigbrains.zig.util.PsiUtil; import com.falsepattern.zigbrains.zig.util.PsiUtil;
import com.intellij.icons.AllIcons; import com.intellij.icons.AllIcons;
@ -25,7 +26,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Icon; import javax.swing.Icon;
public class ZigExecutableRunLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase { public class ZigLineMarkerRun extends ZigTopLevelLineMarkerBase {
public static final ZigLineMarkerRun UTILITY_INSTANCE = new ZigLineMarkerRun();
@Override @Override
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) { protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) { if (PsiUtil.getElementType(element) != ZigTypes.IDENTIFIER) {

View file

@ -0,0 +1,52 @@
/*
* 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.project.execution.test;
import com.falsepattern.zigbrains.project.execution.base.ConfigProducerBase;
import com.falsepattern.zigbrains.project.execution.run.ConfigTypeRun;
import com.intellij.execution.actions.ConfigurationFromContext;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
public class ConfigProducerTest extends ConfigProducerBase<ZigExecConfigTest> {
@Override
public @NotNull ConfigurationFactory getConfigurationFactory() {
return ConfigTypeTest.getInstance().getConfigurationFactories()[0];
}
@Override
protected boolean setupConfigurationFromContext(@NotNull ZigExecConfigTest configuration, PsiElement element, String filePath, VirtualFile theFile) {
if (ZigLineMarkerTest.UTILITY_INSTANCE.elementMatches(element)) {
configuration.filePath = filePath;
configuration.setName("all tests in " + theFile.getPresentableName());
return true;
}
return false;
}
@Override
protected boolean isConfigurationFromContext(@NotNull ZigExecConfigTest configuration, String filePath, VirtualFile vFile, PsiElement element) {
return configuration.filePath.equals(filePath);
}
@Override
public boolean shouldReplace(@NotNull ConfigurationFromContext self, @NotNull ConfigurationFromContext other) {
return self.getConfigurationType() instanceof ConfigTypeRun;
}
}

View file

@ -0,0 +1,54 @@
/*
* 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.project.execution.test;
import com.falsepattern.zigbrains.zig.Icons;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.ConfigurationTypeBase;
import com.intellij.execution.configurations.ConfigurationTypeUtil;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class ConfigTypeTest extends ConfigurationTypeBase {
public static final String IDENTIFIER = "ZIGBRAINS_TEST";
public static ConfigTypeTest getInstance() {
return ConfigurationTypeUtil.findConfigurationType(ConfigTypeTest.class);
}
public ConfigTypeTest() {
super(IDENTIFIER, "ZigTest", "Zig Test", Icons.ZIG);
addFactory(new ConfigFactoryTest());
}
public class ConfigFactoryTest extends ConfigurationFactory {
public ConfigFactoryTest() {
super(ConfigTypeTest.this);
}
@Override
public @NotNull RunConfiguration createTemplateConfiguration(@NotNull Project project) {
return new ZigExecConfigTest(project, this);
}
@Override
public @NotNull @NonNls String getId() {
return IDENTIFIER;
}
}
}

View file

@ -0,0 +1,26 @@
/*
* 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.project.execution.test;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.intellij.execution.runners.ExecutionEnvironment;
public class ProfileStateTest extends ProfileStateBase<ZigExecConfigTest> {
public ProfileStateTest(ExecutionEnvironment environment, ZigExecConfigTest configuration) {
super(environment, configuration);
}
}

View file

@ -0,0 +1,69 @@
/*
* 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.project.execution.test;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.RunConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigExecConfigTest extends ZigExecConfigBase<ZigExecConfigTest> {
public String filePath = "";
public ZigExecConfigTest(@NotNull Project project, @NotNull ConfigurationFactory factory) {
super(project, factory, "Zig Test");
}
@Override
public String[] buildCommandLineArgs() {
return new String[]{"test", filePath};
}
@Override
public @Nullable String suggestedName() {
return "Test";
}
@Override
public @Nullable ProfileStateBase<ZigExecConfigTest> getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) {
return new ProfileStateTest(environment, this);
}
@Override
public @NotNull SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
return new Editor();
}
public static class Editor extends ZigConfigEditor.WithFilePath<ZigExecConfigTest> {
@Override
protected String getFilePath(ZigExecConfigTest config) {
return config.filePath;
}
@Override
protected void setFilePath(ZigExecConfigTest config, String path) {
config.filePath = path;
}
}
}

View file

@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.linemarker; package com.falsepattern.zigbrains.project.execution.test;
import com.falsepattern.zigbrains.project.execution.base.ZigTopLevelLineMarkerBase;
import com.falsepattern.zigbrains.zig.psi.ZigTypes; import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.falsepattern.zigbrains.zig.util.PsiUtil; import com.falsepattern.zigbrains.zig.util.PsiUtil;
import com.intellij.icons.AllIcons; import com.intellij.icons.AllIcons;
@ -25,7 +26,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.Icon; import javax.swing.Icon;
public class ZigTestLineMarkerContributor extends ZigTopLevelDeclarationLineMarkerContributorBase { public class ZigLineMarkerTest extends ZigTopLevelLineMarkerBase {
public static final ZigLineMarkerTest UTILITY_INSTANCE = new ZigLineMarkerTest();
@Override @Override
protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) { protected @Nullable PsiElement getDeclaration(@NotNull PsiElement element) {
if (PsiUtil.getElementType(element) != ZigTypes.KEYWORD_TEST) { if (PsiUtil.getElementType(element) != ZigTypes.KEYWORD_TEST) {
@ -40,6 +42,6 @@ public class ZigTestLineMarkerContributor extends ZigTopLevelDeclarationLineMark
@Override @Override
protected @NotNull Icon getIcon(@NotNull PsiElement element) { protected @NotNull Icon getIcon(@NotNull PsiElement element) {
return AllIcons.RunConfigurations.TestState.Run; return AllIcons.RunConfigurations.TestState.Run_run;
} }
} }

View file

@ -49,7 +49,8 @@ public class ZigNewProjectPanel implements Disposable {
private final List<ZigProjectTemplate> defaultTemplates = Arrays.asList( private final List<ZigProjectTemplate> defaultTemplates = Arrays.asList(
ZigDefaultTemplate.ZigExecutableTemplate.INSTANCE, ZigDefaultTemplate.ZigExecutableTemplate.INSTANCE,
ZigDefaultTemplate.ZigLibraryTemplate.INSTANCE ZigDefaultTemplate.ZigLibraryTemplate.INSTANCE,
ZigDefaultTemplate.ZigInitTemplate.INSTANCE
); );
private final DefaultListModel<ZigProjectTemplate> templateListModel = JBList.createDefaultListModel(defaultTemplates); private final DefaultListModel<ZigProjectTemplate> templateListModel = JBList.createDefaultListModel(defaultTemplates);

View file

@ -34,7 +34,7 @@ public sealed abstract class ZigDefaultTemplate extends ZigProjectTemplate {
@Override @Override
public Map<String, String> fileTemplates() { public Map<String, String> fileTemplates() {
return Map.of("main.zig", "application", return Map.of("src/main.zig", "application",
"build.zig", "application", "build.zig", "application",
"build.zig.zon", "shared"); "build.zig.zon", "shared");
} }
@ -48,9 +48,21 @@ public sealed abstract class ZigDefaultTemplate extends ZigProjectTemplate {
@Override @Override
public Map<String, String> fileTemplates() { public Map<String, String> fileTemplates() {
return Map.of("root.zig", "static", return Map.of("src/root.zig", "static",
"build.zig", "static", "build.zig", "static",
"build.zig.zon", "shared"); "build.zig.zon", "shared");
} }
} }
public static final class ZigInitTemplate extends ZigDefaultTemplate {
public static final ZigInitTemplate INSTANCE = new ZigInitTemplate();
private ZigInitTemplate() {
super("Generate using \"zig init\"", true);
}
@Override
public Map<String, String> fileTemplates() {
throw new UnsupportedOperationException();
}
}
} }

View file

@ -17,12 +17,17 @@
package com.falsepattern.zigbrains.project.platform; package com.falsepattern.zigbrains.project.platform;
import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectConfigurationData; import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectConfigurationData;
import com.falsepattern.zigbrains.project.ide.project.ZigDefaultTemplate;
import com.falsepattern.zigbrains.project.ide.util.projectwizard.ZigProjectSettingsStep; import com.falsepattern.zigbrains.project.ide.util.projectwizard.ZigProjectSettingsStep;
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService; import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
import com.falsepattern.zigbrains.zig.Icons; import com.falsepattern.zigbrains.zig.Icons;
import com.intellij.facet.ui.ValidationResult; import com.intellij.facet.ui.ValidationResult;
import com.intellij.ide.util.projectWizard.AbstractNewProjectStep; import com.intellij.ide.util.projectWizard.AbstractNewProjectStep;
import com.intellij.ide.util.projectWizard.CustomStepProjectGenerator; import com.intellij.ide.util.projectWizard.CustomStepProjectGenerator;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module; import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
@ -76,24 +81,56 @@ public class ZigDirectoryProjectGenerator implements DirectoryProjectGenerator<Z
val settings = data.settings(); val settings = data.settings();
var svc = ZigProjectSettingsService.getInstance(project); var svc = ZigProjectSettingsService.getInstance(project);
svc.getState().setToolchain(settings.toolchain()); val toolchain = settings.toolchain();
svc.getState().setToolchain(toolchain);
val template = data.selectedTemplate(); val template = data.selectedTemplate();
try { if (template instanceof ZigDefaultTemplate.ZigInitTemplate) {
WriteAction.run(() -> { if (toolchain == null) {
val srcDir = baseDir.createChildDirectory(this, "src"); Notifications.Bus.notify(new Notification("ZigBrains.Project",
"Tried to generate project with zig init, but zig toolchain is invalid!",
for (val fileTemplate : template.fileTemplates().entrySet()) { NotificationType.ERROR));
val fileName = fileTemplate.getKey(); return;
val templateDir = fileTemplate.getValue(); }
val resourceData = getResourceString("project-gen/" + templateDir + "/" + fileName + ".template"); val zig = toolchain.zig();
val targetFile = srcDir.createChildData(this, fileName); val resultOpt = zig.callWithArgs(baseDir.toNioPath(), 10000, "init");
VfsUtil.saveText(targetFile, resourceData); if (resultOpt.isEmpty()) {
} Notifications.Bus.notify(new Notification("ZigBrains.Project",
}); "Failed to invoke \"zig init\"!",
} catch (IOException e) { NotificationType.ERROR));
throw new RuntimeException(e); return;
}
val result = resultOpt.get();
if (result.getExitCode() != 0) {
Notifications.Bus.notify(new Notification("ZigBrains.Project",
"\"zig init\" failed with exit code " + result.getExitCode() + "! Check the IDE log files!",
NotificationType.ERROR));
System.err.println(result.getStderr());
}
} else {
try {
val projectName = project.getName();
WriteAction.run(() -> {
for (val fileTemplate : template.fileTemplates().entrySet()) {
var fileName = fileTemplate.getKey();
VirtualFile parentDir;
if (fileName.contains("/")) {
val slashIndex = fileName.indexOf('/');
parentDir = baseDir.createChildDirectory(this, fileName.substring(0, slashIndex));
fileName = fileName.substring(slashIndex + 1);
} else {
parentDir = baseDir;
}
val templateDir = fileTemplate.getValue();
val resourceData = getResourceString("project-gen/" + templateDir + "/" + fileName + ".template").replace("@@PROJECT_NAME@@", projectName);
val targetFile = parentDir.createChildData(this, fileName);
VfsUtil.saveText(targetFile, resourceData);
}
});
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
} }

View file

@ -1,48 +0,0 @@
/*
* 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.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

@ -1,89 +0,0 @@
/*
* 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.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.falsepattern.zigbrains.zig.lsp.ZLSEditorEventManager;
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 com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
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;
}
FileDocumentManager.getInstance().saveAllDocuments();
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,70 @@
/*
* 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.project.runconfig;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.GenericProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ZigProgramRunnerBase<ProfileState extends ProfileStateBase<?>> extends GenericProgramRunner<RunnerSettings> {
protected final String executorId;
public ZigProgramRunnerBase(String executorId) {
this.executorId = executorId;
}
@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 ProfileStateBase<?> state$$)) {
return null;
}
val state = castProfileState(state$$);
if (state == null)
return null;
val toolchain = ZigProjectSettingsService.getInstance(environment.getProject()).getToolchain();
if (toolchain == null) {
return null;
}
FileDocumentManager.getInstance().saveAllDocuments();
return doExecute(state, toolchain, environment);
}
protected abstract @Nullable ProfileState castProfileState(ProfileStateBase<?> state);
protected abstract @Nullable RunContentDescriptor doExecute(ProfileState state,
AbstractZigToolchain toolchain,
ExecutionEnvironment environment) throws ExecutionException;
}

View file

@ -16,17 +16,42 @@
package com.falsepattern.zigbrains.project.runconfig; package com.falsepattern.zigbrains.project.runconfig;
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfigBase;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.runners.DefaultProgramRunnerKt;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ZigRegularRunner extends ZigExecutableRunner{ public class ZigRegularRunner extends ZigProgramRunnerBase<ProfileStateBase<?>> {
public ZigRegularRunner() { public ZigRegularRunner() {
super(DefaultRunExecutor.EXECUTOR_ID, "Unable to run zig"); super(DefaultRunExecutor.EXECUTOR_ID);
} }
@Override @Override
public @NotNull @NonNls String getRunnerId() { public @NotNull @NonNls String getRunnerId() {
return "ZigRegularRunner"; return "ZigRegularRunner";
} }
@Override
public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) {
return this.executorId.equals(executorId) && profile instanceof ZigExecConfigBase<?>;
}
@Override
protected @Nullable ProfileStateBase<?> castProfileState(ProfileStateBase<?> state) {
return state;
}
@Override
protected @Nullable RunContentDescriptor doExecute(ProfileStateBase<?> state, AbstractZigToolchain toolchain, ExecutionEnvironment environment)
throws ExecutionException {
return DefaultProgramRunnerKt.showRunContent(state.executeCommandLine(state.getCommandLine(toolchain), environment), environment);
}
} }

View file

@ -17,7 +17,9 @@
package com.falsepattern.zigbrains.project.toolchain.tools; package com.falsepattern.zigbrains.project.toolchain.tools;
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain; import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
import com.falsepattern.zigbrains.project.util.CLIUtil;
import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.ProcessOutput;
import kotlin.text.Charsets; import kotlin.text.Charsets;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.val; import lombok.val;
@ -28,6 +30,7 @@ import java.nio.file.Path;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
@AllArgsConstructor @AllArgsConstructor
public abstract class AbstractZigTool { public abstract class AbstractZigTool {
@ -38,6 +41,11 @@ public abstract class AbstractZigTool {
return toolchain.pathToExecutable(toolName); return toolchain.pathToExecutable(toolName);
} }
public final Optional<ProcessOutput> callWithArgs(@Nullable Path workingDirectory, int timeoutMillis, String... parameters) {
return CLIUtil.execute(createBaseCommandLine(workingDirectory, parameters),
timeoutMillis);
}
protected final GeneralCommandLine createBaseCommandLine(@Nullable Path workingDirectory, protected final GeneralCommandLine createBaseCommandLine(@Nullable Path workingDirectory,
String @NotNull... parameters) { String @NotNull... parameters) {
return createBaseCommandLine(workingDirectory, Collections.emptyMap(), parameters); return createBaseCommandLine(workingDirectory, Collections.emptyMap(), parameters);

View file

@ -34,10 +34,9 @@ public class ZigCompilerTool extends AbstractZigTool{
} }
public Optional<ZigToolchainEnvironmentSerializable> getEnv(@Nullable Path workingDirectory) { public Optional<ZigToolchainEnvironmentSerializable> getEnv(@Nullable Path workingDirectory) {
return CLIUtil.execute(createBaseCommandLine(workingDirectory, "env"), return callWithArgs(workingDirectory, toolchain.executionTimeoutInMilliseconds(), "env")
toolchain.executionTimeoutInMilliseconds()) .map(ProcessOutput::getStdoutLines)
.map(ProcessOutput::getStdoutLines) .map(lines -> new Gson().fromJson(String.join(" ", lines), ZigToolchainEnvironmentSerializable.class));
.map(lines -> new Gson().fromJson(String.join(" ", lines), ZigToolchainEnvironmentSerializable.class));
} }

View file

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.falsepattern.zigbrains.project.execution.configurations.ui; package com.falsepattern.zigbrains.project.ui;
import com.intellij.execution.ExecutionBundle; import com.intellij.execution.ExecutionBundle;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;

View file

@ -16,16 +16,21 @@
package com.falsepattern.zigbrains.project.ui; package com.falsepattern.zigbrains.project.ui;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.ui.TextBrowseFolderListener;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.ui.TextAccessor; import com.intellij.ui.TextAccessor;
import com.intellij.ui.components.JBTextField; import com.intellij.ui.components.JBTextField;
import javax.swing.JPanel; import javax.swing.JPanel;
import java.awt.BorderLayout; import java.awt.BorderLayout;
public class ZigCommandLinePanel extends JPanel implements TextAccessor { public class ZigFilePathPanel extends JPanel implements TextAccessor {
private final JBTextField textField = new JBTextField(); private final TextFieldWithBrowseButton textField = new TextFieldWithBrowseButton();
public ZigCommandLinePanel() { public ZigFilePathPanel() {
super(new BorderLayout()); super(new BorderLayout());
textField.addBrowseFolderListener(
new TextBrowseFolderListener(new FileChooserDescriptor(true, false, false, false, false, false)));
add(textField, BorderLayout.CENTER); add(textField, BorderLayout.CENTER);
} }

View file

@ -15,9 +15,22 @@
--> -->
<idea-plugin package="com.falsepattern.zigbrains.project"> <idea-plugin package="com.falsepattern.zigbrains.project">
<resource-bundle>zigbrains.project.Bundle</resource-bundle>
<extensions defaultExtensionNs="com.intellij"> <extensions defaultExtensionNs="com.intellij">
<configurationType implementation="com.falsepattern.zigbrains.project.execution.configurations.ZigRunExecutionConfigurationType"/> <configurationType implementation="com.falsepattern.zigbrains.project.execution.run.ConfigTypeRun"/>
<runConfigurationProducer implementation="com.falsepattern.zigbrains.project.execution.actions.ZigRunExecutionConfigurationProducer"/> <runConfigurationProducer implementation="com.falsepattern.zigbrains.project.execution.run.ConfigProducerRun"/>
<runLineMarkerContributor language="Zig"
implementationClass="com.falsepattern.zigbrains.project.execution.run.ZigLineMarkerRun"/>
<configurationType implementation="com.falsepattern.zigbrains.project.execution.test.ConfigTypeTest"/>
<runConfigurationProducer implementation="com.falsepattern.zigbrains.project.execution.test.ConfigProducerTest"/>
<runLineMarkerContributor language="Zig"
implementationClass="com.falsepattern.zigbrains.project.execution.test.ZigLineMarkerTest"/>
<configurationType implementation="com.falsepattern.zigbrains.project.execution.build.ConfigTypeBuild"/>
<runConfigurationProducer implementation="com.falsepattern.zigbrains.project.execution.build.ConfigProducerBuild"/>
<runLineMarkerContributor language="Zig"
implementationClass="com.falsepattern.zigbrains.project.execution.build.ZigLineMarkerBuild"/>
<directoryProjectGenerator implementation="com.falsepattern.zigbrains.project.platform.ZigDirectoryProjectGenerator"/> <directoryProjectGenerator implementation="com.falsepattern.zigbrains.project.platform.ZigDirectoryProjectGenerator"/>
<newProjectWizard.language implementation="com.falsepattern.zigbrains.project.ide.newproject.ZigNewProjectWizard"/> <newProjectWizard.language implementation="com.falsepattern.zigbrains.project.ide.newproject.ZigNewProjectWizard"/>
@ -28,11 +41,14 @@
id="com.falsepattern.zigbrains.project.ide.project.ZigProjectConfigurable" id="com.falsepattern.zigbrains.project.ide.project.ZigProjectConfigurable"
displayName="Zig"/> displayName="Zig"/>
<runLineMarkerContributor language="Zig"
implementationClass="com.falsepattern.zigbrains.project.execution.linemarker.ZigAggregateLineMarkerContributor"/>
<programRunner implementation="com.falsepattern.zigbrains.project.runconfig.ZigRegularRunner" <programRunner implementation="com.falsepattern.zigbrains.project.runconfig.ZigRegularRunner"
id="ZigDebugRunner"/> id="ZigDebugRunner"/>
<notificationGroup displayType="BALLOON"
bundle="zigbrains.project.Bundle"
key="notif-zig-project"
id="ZigBrains.Project"/>
</extensions> </extensions>
<extensions defaultExtensionNs="com.falsepattern.zigbrains"> <extensions defaultExtensionNs="com.falsepattern.zigbrains">

View file

@ -16,7 +16,7 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{ const exe = b.addExecutable(.{
.name = "untitled", .name = "@@PROJECT_NAME@@",
.root_source_file = .{ .path = "src/main.zig" }, .root_source_file = .{ .path = "src/main.zig" },
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,

View file

@ -1,5 +1,5 @@
.{ .{
.name = "untitled", .name = "@@PROJECT_NAME@@",
// This is a [Semantic Version](https://semver.org/). // This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication. // In a future version of Zig it will be used for package deduplication.
.version = "0.0.0", .version = "0.0.0",
@ -43,7 +43,7 @@
// Specifies the set of files and directories that are included in this package. // Specifies the set of files and directories that are included in this package.
// Only files and directories listed here are included in the `hash` that // Only files and directories listed here are included in the `hash` that
// is computed for this package. // is computed for this package.
// Paths are relative to the build root. Use the empty string (``) to refer to // Paths are relative to the build root. Use the empty string (`""`) to refer to
// the build root itself. // the build root itself.
// A directory listed here means that all files within, recursively, are included. // A directory listed here means that all files within, recursively, are included.
.paths = .{ .paths = .{

View file

@ -4,7 +4,7 @@ const std = @import("std");
// declaratively construct a build graph that will be executed by an external // declaratively construct a build graph that will be executed by an external
// runner. // runner.
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
// Standard target options allow the person running `zig build` to choose // Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which // what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options // means any target is allowed, and the default is native. Other options
// for restricting supported target set are available. // for restricting supported target set are available.
@ -16,8 +16,8 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{}); const optimize = b.standardOptimizeOption(.{});
const lib = b.addStaticLibrary(.{ const lib = b.addStaticLibrary(.{
.name = "untitled", .name = "@@PROJECT_NAME@@",
// In this case, the main source file is merely a path, however, in more // In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file. // complicated build scripts, this could be a generated file.
.root_source_file = .{ .path = "src/root.zig" }, .root_source_file = .{ .path = "src/root.zig" },
.target = target, .target = target,

View file

@ -0,0 +1,17 @@
#
# 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.
#
notif-zig-project=Zig Project Status Notification

View file

@ -40,8 +40,10 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Comment//Documentation", ZigSyntaxHighlighter.COMMENT_DOC), new AttributesDescriptor("Comment//Documentation", ZigSyntaxHighlighter.COMMENT_DOC),
new AttributesDescriptor("Enum//Reference", ZigSyntaxHighlighter.ENUM_REF), new AttributesDescriptor("Enum//Reference", ZigSyntaxHighlighter.ENUM_REF),
new AttributesDescriptor("Enum//Declaration", ZigSyntaxHighlighter.ENUM_DECL), new AttributesDescriptor("Enum//Declaration", ZigSyntaxHighlighter.ENUM_DECL),
new AttributesDescriptor("Enum//Member", ZigSyntaxHighlighter.ENUM_MEMBER), new AttributesDescriptor("Enum//Member//Declaration", ZigSyntaxHighlighter.ENUM_MEMBER_DECL),
new AttributesDescriptor("Error tag", ZigSyntaxHighlighter.ERROR_TAG), new AttributesDescriptor("Enum//Member//Reference", ZigSyntaxHighlighter.ENUM_MEMBER_REF),
new AttributesDescriptor("Error tag//Declaration", ZigSyntaxHighlighter.ERROR_TAG_DECL),
new AttributesDescriptor("Error tag//Reference", ZigSyntaxHighlighter.ERROR_TAG_REF),
new AttributesDescriptor("Function//Declaration", ZigSyntaxHighlighter.FUNCTION_DECL), new AttributesDescriptor("Function//Declaration", ZigSyntaxHighlighter.FUNCTION_DECL),
new AttributesDescriptor("Function//Declaration//Generic", ZigSyntaxHighlighter.FUNCTION_DECL_GEN), new AttributesDescriptor("Function//Declaration//Generic", ZigSyntaxHighlighter.FUNCTION_DECL_GEN),
new AttributesDescriptor("Function//Reference", ZigSyntaxHighlighter.FUNCTION_REF), new AttributesDescriptor("Function//Reference", ZigSyntaxHighlighter.FUNCTION_REF),
@ -49,12 +51,17 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Keyword", ZigSyntaxHighlighter.KEYWORD), new AttributesDescriptor("Keyword", ZigSyntaxHighlighter.KEYWORD),
new AttributesDescriptor("Label//Declaration", ZigSyntaxHighlighter.LABEL_REF), new AttributesDescriptor("Label//Declaration", ZigSyntaxHighlighter.LABEL_REF),
new AttributesDescriptor("Label//Reference", ZigSyntaxHighlighter.LABEL_REF), new AttributesDescriptor("Label//Reference", ZigSyntaxHighlighter.LABEL_REF),
new AttributesDescriptor("Method//Declaration", ZigSyntaxHighlighter.METHOD_DECL),
new AttributesDescriptor("Method//Declaration//Generic", ZigSyntaxHighlighter.METHOD_DECL_GEN),
new AttributesDescriptor("Method//Reference", ZigSyntaxHighlighter.METHOD_REF),
new AttributesDescriptor("Method//Reference//Generic", ZigSyntaxHighlighter.METHOD_REF_GEN),
new AttributesDescriptor("Namespace//Declaration", ZigSyntaxHighlighter.NAMESPACE_DECL), new AttributesDescriptor("Namespace//Declaration", ZigSyntaxHighlighter.NAMESPACE_DECL),
new AttributesDescriptor("Namespace//Reference", ZigSyntaxHighlighter.NAMESPACE_REF), new AttributesDescriptor("Namespace//Reference", ZigSyntaxHighlighter.NAMESPACE_REF),
new AttributesDescriptor("Number", ZigSyntaxHighlighter.NUMBER), new AttributesDescriptor("Number", ZigSyntaxHighlighter.NUMBER),
new AttributesDescriptor("Operator", ZigSyntaxHighlighter.OPERATOR), new AttributesDescriptor("Operator", ZigSyntaxHighlighter.OPERATOR),
new AttributesDescriptor("Parameter", ZigSyntaxHighlighter.PARAMETER), new AttributesDescriptor("Parameter", ZigSyntaxHighlighter.PARAMETER),
new AttributesDescriptor("Property", ZigSyntaxHighlighter.PROPERTY), new AttributesDescriptor("Property//Declaration", ZigSyntaxHighlighter.PROPERTY_DECL),
new AttributesDescriptor("Property//Reference", ZigSyntaxHighlighter.PROPERTY_REF),
new AttributesDescriptor("String", ZigSyntaxHighlighter.STRING), new AttributesDescriptor("String", ZigSyntaxHighlighter.STRING),
new AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL), new AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL),
new AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF), new AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF),
@ -62,8 +69,12 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Type//Declaration//Generic", ZigSyntaxHighlighter.TYPE_DECL_GEN), new AttributesDescriptor("Type//Declaration//Generic", ZigSyntaxHighlighter.TYPE_DECL_GEN),
new AttributesDescriptor("Type//Reference", ZigSyntaxHighlighter.TYPE_REF), new AttributesDescriptor("Type//Reference", ZigSyntaxHighlighter.TYPE_REF),
new AttributesDescriptor("Type//Reference//Generic", ZigSyntaxHighlighter.TYPE_REF_GEN), new AttributesDescriptor("Type//Reference//Generic", ZigSyntaxHighlighter.TYPE_REF_GEN),
new AttributesDescriptor("Type parameter//Reference", ZigSyntaxHighlighter.TYPE_PARAM),
new AttributesDescriptor("Type parameter//Declaration", ZigSyntaxHighlighter.TYPE_PARAM_DECL),
new AttributesDescriptor("Variable//Declaration", ZigSyntaxHighlighter.VARIABLE_DECL), new AttributesDescriptor("Variable//Declaration", ZigSyntaxHighlighter.VARIABLE_DECL),
new AttributesDescriptor("Variable//Declaration//Deprecated", ZigSyntaxHighlighter.VARIABLE_DECL_DEPR),
new AttributesDescriptor("Variable//Reference", ZigSyntaxHighlighter.VARIABLE_REF), new AttributesDescriptor("Variable//Reference", ZigSyntaxHighlighter.VARIABLE_REF),
new AttributesDescriptor("Variable//Reference//Deprecated", ZigSyntaxHighlighter.VARIABLE_REF_DEPR),
}; };
@Nullable @Nullable
@ -86,18 +97,18 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
const <ns>std</ns> = @import("std"); const <ns>std</ns> = @import("std");
const <enumDecl>AnEnum</enumDecl> = enum { const <enumDecl>AnEnum</enumDecl> = enum {
<enumMember>A</enumMember>, <enumMemberDecl>A</enumMemberDecl>,
<enumMember>B</enumMember>, <enumMemberDecl>B</enumMemberDecl>,
<enumMember>C</enumMember>, <enumMemberDecl>C</enumMemberDecl>,
}; };
const <structDecl>AStruct</structDecl> = struct { const <structDecl>AStruct</structDecl> = struct {
<property>fieldA</property>: <type>u32</type>, <propertyDecl>fieldA</propertyDecl>: <type>u32</type>,
<property>fieldB</property>: <type>u16</type> <propertyDecl>fieldB</propertyDecl>: <type>u16</type>
}; };
const <typeDecl>AnErrorType</typeDecl> = error { const <typeDecl>AnErrorType</typeDecl> = error {
<etag>SomeError</etag> <etagDecl>SomeError</etagDecl>
}; };
pub fn <fn>main</fn>() <type>AnError</type>.SomeError!<type>void</type> { pub fn <fn>main</fn>() <type>AnError</type>.SomeError!<type>void</type> {
@ -107,24 +118,24 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
// stdout is for the actual output of your application, for example if you // stdout is for the actual output of your application, for example if you
// are implementing gzip, then only the compressed bytes should be sent to // are implementing gzip, then only the compressed bytes should be sent to
// stdout, not any debugging messages. // stdout, not any debugging messages.
const <varDecl>stdout_file</varDecl> = <ns>std</ns>.<ns>io</ns>.<fn>getStdOut</fn>().<fn>writer</fn>(); const <varDecl>stdout_file</varDecl> = <ns>std</ns>.<ns>io</ns>.<fn>getStdOut</fn>().<md>writer</md>();
var <varDecl>bw</varDecl> = <ns>std</ns>.<ns>io</ns>.<fn>bufferedWriter</fn>(<var>stdout_file</var>); var <varDecl>bw</varDecl> = <ns>std</ns>.<ns>io</ns>.<fn>bufferedWriter</fn>(<var>stdout_file</var>);
const <varDecl>stdout</varDecl> = <var>bw</var>.<fn>writer</fn>(); const <varDecl>stdout</varDecl> = <var>bw</var>.<md>writer</md>();
try <var>stdout</var>.<fn>print</fn>(\\\\Run `zig build test` to run the tests. try <var>stdout</var>.<md>print</md>(\\\\Run `zig build test` to run the tests.
\\\\ \\\\
, .{}); , .{});
_ = <enum>AnEnum</enum>.<enumMember>A</enumMember>; _ = <enum>AnEnum</enum>.<enumMember>A</enumMember>;
try <var>bw</var>.<fn>flush</fn>(); // don't forget to flush! try <var>bw</var>.<md>flush</md>(); // don't forget to flush!
} }
test "simple test" { test "simple test" {
var <varDecl>list</varDecl> = <ns>std</ns>.<type>ArrayList</type>(<type>i32</type>).<fn>init</fn>(<ns>std</ns>.<ns>testing</ns>.<type>allocator</type>); var <varDecl>list</varDecl> = <ns>std</ns>.<type>ArrayList</type>(<type>i32</type>).<md>init</md>(<ns>std</ns>.<ns>testing</ns>.<type>allocator</type>);
defer <var>list</var>.<fn>deinit</fn>(); // try commenting this out and see if zig detects the memory leak! defer <var>list</var>.<md>deinit</md>(); // try commenting this out and see if zig detects the memory leak!
try <var>list</var>.<fn>append</fn>(42); try <var>list</var>.<md>append</md>(42);
try <ns>std</ns>.<ns>testing</ns>.<fn>expectEqual</fn>(@as(i32, 42), <var>list</var>.<fn>pop</fn>()); try <ns>std</ns>.<ns>testing</ns>.<fn>expectEqual</fn>(@as(i32, 42), <var>list</var>.<md>pop</md>());
} }
"""; """;
} }
@ -132,17 +143,20 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
private static final Map<String, TextAttributesKey> ADD_HIGHLIGHT = new HashMap<>(); private static final Map<String, TextAttributesKey> ADD_HIGHLIGHT = new HashMap<>();
static { static {
ADD_HIGHLIGHT.put("typeDecl", ZigSyntaxHighlighter.TYPE_DECL); ADD_HIGHLIGHT.put("typeDecl", ZigSyntaxHighlighter.TYPE_DECL);
ADD_HIGHLIGHT.put("etag", ZigSyntaxHighlighter.ERROR_TAG); ADD_HIGHLIGHT.put("etagDecl", ZigSyntaxHighlighter.ERROR_TAG_DECL);
ADD_HIGHLIGHT.put("struct", ZigSyntaxHighlighter.STRUCT_REF); ADD_HIGHLIGHT.put("struct", ZigSyntaxHighlighter.STRUCT_REF);
ADD_HIGHLIGHT.put("enum", ZigSyntaxHighlighter.ENUM_REF); ADD_HIGHLIGHT.put("enum", ZigSyntaxHighlighter.ENUM_REF);
ADD_HIGHLIGHT.put("enumDecl", ZigSyntaxHighlighter.ENUM_DECL); ADD_HIGHLIGHT.put("enumDecl", ZigSyntaxHighlighter.ENUM_DECL);
ADD_HIGHLIGHT.put("enumMember", ZigSyntaxHighlighter.ENUM_MEMBER); ADD_HIGHLIGHT.put("enumMember", ZigSyntaxHighlighter.ENUM_MEMBER_REF);
ADD_HIGHLIGHT.put("enumMemberDecl", ZigSyntaxHighlighter.ENUM_MEMBER_DECL);
ADD_HIGHLIGHT.put("varDecl", ZigSyntaxHighlighter.VARIABLE_DECL); ADD_HIGHLIGHT.put("varDecl", ZigSyntaxHighlighter.VARIABLE_DECL);
ADD_HIGHLIGHT.put("property", ZigSyntaxHighlighter.PROPERTY); ADD_HIGHLIGHT.put("propertyDecl", ZigSyntaxHighlighter.PROPERTY_DECL);
ADD_HIGHLIGHT.put("structDecl", ZigSyntaxHighlighter.STRUCT_DECL);
ADD_HIGHLIGHT.put("var", ZigSyntaxHighlighter.VARIABLE_REF); ADD_HIGHLIGHT.put("var", ZigSyntaxHighlighter.VARIABLE_REF);
ADD_HIGHLIGHT.put("ns", ZigSyntaxHighlighter.NAMESPACE_REF); ADD_HIGHLIGHT.put("ns", ZigSyntaxHighlighter.NAMESPACE_REF);
ADD_HIGHLIGHT.put("type", ZigSyntaxHighlighter.TYPE_REF); ADD_HIGHLIGHT.put("type", ZigSyntaxHighlighter.TYPE_REF);
ADD_HIGHLIGHT.put("fn", ZigSyntaxHighlighter.FUNCTION_REF); ADD_HIGHLIGHT.put("fn", ZigSyntaxHighlighter.FUNCTION_REF);
ADD_HIGHLIGHT.put("md", ZigSyntaxHighlighter.METHOD_REF);
} }
@Nullable @Nullable

View file

@ -41,9 +41,12 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
COMMENT_DOC = createKey("COMMENT_DOC" , DefaultLanguageHighlighterColors.DOC_COMMENT ), COMMENT_DOC = createKey("COMMENT_DOC" , DefaultLanguageHighlighterColors.DOC_COMMENT ),
ENUM_DECL = createKey("ENUM_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME ), ENUM_DECL = createKey("ENUM_DECL" , DefaultLanguageHighlighterColors.CLASS_NAME ),
ENUM_REF = createKey("ENUM" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ), ENUM_REF = createKey("ENUM" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ),
ENUM_MEMBER = createKey("ENUM_MEMBER" , DefaultLanguageHighlighterColors.STATIC_FIELD ), ENUM_MEMBER_DECL = createKey("ENUM_MEMBER_DECL" , DefaultLanguageHighlighterColors.STATIC_FIELD ),
ERROR_TAG = createKey("ERROR_TAG" , DefaultLanguageHighlighterColors.STATIC_FIELD ), ENUM_MEMBER_REF = createKey("ENUM_MEMBER" , ENUM_MEMBER_DECL ),
PROPERTY = createKey("PROPERTY" , DefaultLanguageHighlighterColors.INSTANCE_FIELD ), ERROR_TAG_DECL = createKey("ERROR_TAG_DECL" , DefaultLanguageHighlighterColors.STATIC_FIELD ),
ERROR_TAG_REF = createKey("ERROR_TAG" , ERROR_TAG_DECL ),
PROPERTY_DECL = createKey("PROPERTY_DECL" , DefaultLanguageHighlighterColors.INSTANCE_FIELD ),
PROPERTY_REF = createKey("PROPERTY" , PROPERTY_DECL ),
FUNCTION_DECL = createKey("FUNCTION_DECL" , DefaultLanguageHighlighterColors.FUNCTION_DECLARATION), FUNCTION_DECL = createKey("FUNCTION_DECL" , DefaultLanguageHighlighterColors.FUNCTION_DECLARATION),
FUNCTION_DECL_GEN = createKey("FUNCTION_DECL_GEN" , FUNCTION_DECL ), FUNCTION_DECL_GEN = createKey("FUNCTION_DECL_GEN" , FUNCTION_DECL ),
FUNCTION_REF = createKey("FUNCTION" , DefaultLanguageHighlighterColors.FUNCTION_CALL ), FUNCTION_REF = createKey("FUNCTION" , DefaultLanguageHighlighterColors.FUNCTION_CALL ),
@ -51,6 +54,10 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
KEYWORD = createKey("KEYWORD" , DefaultLanguageHighlighterColors.KEYWORD ), KEYWORD = createKey("KEYWORD" , DefaultLanguageHighlighterColors.KEYWORD ),
LABEL_DECL = createKey("LABEL_DECL" , DefaultLanguageHighlighterColors.LABEL ), LABEL_DECL = createKey("LABEL_DECL" , DefaultLanguageHighlighterColors.LABEL ),
LABEL_REF = createKey("LABEL" , LABEL_DECL ), LABEL_REF = createKey("LABEL" , LABEL_DECL ),
METHOD_DECL = createKey("METHOD_DECL" , FUNCTION_DECL ),
METHOD_DECL_GEN = createKey("METHOD_DECL_GEN" , METHOD_DECL ),
METHOD_REF = createKey("METHOD" , FUNCTION_REF ),
METHOD_REF_GEN = createKey("METHOD_GEN" , METHOD_REF ),
NAMESPACE_DECL = createKey("NAMESPACE_DECL" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ), NAMESPACE_DECL = createKey("NAMESPACE_DECL" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ),
NAMESPACE_REF = createKey("NAMESPACE" , DefaultLanguageHighlighterColors.CLASS_NAME ), NAMESPACE_REF = createKey("NAMESPACE" , DefaultLanguageHighlighterColors.CLASS_NAME ),
NUMBER = createKey("NUMBER" , DefaultLanguageHighlighterColors.NUMBER ), NUMBER = createKey("NUMBER" , DefaultLanguageHighlighterColors.NUMBER ),
@ -63,8 +70,12 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
TYPE_DECL_GEN = createKey("TYPE_DECL_GEN" , TYPE_DECL ), TYPE_DECL_GEN = createKey("TYPE_DECL_GEN" , TYPE_DECL ),
TYPE_REF = createKey("TYPE" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ), TYPE_REF = createKey("TYPE" , DefaultLanguageHighlighterColors.CLASS_REFERENCE ),
TYPE_REF_GEN = createKey("TYPE_GEN" , TYPE_REF ), TYPE_REF_GEN = createKey("TYPE_GEN" , TYPE_REF ),
TYPE_PARAM = createKey("TYPE_PARAM" , TYPE_REF ),
TYPE_PARAM_DECL = createKey("TYPE_PARAM_DECL" , TYPE_PARAM ),
VARIABLE_DECL = createKey("VARIABLE_DECL" , DefaultLanguageHighlighterColors.LOCAL_VARIABLE ), VARIABLE_DECL = createKey("VARIABLE_DECL" , DefaultLanguageHighlighterColors.LOCAL_VARIABLE ),
VARIABLE_REF = createKey("VARIABLE" , VARIABLE_DECL ); VARIABLE_DECL_DEPR= createKey("VARIABLE_DECL_DEPR" , VARIABLE_DECL ),
VARIABLE_REF = createKey("VARIABLE" , VARIABLE_DECL ),
VARIABLE_REF_DEPR = createKey("VARIABLE_REF_DEPL" , VARIABLE_REF );
// @formatter:on // @formatter:on
private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0]; private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];
private static final Map<IElementType, TextAttributesKey[]> KEYMAP = new HashMap<>(); private static final Map<IElementType, TextAttributesKey[]> KEYMAP = new HashMap<>();

View file

@ -16,11 +16,17 @@
package com.falsepattern.zigbrains.zig.ide; package com.falsepattern.zigbrains.zig.ide;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.TextAttributesKey;
import kotlin.Pair;
import lombok.val;
import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.Unmodifiable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -28,24 +34,36 @@ import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.BU
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.COMMENT; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.COMMENT;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.COMMENT_DOC; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.COMMENT_DOC;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_MEMBER; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_MEMBER_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_MEMBER_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ENUM_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ERROR_TAG; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ERROR_TAG_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.ERROR_TAG_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.FUNCTION_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.FUNCTION_DECL_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.FUNCTION_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.FUNCTION_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.FUNCTION_REF_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.KEYWORD; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.KEYWORD;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.LABEL_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.LABEL_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.LABEL_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.LABEL_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.METHOD_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.METHOD_DECL_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.METHOD_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.METHOD_REF_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NAMESPACE_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NAMESPACE_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NAMESPACE_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NAMESPACE_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NUMBER; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.NUMBER;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.OPERATOR; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.OPERATOR;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.PARAMETER; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.PARAMETER;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.PROPERTY; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.PROPERTY_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.PROPERTY_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRING; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRING;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRUCT_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRUCT_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRUCT_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.STRUCT_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_DECL_GEN; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_DECL_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_PARAM;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_PARAM_DECL;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_REF; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_REF;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_REF_GEN; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.TYPE_REF_GEN;
import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.VARIABLE_DECL; import static com.falsepattern.zigbrains.zig.highlighter.ZigSyntaxHighlighter.VARIABLE_DECL;
@ -58,17 +76,24 @@ public enum ZigAttributes {
Comment(COMMENT), Comment(COMMENT),
Enum_Decl(ENUM_DECL, "declaration"), Enum_Decl(ENUM_DECL, "declaration"),
Enum(ENUM_REF), Enum(ENUM_REF),
EnumMember(ENUM_MEMBER), EnumMember_Decl(ENUM_MEMBER_DECL, "declaration"),
ErrorTag(ERROR_TAG), EnumMember(ENUM_MEMBER_REF),
Property(PROPERTY), ErrorTag_Decl(ERROR_TAG_DECL, "declaration"),
Function_Decl_Gen(FUNCTION_REF, "declaration", "generic"), ErrorTag(ERROR_TAG_REF),
Function_Decl(FUNCTION_REF, "declaration"), Property_Decl(PROPERTY_DECL, "declaration"),
Function_Gen(FUNCTION_REF, "generic"), Property(PROPERTY_REF),
Function_Decl_Gen(FUNCTION_DECL_GEN, "declaration", "generic"),
Function_Decl(FUNCTION_DECL, "declaration"),
Function_Gen(FUNCTION_REF_GEN, "generic"),
Function(FUNCTION_REF), Function(FUNCTION_REF),
Keyword(KEYWORD), Keyword(KEYWORD),
KeywordLiteral(KEYWORD), KeywordLiteral(KEYWORD),
Label_Decl(LABEL_DECL, "declaration"), Label_Decl(LABEL_DECL, "declaration"),
Label(LABEL_REF), Label(LABEL_REF),
Method_Decl_Gen(METHOD_DECL_GEN, "declaration", "generic"),
Method_Decl(METHOD_DECL, "declaration"),
Method_Gen(METHOD_REF_GEN, "generic"),
Method(METHOD_REF),
Namespace_Decl(NAMESPACE_DECL, "declaration"), Namespace_Decl(NAMESPACE_DECL, "declaration"),
Namespace(NAMESPACE_REF), Namespace(NAMESPACE_REF),
Number(NUMBER), Number(NUMBER),
@ -82,7 +107,11 @@ public enum ZigAttributes {
Type_Decl(TYPE_DECL, "declaration"), Type_Decl(TYPE_DECL, "declaration"),
Type_Gen(TYPE_REF_GEN, "generic"), Type_Gen(TYPE_REF_GEN, "generic"),
Type(TYPE_REF), Type(TYPE_REF),
TypeParameter_Decl(TYPE_PARAM_DECL, "declaration"),
TypeParameter(TYPE_PARAM),
Variable_Decl_Depr(VARIABLE_DECL, "declaration", "deprecated"),
Variable_Decl(VARIABLE_DECL, "declaration"), Variable_Decl(VARIABLE_DECL, "declaration"),
Variable_Depr(VARIABLE_REF, "deprecated"),
Variable(VARIABLE_REF), Variable(VARIABLE_REF),
; ;
public final TextAttributesKey KEY; public final TextAttributesKey KEY;
@ -97,13 +126,45 @@ public enum ZigAttributes {
this.modifiers = new HashSet<>(List.of(modifiers)); this.modifiers = new HashSet<>(List.of(modifiers));
} }
private static final Map<String, List<ZigAttributes>> types = new HashMap<>();
static {
for (val known: values()) {
types.computeIfAbsent(known.type, (ignored) -> new ArrayList<>()).add(known);
}
}
private static final Logger LOG = Logger.getInstance(ZigAttributes.class);
private static final Set<Pair<String, Set<String>>> warnedUnknowns = new HashSet<>();
private static void complainAboutUnknownCombo(String type, Set<String> modifiers) {
val thePair = new Pair<>(type, modifiers);
synchronized (warnedUnknowns) {
if (warnedUnknowns.contains(thePair))
return;
warnedUnknowns.add(thePair);
LOG.warn("Unrecognized semantic token! type " + type + ", modifiers: " + modifiers);
}
}
public static Optional<TextAttributesKey> getKey(String type, Set<String> modifiers) { public static Optional<TextAttributesKey> getKey(String type, Set<String> modifiers) {
if (type == null) { if (type == null) {
return Optional.empty(); return Optional.empty();
} }
for (var known : values()) { if (!types.containsKey(type)) {
if (known.type.equals(type) && ((modifiers != null && modifiers.containsAll(known.modifiers)) || complainAboutUnknownCombo(type, modifiers);
(modifiers == null && known.modifiers.size() == 0))) { return Optional.empty();
}
val values = types.get(type);
for (var known : values) {
if ((modifiers != null && modifiers.equals(known.modifiers)) ||
(modifiers == null && known.modifiers.isEmpty())) {
return Optional.of(known.KEY);
}
}
complainAboutUnknownCombo(type, modifiers);
//Fallback with weaker matching
for (var known : values) {
if ((modifiers != null && modifiers.containsAll(known.modifiers)) ||
(modifiers == null && known.modifiers.isEmpty())) {
return Optional.of(known.KEY); return Optional.of(known.KEY);
} }
} }

View file

@ -118,7 +118,7 @@ public class ZLSEditorEventManager extends EditorEventManager {
return () -> { return () -> {
run.run(); run.run();
if (!editor.isDisposed()) { if (!editor.isDisposed()) {
ApplicationManager.getApplication().invokeLater(() -> HighlightingUtil.refreshHighlighting(this)); HighlightingUtil.refreshHighlighting(this);
} }
}; };
} }

View file

@ -23,6 +23,7 @@ import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.editor.markup.HighlighterLayer; import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
import lombok.val;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
@ -61,14 +62,15 @@ public class HighlightingUtil {
.map(hl -> Map.entry(hl, hl.getStartOffset())) .map(hl -> Map.entry(hl, hl.getStartOffset()))
.sorted(Comparator.comparingInt(Map.Entry::getValue)) .sorted(Comparator.comparingInt(Map.Entry::getValue))
.toList()); .toList());
app.invokeLater(() -> { val writes = new ArrayList<Runnable>();
app.runReadAction(() -> {
if (editor.isDisposed()) { if (editor.isDisposed()) {
return; return;
} }
if (highlightRanges.size() == 1 && if (highlightRanges.size() == 1 &&
highlightRanges.get(0).start() == 0 && highlightRanges.get(0).start() == 0 &&
highlightRanges.get(0).remove() == -1) { highlightRanges.get(0).remove() == -1) {
markup.removeAllHighlighters(); writes.add(markup::removeAllHighlighters);
} }
var documentLength = editor.getDocument().getTextLength(); var documentLength = editor.getDocument().getTextLength();
for (var range : highlightRanges) { for (var range : highlightRanges) {
@ -80,7 +82,8 @@ public class HighlightingUtil {
if (hl.getValue() >= start) { if (hl.getValue() >= start) {
for (int j = 0; j < toRemove; j++) { for (int j = 0; j < toRemove; j++) {
highlightersSorted.remove(i); highlightersSorted.remove(i);
markup.removeHighlighter(hl.getKey()); val key = hl.getKey();
writes.add(() -> markup.removeHighlighter(key));
} }
} }
} }
@ -91,10 +94,14 @@ public class HighlightingUtil {
if (end > documentLength || editStart > documentLength) { if (end > documentLength || editStart > documentLength) {
continue; continue;
} }
markup.addRangeHighlighter(edit.color(), editStart, end, HighlighterLayer.ADDITIONAL_SYNTAX, val color = edit.color();
HighlighterTargetArea.EXACT_RANGE); writes.add(() -> markup.addRangeHighlighter(color, editStart, end, HighlighterLayer.ADDITIONAL_SYNTAX, HighlighterTargetArea.EXACT_RANGE));
} }
} }
app.invokeLater(() -> {
for (val write: writes)
write.run();
});
}); });
}); });
} }