backport: 15.0.0
This commit is contained in:
parent
b036233f60
commit
403d18f0fb
63 changed files with 1466 additions and 623 deletions
|
@ -17,10 +17,15 @@ Changelog structure reference:
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [14.5.0]
|
||||
## [15.0.0]
|
||||
|
||||
### Changed
|
||||
|
||||
- Debugging
|
||||
- Major update, debugging on linux now works outside CLion (confirmed working in RustRover, IDEA Ultimate)
|
||||
- Windows debugging has been made much more streamlined, user doesn't need to download random files manually anymore
|
||||
(except the visual studio debugging sdk of course)
|
||||
- debugging support on macOS with LLDB
|
||||
- Project
|
||||
- Updated new project templates to the latest Zig 0.13.0 init files
|
||||
|
||||
|
|
4
LICENSE
4
LICENSE
|
@ -34,7 +34,11 @@ These art assets are licensed under Creative Commons Attribution-ShareAlike 4.0
|
|||
Parts of the codebase are based on the intellij-zig plugin,
|
||||
developed by HTGAzureX1212 (https://github.com/HTGAzureX1212), licensed under the Apache 2.0 license.
|
||||
--------------------------------
|
||||
Parts of the codebase are based on the intellij-rust plugin,
|
||||
developed by the intellij-rust team (https://github.com/intellij-rust), licensed under the intellij-rust MIT license.
|
||||
--------------------------------
|
||||
|
||||
All of the licenses listed here are available in the following files, bundled with the plugin:
|
||||
- licenses/APACHE_2.0.LICENSE
|
||||
- licenses/CC_BY_SA_4.0.LICENSE
|
||||
- licenses/INTELLIJ-RUST.LICENSE
|
50
README.md
50
README.md
|
@ -19,7 +19,6 @@ through the built-in plugin browser:
|
|||
- `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml
|
||||
- `2023.3.*`: https://falsepattern.com/zigbrains/updatePlugins-233.xml
|
||||
- `2023.2.*`: https://falsepattern.com/zigbrains/updatePlugins-232.xml
|
||||
- `2023.1.*`: https://falsepattern.com/zigbrains/updatePlugins-231.xml
|
||||
4. Click `OK`, and your IDE should now automatically detect the latest version
|
||||
(both in the Installed tab and in the Marketplace tab), even if it's not yet verified on the official JetBrains marketplace yet.
|
||||
|
||||
|
@ -37,14 +36,18 @@ complain about missing files
|
|||
## Special Thanks
|
||||
|
||||
- The [ZigTools](https://github.com/zigtools/) team for developing the Zig Language Server.
|
||||
|
||||
- [HTGAzureX1212](https://github.com/HTGAzureX1212) for developing [intellij-zig](https://github.com/intellij-zig/intellij-zig),
|
||||
which served as a fantastic reference for deep IDE integration features
|
||||
which served as a fantastic reference for deep IDE integration features.
|
||||
|
||||
- The members of the `Zig Programming Language` discord server's `#tooling-dev` channel for providing encouragement,
|
||||
feedback, and lots of bug reports.
|
||||
|
||||
- The Ballerina Platform developers for `lsp4intellij`, the language server connector between the IntelliJ platform
|
||||
and the Eclipse LSP4J project
|
||||
and the Eclipse LSP4J project.
|
||||
|
||||
- The developers of the [intellij-rust](https://github.com/intellij-rust/intellij-rust/) plugin for providing an
|
||||
excellent example on how to write debugger support that doesn't depend on CLion.
|
||||
|
||||
- All the people who have generously funded the project
|
||||
- gree7
|
||||
|
@ -67,7 +70,7 @@ Z - Patch version, incremented only when a fix is purely an internal change and
|
|||
of complexity (determined at the discretion of FalsePattern)
|
||||
|
||||
Note: before version 11, the version scheme used was 0.X.Y, without separate patch versions.
|
||||
As this plugin will constantly be evolving together with the zig language, it makes not sense to keep the 0 prefix,
|
||||
As this plugin will constantly be evolving together with the zig language, it makes no sense to keep the 0 prefix,
|
||||
and might as well utilize the full semver string for extra information.
|
||||
|
||||
# Description
|
||||
|
@ -95,32 +98,37 @@ LSP server is running.
|
|||
|
||||
## Debugging
|
||||
|
||||
### Note
|
||||
Debugging on Linux/MacOS/Unix is only available in CLion, as ZigBrains depends on the C++ toolchains system.
|
||||
Debugger settings are available in the `Settings | Build, Execution, Deployment | Debugger` menu, under the `Zig` section.
|
||||
|
||||
On Windows, debugging is also available with the help of the
|
||||
[Native Debugging Support](https://plugins.jetbrains.com/plugin/12775-native-debugging-support), which is unfortunately
|
||||
only compatible with paid IDEs.
|
||||
### IDE Compatibility
|
||||
Debugging Zig code is supported in any native debugging capable IDE. The following have been verified to work so far:
|
||||
|
||||
- CLion
|
||||
- IntelliJ IDEA Ultimate
|
||||
- RustRover (including the non-commercial free version too)
|
||||
- GoLand
|
||||
- PyCharm Professional
|
||||
|
||||
Additionally, in CLion, the plugin uses the C++ Toolchains for sourcing the debugger (this can be toggled off in the settings).
|
||||
|
||||
The open-source Community edition IDEs don't have the native debugging code as it's a proprietary module, so you cannot
|
||||
debug zig code with them. You can still use those IDEs to develop code and use everything else the plugin has to offer.
|
||||
|
||||
### Windows
|
||||
|
||||
Due to technical limitations, the C++ toolchains cannot be used for debugging zig code on windows.
|
||||
Supported debuggers: `MSVC`
|
||||
|
||||
Go to `Settings | Build, Execution, Deployment | Debugger | Zig (Windows)` and follow the steps shown there to set up a
|
||||
zig-compatible debugger.
|
||||
Debugging on Windows requires you to set up the Microsoft debugger.
|
||||
|
||||
### Linux / MacOS / Unix
|
||||
To do this, go to the following URL and install the MSVC compiler toolset according to step 3 in the prerequisites:
|
||||
https://code.visualstudio.com/docs/cpp/config-msvc
|
||||
|
||||
ZigBrains uses the CLion C++ toolchains `Settings | Build, Execution, Deployment | Toolchains` for debugging purposes,
|
||||
and it is fully compatible with both GDB and LLDB debuggers.
|
||||
### Linux
|
||||
|
||||
Additionally, ZigBrains will prioritize a toolchain if it is called `Zig`, otherwise it will use the default toolchain.
|
||||
Supported debuggers: `LLDB`, `GDB`
|
||||
|
||||
If no toolchain is available, ZigBrains will attempt to use the bundled LLDB debugger, and if that is not available either,
|
||||
an error popup will be shown when you try to run with debugging.
|
||||
### MacOS
|
||||
|
||||
Note: There is a small issue with the LLDB debugger which does not happen with GDB: The debugger will pause on the first
|
||||
instruction (usually, deep inside the zig standard library's startup code). Unfortunately, we have not found a fix for
|
||||
this yet, but fortunately it doesn't break anything, just a bit of inconvenience.
|
||||
Supported debuggers: `LLDB`
|
||||
|
||||
<!-- Plugin description end -->
|
||||
|
|
2
build.sh
2
build.sh
|
@ -15,7 +15,7 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
declare -a branches=("master" "241" "233" "232" "231")
|
||||
declare -a branches=("master" "241" "233" "232")
|
||||
|
||||
DEFAULT_BRANCH="${branches[0]}"
|
||||
|
||||
|
|
22
licenses/INTELLIJ-RUST.LICENSE
Normal file
22
licenses/INTELLIJ-RUST.LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Aleksey Kladov, Evgeny Kurbatsky, Alexey Kudinkin and contributors
|
||||
Copyright (c) 2016 JetBrains
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,19 @@
|
|||
package com.falsepattern.zigbrains;
|
||||
|
||||
|
||||
import com.intellij.DynamicBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
public class ZigBundle extends DynamicBundle {
|
||||
public static final String BUNDLE = "zigbrains.Bundle";
|
||||
public static final ZigBundle INSTANCE = new ZigBundle();
|
||||
private ZigBundle() {
|
||||
super(BUNDLE);
|
||||
}
|
||||
|
||||
@Nls
|
||||
public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
|
||||
return INSTANCE.getMessage(key, params);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.falsepattern.zigbrains.common;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Evil hack for bypassing plugin verifier restrictions via generics. Unfortunately this is necessary due to public api limitations.
|
||||
*/
|
||||
public record ObjectHolder<T>(@NotNull T value) {
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.falsepattern.zigbrains.common;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class ZigPathManager {
|
||||
public static Path pluginDirInSystem() {
|
||||
return PathManager.getSystemDir().resolve("zigbrains");
|
||||
}
|
||||
|
||||
public static Path tempPluginDirInSystem() {
|
||||
return Paths.get(PathManager.getTempPath()).resolve("zigbrains");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
inlayprovider=ZLS Inlay Provider
|
||||
notif-zb=ZigBrains general notification
|
||||
notif-zig-project=Zig project notification
|
||||
notif-zls-error=ZLS error notification
|
||||
notif-debug-info=ZigBrains debugger info
|
||||
notif-debug-warn=ZigBrains debugger warning
|
||||
notif-debug-error=ZigBrains debugger error
|
||||
dialog.title.download.debugger=Download Debugger
|
||||
notification.nativedebug.title=Zig native debugger
|
||||
notification.nativedebug.text=You need to install the "Native Debugging Support" plugin for Zig debugging in this IDE!
|
||||
notification.nativedebug.market=Install from Marketplace
|
||||
notification.nativedebug.browser=Open in Browser
|
||||
notification.title.debugger=Debugger
|
||||
notification.content.debugger.successfully.downloaded=Debugger successfully downloaded
|
||||
notification.content.debugger.downloading.failed=Debugger downloading failed
|
||||
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed
|
||||
settings.debugger.toolchain.download.debugger.automatically.checkbox=Download and update the debugger automatically
|
||||
settings.debugger.title=Zig
|
||||
settings.debugger.toolchain.debugger.label=Debugger:
|
||||
settings.debugger.toolchain.download.comment=Need to be <a>downloaded</a>
|
||||
settings.debugger.toolchain.update.comment=Need to be <a>updated</a>
|
||||
settings.debugger.toolchain.use.clion.toolchains=Use Clion toolchains instead
|
||||
notification.content.debugger.need.download=You need to download/update the debugger before you can run debugging! (Settings | Build, Execution, Deployment | Debugging -> Zig)
|
||||
unable.to.run.debugger=Unable to Run Debugger
|
|
@ -14,11 +14,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.falsepattern.zigbrains.cpp;
|
||||
package com.falsepattern.zigbrains.clion;
|
||||
|
||||
import com.falsepattern.zigbrains.debugbridge.DebuggerDriverProvider;
|
||||
import com.falsepattern.zigbrains.common.ObjectHolder;
|
||||
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProvider;
|
||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.jetbrains.cidr.cpp.execution.debugger.backend.CLionGDBDriverConfiguration;
|
||||
import com.jetbrains.cidr.cpp.execution.debugger.backend.CLionLLDBDriverConfiguration;
|
||||
import com.jetbrains.cidr.cpp.toolchains.CPPToolchains;
|
||||
|
@ -26,10 +29,17 @@ import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
|
|||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CPPDebuggerDriverProvider implements DebuggerDriverProvider {
|
||||
private static final Logger LOG = Logger.getInstance(CPPDebuggerDriverProvider.class);
|
||||
public class ZigClionDebuggerDriverConfigurationProvider implements ZigDebuggerDriverConfigurationProvider {
|
||||
private static final Logger LOG = Logger.getInstance(ZigClionDebuggerDriverConfigurationProvider.class);
|
||||
|
||||
@Override
|
||||
public @Nullable DebuggerDriverConfiguration getDebuggerConfiguration(Project project) {
|
||||
public @Nullable ObjectHolder<DebuggerDriverConfiguration> getDebuggerConfiguration(Project project, boolean isElevated, boolean emulateTerminal) {
|
||||
if (SystemInfo.isWindows)
|
||||
return null;
|
||||
|
||||
if (!ZigDebuggerSettings.getInstance().useClion)
|
||||
return null;
|
||||
|
||||
val toolchains = CPPToolchains.getInstance();
|
||||
var toolchain = toolchains.getToolchainByNameOrDefault("Zig");
|
||||
if (toolchain == null || !toolchain.isDebuggerSupported()) {
|
||||
|
@ -42,8 +52,8 @@ public class CPPDebuggerDriverProvider implements DebuggerDriverProvider {
|
|||
}
|
||||
|
||||
return switch (toolchain.getDebuggerKind()) {
|
||||
case CUSTOM_GDB, BUNDLED_GDB -> new CLionGDBDriverConfiguration(project, toolchain);
|
||||
case BUNDLED_LLDB -> new CLionLLDBDriverConfiguration(project, toolchain);
|
||||
case CUSTOM_GDB, BUNDLED_GDB -> new ObjectHolder<>(new CLionGDBDriverConfiguration(project, toolchain));
|
||||
case BUNDLED_LLDB -> new ObjectHolder<>(new CLionLLDBDriverConfiguration(project, toolchain));
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,43 +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.debugbridge;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* getDebuggerConfiguration should return com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration, it's UserDataHolder here to
|
||||
* avoid a plugin verifier error.
|
||||
*/
|
||||
public interface DebuggerDriverProvider {
|
||||
ExtensionPointName<DebuggerDriverProvider> EXTENSION_POINT_NAME = ExtensionPointName.create("com.falsepattern.zigbrains.debuggerDriverProvider");
|
||||
|
||||
static @NotNull Stream<UserDataHolder> findDebuggerConfigurations(Project project) {
|
||||
return EXTENSION_POINT_NAME.getExtensionList()
|
||||
.stream()
|
||||
.map(it -> it.getDebuggerConfiguration(project))
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
@Nullable UserDataHolder getDebuggerConfiguration(Project project);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.debugbridge;
|
||||
|
||||
import com.falsepattern.zigbrains.common.ObjectHolder;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface ZigDebuggerDriverConfigurationProvider {
|
||||
ExtensionPointName<ZigDebuggerDriverConfigurationProvider> EXTENSION_POINT_NAME = ExtensionPointName.create("com.falsepattern.zigbrains.debuggerDriverProvider");
|
||||
|
||||
static @NotNull Stream<Supplier<DebuggerDriverConfiguration>> findDebuggerConfigurations(Project project, boolean isElevated, boolean emulateTerminal) {
|
||||
return EXTENSION_POINT_NAME.getExtensionList()
|
||||
.stream()
|
||||
.map(it -> (Supplier<DebuggerDriverConfiguration>) () -> Optional.ofNullable(it.getDebuggerConfiguration(project, isElevated, emulateTerminal))
|
||||
.map(ObjectHolder::value)
|
||||
.orElse(null));
|
||||
}
|
||||
|
||||
@Nullable ObjectHolder<DebuggerDriverConfiguration> getDebuggerConfiguration(Project project, boolean isElevated, boolean emulateTerminal);
|
||||
}
|
|
@ -16,45 +16,13 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger;
|
||||
|
||||
import com.falsepattern.zigbrains.debugbridge.DebuggerDriverProvider;
|
||||
import com.falsepattern.zigbrains.debugger.win.WinDebuggerDriverConfiguration;
|
||||
import com.falsepattern.zigbrains.project.util.CLIUtil;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.system.OS;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Utils {
|
||||
public static @Nullable DebuggerDriverConfiguration getDebuggerConfiguration(Project project) {
|
||||
if (OS.CURRENT == OS.Windows) {
|
||||
return new WinDebuggerDriverConfiguration();
|
||||
}
|
||||
val providedDebugger = DebuggerDriverProvider.findDebuggerConfigurations(project)
|
||||
.filter(x -> x instanceof DebuggerDriverConfiguration)
|
||||
.map(x -> (DebuggerDriverConfiguration)x)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (providedDebugger != null)
|
||||
return providedDebugger;
|
||||
|
||||
|
||||
if (LLDBDriverConfiguration.hasBundledLLDB()) {
|
||||
Notifications.Bus.notify(new Notification("ZigBrains.Debugger.Warn",
|
||||
"Couldn't find a working debug toolchain, using bundled LLDB debugger!",
|
||||
NotificationType.WARNING));
|
||||
return new LLDBDriverConfiguration();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void executeCommandLineWithErrorChecks(GeneralCommandLine cli) throws ExecutionException, ProcessException {
|
||||
val outputOpt = CLIUtil.execute(cli, Integer.MAX_VALUE);
|
||||
|
|
|
@ -0,0 +1,225 @@
|
|||
package com.falsepattern.zigbrains.debugger;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.common.ObjectHolder;
|
||||
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProvider;
|
||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability.GDBBinaries;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability.LLDBBinaries;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability.MSVCBinaries;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerKind;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService;
|
||||
import com.falsepattern.zigbrains.debugger.win.MSVCDriverConfiguration;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DoNotAskOption;
|
||||
import com.intellij.openapi.ui.MessageDialogBuilder;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.jetbrains.cidr.ArchitectureType;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.gdb.GDBDriverConfiguration;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class ZigDefaultDebuggerDriverConfigurationProvider implements ZigDebuggerDriverConfigurationProvider {
|
||||
private static boolean availabilityCheck(Project project, DebuggerKind kind) {
|
||||
val service = ZigDebuggerToolchainService.getInstance();
|
||||
val availability = service.debuggerAvailability(kind);
|
||||
|
||||
final String message, action;
|
||||
switch (availability.kind()) {
|
||||
case Bundled, Binaries -> {
|
||||
return true;
|
||||
}
|
||||
case Unavailable -> {
|
||||
return false;
|
||||
}
|
||||
case NeedToDownload -> {
|
||||
message = "Debugger is not loaded yet";
|
||||
action = "Download";
|
||||
}
|
||||
case NeedToUpdate -> {
|
||||
message = " Debugger is outdated";
|
||||
action = "Update";
|
||||
}
|
||||
default -> throw new AssertionError("This should never happen");
|
||||
}
|
||||
|
||||
val downloadDebugger = ZigDebuggerSettings.getInstance().downloadAutomatically || showDialog(project, message, action);
|
||||
|
||||
if (downloadDebugger) {
|
||||
val result = ZigDebuggerToolchainService.getInstance().downloadDebugger(project, kind);
|
||||
if (result instanceof ZigDebuggerToolchainService.DownloadResult.Ok)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean showDialog(Project project, String message, String action) {
|
||||
val doNotAsk = new DoNotAskOption.Adapter() {
|
||||
@Override
|
||||
public void rememberChoice(boolean isSelected, int exitCode) {
|
||||
if (exitCode == Messages.OK) {
|
||||
ZigDebuggerSettings.getInstance().downloadAutomatically = isSelected;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return MessageDialogBuilder.okCancel(ZigBundle.message("unable.to.run.debugger"), message)
|
||||
.yesText(action)
|
||||
.icon(Messages.getErrorIcon())
|
||||
.doNotAsk(doNotAsk)
|
||||
.ask(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ObjectHolder<DebuggerDriverConfiguration> getDebuggerConfiguration(Project project, boolean isElevated, boolean emulateTerminal) {
|
||||
val settings = ZigDebuggerSettings.getInstance();
|
||||
val service = ZigDebuggerToolchainService.getInstance();
|
||||
val kind = settings.debuggerKind;
|
||||
if (!availabilityCheck(project, kind)) {
|
||||
return null;
|
||||
}
|
||||
val availability = service.debuggerAvailability(kind);
|
||||
return switch (availability.kind()) {
|
||||
case Bundled -> new ObjectHolder<>(switch (kind) {
|
||||
case LLDB -> new ZigLLDBDriverConfiguration(isElevated, emulateTerminal);
|
||||
case GDB -> new ZigGDBDriverConfiguration(isElevated, emulateTerminal);
|
||||
case MSVC -> throw new AssertionError("MSVC is never bundled");
|
||||
});
|
||||
case Binaries -> {
|
||||
val bin = (DebuggerAvailability.Binaries) availability;
|
||||
yield new ObjectHolder<>(switch (bin.binariesKind()) {
|
||||
case LLDB -> new ZigCustomBinariesLLDBDriverConfiguration((LLDBBinaries) bin, isElevated, emulateTerminal);
|
||||
case GDB -> new ZigCustomBinariesGDBDriverConfiguration((GDBBinaries) bin, isElevated, emulateTerminal);
|
||||
case MSVC -> new ZigMSVCDriverConfiguration((MSVCBinaries) bin, isElevated, emulateTerminal);
|
||||
});
|
||||
}
|
||||
case Unavailable, NeedToDownload, NeedToUpdate -> throw new AssertionError("This should never happen");
|
||||
};
|
||||
}
|
||||
|
||||
//region GDB
|
||||
@RequiredArgsConstructor
|
||||
public static class ZigGDBDriverConfiguration extends GDBDriverConfiguration {
|
||||
private final boolean isElevated;
|
||||
private final boolean emulateTerminal;
|
||||
|
||||
@Override
|
||||
public @NotNull String getDriverName() {
|
||||
return "Zig GDB";
|
||||
}
|
||||
|
||||
// TODO: investigate attach to process feature separately
|
||||
@Override
|
||||
public boolean isAttachSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isElevated() {
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean emulateTerminal() {
|
||||
return emulateTerminal;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ZigCustomBinariesGDBDriverConfiguration extends ZigGDBDriverConfiguration {
|
||||
private final GDBBinaries binaries;
|
||||
public ZigCustomBinariesGDBDriverConfiguration(GDBBinaries binaries, boolean isElevated, boolean emulateTerminal) {
|
||||
super(isElevated, emulateTerminal);
|
||||
this.binaries = binaries;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull String getGDBExecutablePath() {
|
||||
return binaries.gdbFile().toString();
|
||||
}
|
||||
}
|
||||
//endregion GDB
|
||||
|
||||
//region LLDB
|
||||
@RequiredArgsConstructor
|
||||
public static class ZigLLDBDriverConfiguration extends LLDBDriverConfiguration {
|
||||
private final boolean isElevated;
|
||||
private final boolean emulateTerminal;
|
||||
|
||||
@Override
|
||||
public @NotNull String getDriverName() {
|
||||
return "Zig LLDB";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isElevated() {
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean emulateTerminal() {
|
||||
return emulateTerminal;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ZigCustomBinariesLLDBDriverConfiguration extends ZigLLDBDriverConfiguration {
|
||||
private final LLDBBinaries binaries;
|
||||
public ZigCustomBinariesLLDBDriverConfiguration(LLDBBinaries binaries, boolean isElevated, boolean emulateTerminal) {
|
||||
super(isElevated, emulateTerminal);
|
||||
this.binaries = binaries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSTLRenderers() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull File getLLDBFrameworkFile(@NotNull ArchitectureType architectureType) {
|
||||
return binaries.frameworkFile().toFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull File getLLDBFrontendFile(@NotNull ArchitectureType architectureType) {
|
||||
return binaries.frontendFile().toFile();
|
||||
}
|
||||
}
|
||||
//endregion LLDB
|
||||
|
||||
//region MSVC
|
||||
@RequiredArgsConstructor
|
||||
public static class ZigMSVCDriverConfiguration extends MSVCDriverConfiguration {
|
||||
private final MSVCBinaries binaries;
|
||||
private final boolean isElevated;
|
||||
private final boolean emulateTerminal;
|
||||
|
||||
@Override
|
||||
public @NotNull String getDriverName() {
|
||||
return "Zig MSVC";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path getDebuggerExecutable() {
|
||||
return binaries.msvcFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isElevated() {
|
||||
return isElevated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean emulateTerminal() {
|
||||
return emulateTerminal;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion MSVC
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.PreLaunchAware;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.filters.Filter;
|
||||
import com.intellij.execution.filters.TextConsoleBuilder;
|
||||
|
@ -41,19 +42,21 @@ public class ZigLocalDebugProcess extends CidrLocalDebugProcess {
|
|||
PostStart,
|
||||
Unsuppressed
|
||||
}
|
||||
private volatile SuppressionLevel suppressionLevel = SuppressionLevel.PreStart;
|
||||
private volatile SuppressionLevel suppressionLevel;
|
||||
private final List<Runnable> preStart = new ArrayList<>();
|
||||
private final List<Runnable> postStart = new ArrayList<>();
|
||||
public ZigLocalDebugProcess(@NotNull RunParameters parameters, @NotNull XDebugSession session, @NotNull TextConsoleBuilder consoleBuilder)
|
||||
throws ExecutionException {
|
||||
super(parameters, session, consoleBuilder, (project) -> Filter.EMPTY_ARRAY, false);
|
||||
suppressionLevel = parameters instanceof PreLaunchAware ? SuppressionLevel.PreStart : SuppressionLevel.Unsuppressed;
|
||||
}
|
||||
|
||||
public void doStart() {
|
||||
start();
|
||||
lock.lock();
|
||||
try {
|
||||
suppressionLevel = SuppressionLevel.PostStart;
|
||||
if (suppressionLevel == SuppressionLevel.PreStart)
|
||||
suppressionLevel = SuppressionLevel.PostStart;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
@ -82,7 +85,8 @@ public class ZigLocalDebugProcess extends CidrLocalDebugProcess {
|
|||
|
||||
lock.lock();
|
||||
try {
|
||||
if (suppressionLevel == SuppressionLevel.Unsuppressed)
|
||||
val level = suppressionLevel;
|
||||
if (level == SuppressionLevel.Unsuppressed)
|
||||
return original.get();
|
||||
|
||||
val bypass = new CompletableFuture<T>();
|
||||
|
@ -93,7 +97,7 @@ public class ZigLocalDebugProcess extends CidrLocalDebugProcess {
|
|||
bypass.completeExceptionally(ex);
|
||||
return null;
|
||||
});
|
||||
switch (suppressionLevel) {
|
||||
switch (level) {
|
||||
case PreStart -> preStart.add(task);
|
||||
case PostStart -> postStart.add(task);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.base;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface PreLaunchAware {
|
||||
void preLaunch() throws Exception;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.base;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.Lazy;
|
||||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.jetbrains.cidr.execution.Installer;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
|
@ -23,12 +23,9 @@ import com.jetbrains.cidr.ArchitectureType;
|
|||
import com.jetbrains.cidr.execution.RunParameters;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class ZigDebugParametersBase<ProfileState extends ProfileStateBase<?>> extends RunParameters {
|
||||
|
|
|
@ -20,7 +20,6 @@ import com.falsepattern.zigbrains.debugger.Utils;
|
|||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import lombok.val;
|
||||
|
@ -29,7 +28,6 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public abstract class ZigDebugParametersEmitBinaryBase<ProfileState extends ProfileStateBase<?>> extends ZigDebugParametersBase<ProfileState> implements PreLaunchAware {
|
||||
protected volatile File executableFile;
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
package com.falsepattern.zigbrains.debugger.runner.base;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
|
||||
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProvider;
|
||||
import com.falsepattern.zigbrains.debugger.Utils;
|
||||
import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess;
|
||||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.project.runconfig.ZigProgramRunnerBase;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.debugger.Utils;
|
||||
import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.executors.DefaultDebugExecutor;
|
||||
|
@ -32,9 +33,6 @@ import com.intellij.execution.runners.ExecutionEnvironment;
|
|||
import com.intellij.execution.ui.ConsoleView;
|
||||
import com.intellij.execution.ui.ConsoleViewContentType;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebugProcessStarter;
|
||||
|
@ -68,9 +66,18 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
|
|||
protected RunContentDescriptor doExecute(ProfileState state, AbstractZigToolchain toolchain, ExecutionEnvironment environment)
|
||||
throws ExecutionException {
|
||||
val project = environment.getProject();
|
||||
val debuggerDriver = Utils.getDebuggerConfiguration(project);
|
||||
val providers = ZigDebuggerDriverConfigurationProvider.findDebuggerConfigurations(project, false, false)
|
||||
.toList();
|
||||
|
||||
DebuggerDriverConfiguration debuggerDriver = null;
|
||||
|
||||
for (val provider: providers) {
|
||||
debuggerDriver = provider.get();
|
||||
if (debuggerDriver != null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (debuggerDriver == null) {
|
||||
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;
|
||||
}
|
||||
ZigDebugParametersBase<ProfileState> runParameters = getDebugParameters(state, environment, debuggerDriver, toolchain);
|
||||
|
@ -132,10 +139,9 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
|
|||
}
|
||||
};
|
||||
val process = new ZigLocalDebugProcess(params, session, wrappedBuilder);
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
ProcessTerminatedListener.attach(process.getProcessHandler(), environment.getProject());
|
||||
|
||||
if (params instanceof PreLaunchAware pla) {
|
||||
if (params instanceof PreLaunchAware pla) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
ProcessTerminatedListener.attach(process.getProcessHandler(), environment.getProject());
|
||||
try {
|
||||
pla.preLaunch();
|
||||
} catch (Exception e) {
|
||||
|
@ -156,9 +162,9 @@ public abstract class ZigDebugRunnerBase<ProfileState extends ProfileStateBase<?
|
|||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
process.unSuppress(true);
|
||||
});
|
||||
process.unSuppress(true);
|
||||
});
|
||||
}
|
||||
process.doStart();
|
||||
return process;
|
||||
}
|
||||
|
|
|
@ -16,15 +16,13 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.binary;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ProfileStateBinary;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ProfileStateBinary;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.jetbrains.cidr.execution.Installer;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
|
|
@ -16,19 +16,16 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.binary;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ProfileStateBinary;
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ZigExecConfigBinary;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ProfileStateBinary;
|
||||
import com.falsepattern.zigbrains.debugger.execution.binary.ZigExecConfigBinary;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
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;
|
||||
|
|
|
@ -22,23 +22,16 @@ import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstall
|
|||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.project.execution.build.ProfileStateBuild;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.project.util.CLIUtil;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.jetbrains.cidr.execution.Installer;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import lombok.Cleanup;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ZigDebugParametersBuild extends ZigDebugParametersBase<ProfileStateBuild> implements PreLaunchAware {
|
||||
private static final String BoilerplateNotice = "\nPlease edit this intellij build configuration and specify the path of the executable created by \"zig build\" directly!";
|
||||
|
|
|
@ -16,21 +16,17 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.build;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.project.execution.build.ProfileStateBuild;
|
||||
import com.falsepattern.zigbrains.project.execution.build.ZigExecConfigBuild;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
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 lombok.val;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.run;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
import com.falsepattern.zigbrains.project.execution.base.ProfileStateBase;
|
||||
import com.falsepattern.zigbrains.project.execution.run.ProfileStateRun;
|
||||
|
@ -26,9 +25,6 @@ import com.falsepattern.zigbrains.project.toolchain.LocalZigToolchain;
|
|||
import com.intellij.execution.ExecutionException;
|
||||
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;
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.test;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersEmitBinaryBase;
|
||||
import com.falsepattern.zigbrains.project.execution.test.ProfileStateTest;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugEmitBinaryInstaller;
|
||||
import com.jetbrains.cidr.execution.Installer;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
|
@ -16,19 +16,16 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.runner.test;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
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.debugger.runner.base.ZigDebugParametersBase;
|
||||
import com.falsepattern.zigbrains.debugger.runner.base.ZigDebugRunnerBase;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
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;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package com.falsepattern.zigbrains.debugger.settings;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.dsl.JavaPanel;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.options.ConfigurableUi;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ZigDebuggerGeneralSettingsConfigurableUi implements ConfigurableUi<ZigDebuggerSettings>, Disposable {
|
||||
private final List<ZigDebuggerUiComponent> components;
|
||||
|
||||
public ZigDebuggerGeneralSettingsConfigurableUi() {
|
||||
components = new ArrayList<>();
|
||||
components.add(new ZigDebuggerToolchainConfigurableUi());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified(@NotNull ZigDebuggerSettings settings) {
|
||||
for (val it: components) {
|
||||
if (it.isModified(settings)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(@NotNull ZigDebuggerSettings settings) {
|
||||
for (val it: components) {
|
||||
it.reset(settings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(@NotNull ZigDebuggerSettings settings) throws ConfigurationException {
|
||||
for (val it: components) {
|
||||
it.apply(settings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JComponent getComponent() {
|
||||
return JavaPanel.newPanel(p -> {
|
||||
for (val it: components) {
|
||||
it.buildUi(p);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
components.forEach(Disposable::dispose);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.falsepattern.zigbrains.debugger.settings;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerKind;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.SimpleConfigurable;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import com.intellij.xdebugger.settings.DebuggerSettingsCategory;
|
||||
import com.intellij.xdebugger.settings.XDebuggerSettings;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ZigDebuggerSettings extends XDebuggerSettings<ZigDebuggerSettings> {
|
||||
public static final String GENERAL_SETTINGS_ID = "Debugger.Zig.General";
|
||||
|
||||
public DebuggerKind debuggerKind = DebuggerKind.defaultKind();
|
||||
|
||||
public boolean downloadAutomatically = false;
|
||||
public boolean useClion = true;
|
||||
|
||||
protected ZigDebuggerSettings() {
|
||||
super("Zig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ZigDebuggerSettings getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull ZigDebuggerSettings state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<? extends Configurable> createConfigurables(@NotNull DebuggerSettingsCategory category) {
|
||||
val configurable = switch (category) {
|
||||
case GENERAL -> createGeneralSettingsConfigurable();
|
||||
default -> null;
|
||||
};
|
||||
return configurable == null ? Collections.emptyList() : List.of(configurable);
|
||||
}
|
||||
|
||||
private Configurable createGeneralSettingsConfigurable() {
|
||||
return SimpleConfigurable.create(
|
||||
GENERAL_SETTINGS_ID,
|
||||
ZigBundle.message("settings.debugger.title"),
|
||||
ZigDebuggerGeneralSettingsConfigurableUi.class,
|
||||
ZigDebuggerSettings::getInstance
|
||||
);
|
||||
}
|
||||
|
||||
public static ZigDebuggerSettings getInstance() {
|
||||
return XDebuggerSettings.getInstance(ZigDebuggerSettings.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package com.falsepattern.zigbrains.debugger.settings;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.common.util.dsl.JavaPanel;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerAvailability;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.DebuggerKind;
|
||||
import com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.observable.util.ListenerUiUtil;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JEditorPane;
|
||||
import java.util.Arrays;
|
||||
import java.util.Vector;
|
||||
|
||||
import static com.intellij.ui.dsl.builder.UtilsKt.DEFAULT_COMMENT_WIDTH;
|
||||
|
||||
public class ZigDebuggerToolchainConfigurableUi extends ZigDebuggerUiComponent {
|
||||
private final ComboBox<DebuggerKind> debuggerKindCombobox = new ComboBox<>(createDebuggerKindComboBoxModel());
|
||||
|
||||
private final JBCheckBox downloadAutomaticallyCheckBox = new JBCheckBox(
|
||||
ZigBundle.message("settings.debugger.toolchain.download.debugger.automatically.checkbox"),
|
||||
ZigDebuggerSettings.getInstance().downloadAutomatically
|
||||
);
|
||||
|
||||
private final JBCheckBox useClion = new JBCheckBox(
|
||||
ZigBundle.message("settings.debugger.toolchain.use.clion.toolchains"),
|
||||
ZigDebuggerSettings.getInstance().useClion
|
||||
);
|
||||
|
||||
private JEditorPane comment = null;
|
||||
|
||||
private DebuggerKind currentDebuggerKind() {
|
||||
return debuggerKindCombobox.getItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified(@NotNull ZigDebuggerSettings settings) {
|
||||
return settings.debuggerKind != debuggerKindCombobox.getItem() ||
|
||||
settings.downloadAutomatically != downloadAutomaticallyCheckBox.isSelected() ||
|
||||
settings.useClion != useClion.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(@NotNull ZigDebuggerSettings settings) {
|
||||
debuggerKindCombobox.setItem(settings.debuggerKind);
|
||||
downloadAutomaticallyCheckBox.setSelected(settings.downloadAutomatically);
|
||||
useClion.setSelected(settings.useClion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(@NotNull ZigDebuggerSettings settings) throws ConfigurationException {
|
||||
settings.debuggerKind = debuggerKindCombobox.getItem();
|
||||
settings.downloadAutomatically = downloadAutomaticallyCheckBox.isSelected();
|
||||
settings.useClion = useClion.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildUi(JavaPanel panel) {
|
||||
panel.row(ZigBundle.message("settings.debugger.toolchain.debugger.label"), r -> {
|
||||
comment = r.cell(debuggerKindCombobox)
|
||||
.comment("", DEFAULT_COMMENT_WIDTH, (e) -> downloadDebugger())
|
||||
.applyToComponent(c -> {
|
||||
ListenerUiUtil.whenItemSelected(c, null, (x) -> {
|
||||
update();
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
})
|
||||
.getComment();
|
||||
});
|
||||
panel.row(r -> {
|
||||
r.cell(downloadAutomaticallyCheckBox);
|
||||
});
|
||||
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion"))) {
|
||||
panel.row(r -> {
|
||||
r.cell(useClion);
|
||||
});
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
private ComboBoxModel<DebuggerKind> createDebuggerKindComboBoxModel() {
|
||||
val toolchainService = ZigDebuggerToolchainService.getInstance();
|
||||
val availableKinds = Arrays.stream(DebuggerKind.values())
|
||||
.filter(kind -> toolchainService.debuggerAvailability(kind) != DebuggerAvailability.Unavailable)
|
||||
.toList();
|
||||
|
||||
val model = new DefaultComboBoxModel<>(new Vector<>(availableKinds));
|
||||
model.setSelectedItem(ZigDebuggerSettings.getInstance().debuggerKind);
|
||||
return model;
|
||||
}
|
||||
|
||||
private void downloadDebugger() {
|
||||
val result = ZigDebuggerToolchainService.getInstance().downloadDebugger(null, currentDebuggerKind());
|
||||
if (result instanceof ZigDebuggerToolchainService.DownloadResult.Ok) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
private void update() {
|
||||
val availability = ZigDebuggerToolchainService.getInstance().debuggerAvailability(currentDebuggerKind());
|
||||
final String text;
|
||||
if (availability == DebuggerAvailability.NeedToDownload) {
|
||||
text = ZigBundle.message("settings.debugger.toolchain.download.comment");
|
||||
} else if (availability == DebuggerAvailability.NeedToUpdate) {
|
||||
text = ZigBundle.message("settings.debugger.toolchain.update.comment");
|
||||
} else {
|
||||
text = null;
|
||||
}
|
||||
|
||||
if (comment != null) {
|
||||
comment.setText(text);
|
||||
comment.setVisible(text != null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.falsepattern.zigbrains.debugger.settings;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.dsl.JavaPanel;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.options.ConfigurableUi;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public abstract class ZigDebuggerUiComponent implements ConfigurableUi<ZigDebuggerSettings>, Disposable {
|
||||
public abstract void buildUi(JavaPanel panel);
|
||||
|
||||
@Override
|
||||
public @NotNull JComponent getComponent() {
|
||||
return JavaPanel.newPanel(this::buildUi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.falsepattern.zigbrains.debugger.toolchain;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public sealed interface DebuggerAvailability {
|
||||
enum Kind {
|
||||
Unavailable,
|
||||
NeedToDownload,
|
||||
NeedToUpdate,
|
||||
Bundled,
|
||||
Binaries
|
||||
}
|
||||
|
||||
Kind kind();
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
final class Unavailable implements DebuggerAvailability {
|
||||
@Override
|
||||
public Kind kind() {
|
||||
return Kind.Unavailable;
|
||||
}
|
||||
}
|
||||
Unavailable Unavailable = new Unavailable();
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
final class NeedToDownload implements DebuggerAvailability {
|
||||
@Override
|
||||
public Kind kind() {
|
||||
return Kind.NeedToDownload;
|
||||
}
|
||||
}
|
||||
NeedToDownload NeedToDownload = new NeedToDownload();
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
final class NeedToUpdate implements DebuggerAvailability {
|
||||
@Override
|
||||
public Kind kind() {
|
||||
return Kind.NeedToUpdate;
|
||||
}
|
||||
}
|
||||
NeedToUpdate NeedToUpdate = new NeedToUpdate();
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
final class Bundled implements DebuggerAvailability {
|
||||
@Override
|
||||
public Kind kind() {
|
||||
return Kind.Bundled;
|
||||
}
|
||||
}
|
||||
Bundled Bundled = new Bundled();
|
||||
|
||||
sealed interface Binaries extends DebuggerAvailability {
|
||||
@Override
|
||||
default Kind kind() {
|
||||
return Kind.Binaries;
|
||||
}
|
||||
|
||||
DebuggerKind binariesKind();
|
||||
}
|
||||
|
||||
record LLDBBinaries(Path frameworkFile, Path frontendFile) implements Binaries {
|
||||
@Override
|
||||
public DebuggerKind binariesKind() {
|
||||
return DebuggerKind.LLDB;
|
||||
}
|
||||
}
|
||||
record GDBBinaries(Path gdbFile) implements Binaries {
|
||||
@Override
|
||||
public DebuggerKind binariesKind() {
|
||||
return DebuggerKind.GDB;
|
||||
}
|
||||
}
|
||||
record MSVCBinaries(Path msvcFile) implements Binaries {
|
||||
@Override
|
||||
public DebuggerKind binariesKind() {
|
||||
return DebuggerKind.MSVC;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.falsepattern.zigbrains.debugger.toolchain;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
|
||||
public enum DebuggerKind {
|
||||
LLDB,
|
||||
GDB,
|
||||
MSVC;
|
||||
|
||||
public static DebuggerKind defaultKind() {
|
||||
if (SystemInfo.isWindows)
|
||||
return MSVC;
|
||||
return LLDB;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,496 @@
|
|||
package com.falsepattern.zigbrains.debugger.toolchain;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.common.ZigPathManager;
|
||||
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.PathManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.components.JBPanel;
|
||||
import com.intellij.util.download.DownloadableFileService;
|
||||
import com.intellij.util.io.Decompressor;
|
||||
import com.intellij.util.system.CpuArch;
|
||||
import com.intellij.util.system.OS;
|
||||
import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Cleanup;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
public final class ZigDebuggerToolchainService {
|
||||
public static ZigDebuggerToolchainService getInstance() {
|
||||
return ApplicationManager.getApplication().getService(ZigDebuggerToolchainService.class);
|
||||
}
|
||||
|
||||
public DebuggerAvailability debuggerAvailability(DebuggerKind kind) {
|
||||
return switch (kind) {
|
||||
case LLDB -> lldbAvailability();
|
||||
case GDB -> gdbAvailability();
|
||||
case MSVC -> msvcAvailability();
|
||||
};
|
||||
}
|
||||
|
||||
public DebuggerAvailability lldbAvailability() {
|
||||
if (LLDBDriverConfiguration.hasBundledLLDB())
|
||||
return DebuggerAvailability.Bundled;
|
||||
|
||||
final String frameworkPath, frontendPath;
|
||||
if (SystemInfo.isMac) {
|
||||
frameworkPath = "LLDB.framework";
|
||||
frontendPath = "LLDBFrontend";
|
||||
} else if (SystemInfo.isUnix) {
|
||||
frameworkPath = "lib/liblldb.so";
|
||||
frontendPath = "bin/LLDBFrontend";
|
||||
} else if (SystemInfo.isWindows) {
|
||||
return DebuggerAvailability.Unavailable;
|
||||
// frameworkPath = "bin/liblldb.dll";
|
||||
// frontendPath = "bin/LLDBFrontend.exe";
|
||||
} else {
|
||||
return DebuggerAvailability.Unavailable;
|
||||
}
|
||||
|
||||
val lldbPath = lldbPath();
|
||||
val frameworkFile = lldbPath.resolve(frameworkPath);
|
||||
val frontendFile = lldbPath.resolve(frontendPath);
|
||||
if (!Files.exists(frameworkFile) || !Files.exists(frontendFile))
|
||||
return DebuggerAvailability.NeedToDownload;
|
||||
|
||||
val versions = loadDebuggerVersions(DebuggerKind.LLDB);
|
||||
val urls = lldbUrls();
|
||||
if (urls == null)
|
||||
return DebuggerAvailability.Unavailable;
|
||||
|
||||
val lldbFrameworkVersion = fileNameWithoutExtension(urls.framework().toString());
|
||||
val lldbFrontendVersion = fileNameWithoutExtension(urls.frontend().toString());
|
||||
|
||||
if (!Objects.equals(versions.get(LLDB_FRAMEWORK_PROPERTY_NAME), lldbFrameworkVersion) ||
|
||||
!Objects.equals(versions.get(LLDB_FRONTEND_PROPERTY_NAME), lldbFrontendVersion))
|
||||
return DebuggerAvailability.NeedToUpdate;
|
||||
|
||||
return new DebuggerAvailability.LLDBBinaries(frameworkFile, frontendFile);
|
||||
}
|
||||
|
||||
public DebuggerAvailability gdbAvailability() {
|
||||
// Even if we have bundled GDB, it still doesn't work on macOS for local runs
|
||||
if (SystemInfo.isMac)
|
||||
return DebuggerAvailability.Unavailable;
|
||||
|
||||
if (CidrDebuggerPathManager.getBundledGDBBinary().exists())
|
||||
return DebuggerAvailability.Bundled;
|
||||
|
||||
final String gdbBinaryPath;
|
||||
if (SystemInfo.isUnix) {
|
||||
gdbBinaryPath = "bin/gdb";
|
||||
} else if (SystemInfo.isWindows) {
|
||||
return DebuggerAvailability.Unavailable;
|
||||
// gdbBinaryPath = "bin/gdb.exe";
|
||||
} else {
|
||||
return DebuggerAvailability.Unavailable;
|
||||
}
|
||||
|
||||
val gdbFile = gdbPath().resolve(gdbBinaryPath);
|
||||
if (!Files.exists(gdbFile))
|
||||
return DebuggerAvailability.NeedToDownload;
|
||||
|
||||
val versions = loadDebuggerVersions(DebuggerKind.GDB);
|
||||
val gdbUrl = gdbUrl();
|
||||
if (gdbUrl == null)
|
||||
return DebuggerAvailability.Unavailable;
|
||||
|
||||
val gdbVersion = fileNameWithoutExtension(gdbUrl.toString());
|
||||
|
||||
if (!Objects.equals(versions.get(GDB_PROPERTY_NAME), gdbVersion))
|
||||
return DebuggerAvailability.NeedToUpdate;
|
||||
|
||||
return new DebuggerAvailability.GDBBinaries(gdbFile);
|
||||
}
|
||||
|
||||
public DebuggerAvailability msvcAvailability() {
|
||||
//Only applies to Windows
|
||||
if (!SystemInfo.isWindows)
|
||||
return DebuggerAvailability.Unavailable;
|
||||
|
||||
val msvcBinaryPath = "vsdbg.exe";
|
||||
|
||||
val msvcFile = msvcPath().resolve(msvcBinaryPath);
|
||||
if (!Files.exists(msvcFile))
|
||||
return DebuggerAvailability.NeedToDownload;
|
||||
|
||||
val msvcUrl = msvcUrl();
|
||||
if (msvcUrl == null) //Fallback in case falsepattern.com goes down
|
||||
return new DebuggerAvailability.MSVCBinaries(msvcFile);
|
||||
|
||||
val versions = loadDebuggerVersions(DebuggerKind.MSVC);
|
||||
|
||||
if (!Objects.equals(versions.get(MSVC_PROPERTY_NAME), msvcUrl.version))
|
||||
return DebuggerAvailability.NeedToUpdate;
|
||||
|
||||
return new DebuggerAvailability.MSVCBinaries(msvcFile);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public DownloadResult downloadDebugger(@Nullable Project project, DebuggerKind debuggerKind) {
|
||||
val result = ProgressManager.getInstance()
|
||||
.runProcessWithProgressSynchronously(() -> downloadDebuggerSynchronously(debuggerKind),
|
||||
ZigBundle.message("dialog.title.download.debugger"),
|
||||
true,
|
||||
project);
|
||||
|
||||
if (result instanceof DownloadResult.Ok) {
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Warn",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.successfully.downloaded"),
|
||||
NotificationType.INFORMATION
|
||||
));
|
||||
} else if (result instanceof DownloadResult.Failed) {
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Project",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.downloading.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private DownloadResult downloadDebuggerSynchronously(DebuggerKind kind) {
|
||||
val baseDir = basePath(kind);
|
||||
|
||||
val downloadableBinaries = switch (kind) {
|
||||
case LLDB -> {
|
||||
val urls = lldbUrls();
|
||||
if (urls == null)
|
||||
yield null;
|
||||
|
||||
val fwUrl = urls.framework.toString();
|
||||
val feUrl = urls.frontend.toString();
|
||||
yield List.of(
|
||||
new DownloadableDebuggerBinary(fwUrl, LLDB_FRAMEWORK_PROPERTY_NAME, fileNameWithoutExtension(fwUrl)),
|
||||
new DownloadableDebuggerBinary(feUrl, LLDB_FRONTEND_PROPERTY_NAME, fileNameWithoutExtension(feUrl))
|
||||
);
|
||||
}
|
||||
case GDB -> {
|
||||
val gdbUrl = gdbUrl();
|
||||
if (gdbUrl == null)
|
||||
yield null;
|
||||
val url = gdbUrl.toString();
|
||||
yield List.of(new DownloadableDebuggerBinary(url, GDB_PROPERTY_NAME, fileNameWithoutExtension(url)));
|
||||
}
|
||||
case MSVC -> {
|
||||
val msvcUrl = msvcUrl();
|
||||
if (msvcUrl == null)
|
||||
yield null;
|
||||
|
||||
AtomicReference<Boolean> accepted = new AtomicReference<>(false);
|
||||
|
||||
ApplicationManager.getApplication().invokeAndWait(() -> {
|
||||
val dialog = new DialogBuilder();
|
||||
dialog.setTitle(msvcUrl.dialogTitle);
|
||||
dialog.addCancelAction().setText("Reject");
|
||||
dialog.addOkAction().setText("Accept");
|
||||
val centerPanel = new JBPanel<>();
|
||||
val hyperlink = new HyperlinkLabel();
|
||||
hyperlink.setTextWithHyperlink(msvcUrl.dialogBody);
|
||||
hyperlink.setHyperlinkTarget(msvcUrl.dialogLink);
|
||||
hyperlink.addHyperlinkListener(new BrowserHyperlinkListener());
|
||||
centerPanel.add(hyperlink);
|
||||
dialog.centerPanel(centerPanel);
|
||||
accepted.set(dialog.showAndGet());
|
||||
});
|
||||
|
||||
if (!accepted.get())
|
||||
yield null;
|
||||
|
||||
yield List.of(new DownloadableDebuggerBinary(msvcUrl.url.toString(), MSVC_PROPERTY_NAME, msvcUrl.version, "extension/debugAdapters/vsdbg/bin"));
|
||||
}
|
||||
};
|
||||
|
||||
if (downloadableBinaries == null)
|
||||
return DownloadResult.NoUrls;
|
||||
|
||||
try {
|
||||
downloadAndUnarchive(baseDir, downloadableBinaries);
|
||||
return new DownloadResult.Ok(baseDir);
|
||||
} catch (IOException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
return new DownloadResult.Failed(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadAndUnarchive(Path baseDir, List<DownloadableDebuggerBinary> binariesToDownload)
|
||||
throws IOException {
|
||||
val service = DownloadableFileService.getInstance();
|
||||
|
||||
val downloadDir = baseDir.toFile();
|
||||
FileUtil.deleteRecursively(baseDir);
|
||||
|
||||
val descriptions = binariesToDownload.stream().map(it -> service.createFileDescription(it.url, fileName(it.url))).toList();
|
||||
|
||||
val downloader = service.createDownloader(descriptions, "Debugger downloading");
|
||||
val downloadDirectory = downloadPath().toFile();
|
||||
val downloadResults = downloader.download(downloadDirectory);
|
||||
|
||||
val versions = new Properties();
|
||||
for (val result: downloadResults) {
|
||||
val downloadUrl = result.getSecond().getDownloadUrl();
|
||||
val binaryToDownload = binariesToDownload.stream()
|
||||
.filter(it -> Objects.equals(it.url, downloadUrl))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IOException("Failed to find matching download URL!"));
|
||||
val propertyName = binaryToDownload.propertyName;
|
||||
val archiveFile = result.getFirst();
|
||||
Unarchiver.unarchive(archiveFile, downloadDir, binaryToDownload.prefix);
|
||||
archiveFile.delete();
|
||||
versions.put(propertyName, binaryToDownload.version);
|
||||
}
|
||||
|
||||
saveVersionsFile(baseDir, versions);
|
||||
}
|
||||
|
||||
public Properties loadDebuggerVersions(DebuggerKind kind) {
|
||||
return loadVersions(basePath(kind));
|
||||
}
|
||||
|
||||
public void saveDebuggerVersions(DebuggerKind kind, Properties versions) {
|
||||
saveVersionsFile(basePath(kind), versions);
|
||||
}
|
||||
|
||||
private void saveVersionsFile(Path basePath, Properties versions) {
|
||||
val file = basePath.resolve(DEBUGGER_VERSIONS);
|
||||
try (val writer = Files.newBufferedWriter(file)){
|
||||
versions.store(writer, "");
|
||||
} catch (IOException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private Properties loadVersions(Path basePath) {
|
||||
val versions = new Properties();
|
||||
val versionsFile = basePath.resolve(DEBUGGER_VERSIONS);
|
||||
|
||||
if (Files.exists(versionsFile)) {
|
||||
try(val reader = Files.newBufferedReader(versionsFile)) {
|
||||
versions.load(reader);
|
||||
} catch (IOException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
|
||||
private Path basePath(DebuggerKind kind) {
|
||||
return switch (kind) {
|
||||
case LLDB -> lldbPath();
|
||||
case GDB -> gdbPath();
|
||||
case MSVC -> msvcPath();
|
||||
};
|
||||
}
|
||||
|
||||
private static Path downloadPath() {
|
||||
return Paths.get(PathManager.getTempPath());
|
||||
}
|
||||
|
||||
private static Path lldbPath() {
|
||||
return ZigPathManager.pluginDirInSystem().resolve("lldb");
|
||||
}
|
||||
|
||||
private static Path gdbPath() {
|
||||
return ZigPathManager.pluginDirInSystem().resolve("gdb");
|
||||
}
|
||||
|
||||
private static Path msvcPath() {
|
||||
return ZigPathManager.pluginDirInSystem().resolve("msvc");
|
||||
}
|
||||
|
||||
private LLDBUrls lldbUrls() {
|
||||
val lldb = UrlProvider.lldb(OS.CURRENT, CpuArch.CURRENT);
|
||||
if (lldb == null)
|
||||
return null;
|
||||
|
||||
val lldbFrontend = UrlProvider.lldbFrontend(OS.CURRENT, CpuArch.CURRENT);
|
||||
if (lldbFrontend == null)
|
||||
return null;
|
||||
|
||||
return new LLDBUrls(lldb, lldbFrontend);
|
||||
}
|
||||
|
||||
private record LLDBUrls(URL framework, URL frontend) {}
|
||||
|
||||
private URL gdbUrl() {
|
||||
return UrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT);
|
||||
}
|
||||
|
||||
private Properties msvcProperties() {
|
||||
val service = DownloadableFileService.getInstance();
|
||||
val desc = service.createFileDescription("https://falsepattern.com/zigbrains/msvc.properties", "msvc.properties");
|
||||
val downloader = service.createDownloader(List.of(desc), "Debugger metadata downloading");
|
||||
val downloadDirectory = downloadPath().toFile();
|
||||
val prop = new Properties();
|
||||
try {
|
||||
val downloadResults = downloader.download(downloadDirectory);
|
||||
for (val result : downloadResults) {
|
||||
if (Objects.equals(result.second.getDefaultFileName(), "msvc.properties")) {
|
||||
@Cleanup val reader = new FileReader(result.first);
|
||||
prop.load(reader);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"Zig Debugger",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
private MSVCUrl msvcUrl() {
|
||||
String dlKey = switch (CpuArch.CURRENT) {
|
||||
case X86 -> "downloadX86";
|
||||
case X86_64 -> "downloadX86_64";
|
||||
case ARM64 -> "downloadARM64";
|
||||
default -> null;
|
||||
};
|
||||
if (dlKey == null)
|
||||
return null;
|
||||
|
||||
val props = msvcProperties();
|
||||
val version = props.getProperty("version");
|
||||
val url = props.getProperty(dlKey);
|
||||
if (url == null || version == null)
|
||||
return null;
|
||||
|
||||
try {
|
||||
return new MSVCUrl(new URL(url), version, props.getProperty("dialogTitle"), props.getProperty("dialogBody"), props.getProperty("dialogLink"));
|
||||
} catch (MalformedURLException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private record MSVCUrl(URL url, String version, String dialogTitle, String dialogBody, String dialogLink) {}
|
||||
|
||||
private static String fileName(String url) {
|
||||
return url.substring(url.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
private static String fileNameWithoutExtension(String url) {
|
||||
url = fileName(url);
|
||||
url = removeSuffix(url, ".zip");
|
||||
url = removeSuffix(url, ".tar.gz");
|
||||
return url;
|
||||
}
|
||||
|
||||
private static String removeSuffix(String str, String suffix) {
|
||||
if (str.endsWith(suffix))
|
||||
str = str.substring(0, str.length() - suffix.length());
|
||||
return str;
|
||||
}
|
||||
private static final String DEBUGGER_VERSIONS = "versions.properties";
|
||||
private static final String LLDB_FRONTEND_PROPERTY_NAME = "lldbFrontend";
|
||||
private static final String LLDB_FRAMEWORK_PROPERTY_NAME = "lldbFramework";
|
||||
private static final String GDB_PROPERTY_NAME = "gdb";
|
||||
private static final String MSVC_PROPERTY_NAME = "msvc";
|
||||
|
||||
public sealed interface DownloadResult {
|
||||
record Ok(Path baseDir) implements DownloadResult {}
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
final class NoUrls implements DownloadResult {}
|
||||
NoUrls NoUrls = new NoUrls();
|
||||
record Failed(String message) implements DownloadResult {}
|
||||
}
|
||||
|
||||
private enum Unarchiver {
|
||||
ZIP {
|
||||
@Override
|
||||
protected String extension() {
|
||||
return "zip";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decompressor createDecompressor(File file) {
|
||||
return new Decompressor.Zip(file);
|
||||
}
|
||||
},
|
||||
TAR {
|
||||
@Override
|
||||
protected String extension() {
|
||||
return "tar.gz";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decompressor createDecompressor(File file) {
|
||||
return new Decompressor.Tar(file);
|
||||
}
|
||||
},
|
||||
VSIX {
|
||||
@Override
|
||||
protected String extension() {
|
||||
return "vsix";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Decompressor createDecompressor(File file) {
|
||||
return new Decompressor.Zip(file);
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract String extension();
|
||||
protected abstract Decompressor createDecompressor(File file);
|
||||
|
||||
static void unarchive(File archivePath, File dst, String prefix) throws IOException {
|
||||
val unarchiver = Arrays.stream(values())
|
||||
.filter(it -> archivePath.getName().endsWith(it.extension()))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new IOException("Failed to find decompressor for file " + archivePath.getName()));
|
||||
val dec = unarchiver.createDecompressor(archivePath);
|
||||
if (prefix != null) {
|
||||
dec.removePrefixPath(prefix);
|
||||
}
|
||||
dec.extract(dst);
|
||||
}
|
||||
}
|
||||
|
||||
private record DownloadableDebuggerBinary(String url, String propertyName, String version, String prefix) {
|
||||
public DownloadableDebuggerBinary(String url, String propertyName, String version) {
|
||||
this(url, propertyName, version, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright 2023-2024 FalsePattern
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.falsepattern.zigbrains.debugger.win;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.dap.DAPDebuggerDriverConfiguration;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.jetbrains.cidr.ArchitectureType;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver;
|
||||
import lombok.val;
|
||||
import org.eclipse.lsp4j.debug.InitializeRequestArguments;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public abstract class MSVCDriverConfiguration extends DAPDebuggerDriverConfiguration {
|
||||
protected abstract Path getDebuggerExecutable();
|
||||
|
||||
@Override
|
||||
public @NotNull DebuggerDriver createDriver(DebuggerDriver.@NotNull Handler handler, @NotNull ArchitectureType architectureType)
|
||||
throws ExecutionException {
|
||||
return new WinDAPDriver(handler, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull GeneralCommandLine createDriverCommandLine(
|
||||
@NotNull DebuggerDriver debuggerDriver, @NotNull ArchitectureType architectureType)
|
||||
throws ExecutionException {
|
||||
val path = getDebuggerExecutable();
|
||||
val cli = new GeneralCommandLine();
|
||||
cli.setExePath(path.toString());
|
||||
cli.addParameters("--interpreter=vscode", "--extConfigDir=%USERPROFILE%\\.cppvsdbg\\extensions");
|
||||
cli.setWorkDirectory(path.getParent().toString());
|
||||
return cli;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeInitializeArguments(InitializeRequestArguments initArgs) {
|
||||
initArgs.setPathFormat("path");
|
||||
initArgs.setAdapterID("cppvsdbg");
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger.win;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.dap.DAPDebuggerDriverConfiguration;
|
||||
import com.falsepattern.zigbrains.debugger.dap.DAPDriver;
|
||||
import com.falsepattern.zigbrains.debugger.dap.WrappedDebugServer;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
|
@ -51,7 +52,7 @@ public class WinDAPDriver extends DAPDriver<
|
|||
WinDAPDriver.WinDAPDebuggerClient
|
||||
> {
|
||||
private final CompletableFuture<HandshakeResponse> handshakeFuture = new CompletableFuture<>();
|
||||
public WinDAPDriver(@NotNull Handler handler, WinDebuggerDriverConfiguration config) throws ExecutionException {
|
||||
public WinDAPDriver(@NotNull Handler handler, DAPDebuggerDriverConfiguration config) throws ExecutionException {
|
||||
super(handler, config);
|
||||
DAPDriver$postConstructor();
|
||||
}
|
||||
|
|
|
@ -1,139 +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.debugger.win;
|
||||
|
||||
import com.falsepattern.zigbrains.debugger.dap.DAPDebuggerDriverConfiguration;
|
||||
import com.falsepattern.zigbrains.debugger.win.config.WinDebuggerConfigService;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.jetbrains.cidr.ArchitectureType;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriver;
|
||||
import lombok.val;
|
||||
import org.apache.commons.io.file.PathUtils;
|
||||
import org.eclipse.lsp4j.debug.InitializeRequestArguments;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Map;
|
||||
|
||||
public class WinDebuggerDriverConfiguration extends DAPDebuggerDriverConfiguration {
|
||||
private static void extractVSDebugger(Path pathToPluginFile, Path pathToExtracted) throws IOException {
|
||||
if (pathToPluginFile == null) {
|
||||
throw new IllegalArgumentException("Please set the debugger inside Build, Execution, Deployment | Debugger | Zig (Windows)");
|
||||
}
|
||||
if (!Files.isRegularFile(pathToPluginFile) || !pathToPluginFile.getFileName().toString().endsWith(".vsix")) {
|
||||
throw new IllegalArgumentException("Invalid debugger file path! Please check Build, Execution, Deployment | Debugger | Zig (Windows) again! The file MUST be a .vsix file!");
|
||||
}
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI("jar:" + pathToPluginFile.toAbsolutePath().toUri().toASCIIString());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("Could not parse plugin file path: " + pathToPluginFile);
|
||||
}
|
||||
try (val fs = FileSystems.newFileSystem(uri, Map.of())) {
|
||||
val basePath = fs.getPath("/extension/debugAdapters/vsdbg/bin");
|
||||
try (val walk = Files.walk(basePath)) {
|
||||
walk.forEach(path -> {
|
||||
if (!Files.isRegularFile(path))
|
||||
return;
|
||||
val relPath = Path.of(basePath.relativize(path).toString());
|
||||
val resPath = pathToExtracted.resolve(relPath);
|
||||
try {
|
||||
Files.createDirectories(resPath.getParent());
|
||||
Files.copy(path, resPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull GeneralCommandLine createDriverCommandLine(@NotNull DebuggerDriver debuggerDriver, @NotNull ArchitectureType architectureType) {
|
||||
val pathToPluginFileStr = WinDebuggerConfigService.getInstance().cppToolsPath;
|
||||
if (pathToPluginFileStr == null || pathToPluginFileStr.isBlank()) {
|
||||
throw new IllegalArgumentException("Please set the debugger inside Build, Execution, Deployment | Debugger | Zig (Windows)");
|
||||
}
|
||||
Path pathToPluginFile;
|
||||
try {
|
||||
pathToPluginFile = Path.of(pathToPluginFileStr);
|
||||
} catch (InvalidPathException e) {
|
||||
throw new IllegalArgumentException("Invalid debugger path " + pathToPluginFileStr + "! Make sure it points to the .vsix file!");
|
||||
}
|
||||
Path pathToExtracted;
|
||||
try {
|
||||
val tmpDir = Path.of(System.getProperty("java.io.tmpdir"));
|
||||
int i = 0;
|
||||
do {
|
||||
pathToExtracted = tmpDir.resolve("zb-windbg-" + i++);
|
||||
} while (Files.exists(pathToExtracted.resolve(".lock")) || Files.isRegularFile(pathToExtracted));
|
||||
if (Files.exists(pathToExtracted)) {
|
||||
PathUtils.deleteDirectory(pathToExtracted);
|
||||
}
|
||||
extractVSDebugger(pathToPluginFile, pathToExtracted);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Path finalPathToExtracted = pathToExtracted;
|
||||
val lockFile = finalPathToExtracted.resolve(".lock");
|
||||
try {
|
||||
Files.createFile(lockFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Cleaner.create().register(debuggerDriver, () -> {
|
||||
try {
|
||||
Files.delete(lockFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
val cli = new GeneralCommandLine();
|
||||
cli.setExePath(finalPathToExtracted.resolve("vsdbg.exe").toString());
|
||||
cli.setCharset(StandardCharsets.UTF_8);
|
||||
cli.addParameters("--interpreter=vscode", "--extConfigDir=%USERPROFILE%\\.cppvsdbg\\extensions");
|
||||
cli.setWorkDirectory(finalPathToExtracted.toString());
|
||||
return cli;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDriverName() {
|
||||
return "WinDAPDriver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DebuggerDriver createDriver(DebuggerDriver.@NotNull Handler handler, @NotNull ArchitectureType architectureType)
|
||||
throws ExecutionException {
|
||||
return new WinDAPDriver(handler, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customizeInitializeArguments(InitializeRequestArguments initArgs) {
|
||||
initArgs.setPathFormat("path");
|
||||
initArgs.setAdapterID("cppvsdbg");
|
||||
}
|
||||
}
|
|
@ -1,46 +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.debugger.win.config;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
@State(name = "CPPToolsSettings",
|
||||
storages = @Storage("zigbrains.xml"))
|
||||
public final class WinDebuggerConfigService implements PersistentStateComponent<WinDebuggerConfigService> {
|
||||
public String cppToolsPath = "";
|
||||
|
||||
public static WinDebuggerConfigService getInstance() {
|
||||
return ApplicationManager.getApplication().getService(WinDebuggerConfigService.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull WinDebuggerConfigService getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull WinDebuggerConfigService state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
}
|
|
@ -1,88 +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.debugger.win.config;
|
||||
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.system.OS;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.ui.dsl.builder.BuilderKt.panel;
|
||||
|
||||
public class WinDebuggerConfigurable implements Configurable {
|
||||
private WinDebuggerSettingsPanel settingsPanel;
|
||||
|
||||
@Override
|
||||
public @NlsContexts.ConfigurableName String getDisplayName() {
|
||||
return "Zig Debugger (Windows)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable JComponent createComponent() {
|
||||
settingsPanel = new WinDebuggerSettingsPanel();
|
||||
return panel((p) -> {
|
||||
if (OS.CURRENT != OS.Windows) {
|
||||
p.row("This menu has no effect on linux/macos/non-windows systems, use the C++ toolchains (see plugin description).", (r) -> null);
|
||||
p.row("For completeness' sake, here is what you would need to configure on Windows:", (r) -> null);
|
||||
p.separator(JBColor.foreground());
|
||||
}
|
||||
settingsPanel.attachPanelTo(p);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (settingsPanel == null)
|
||||
return false;
|
||||
var cppSettings = WinDebuggerConfigService.getInstance();
|
||||
var settingsData = settingsPanel.getData();
|
||||
return !Objects.equals(settingsData.cppToolsPath(), cppSettings.cppToolsPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
if (settingsPanel == null)
|
||||
return;
|
||||
var cppSettings = WinDebuggerConfigService.getInstance();
|
||||
var settingsData = settingsPanel.getData();
|
||||
cppSettings.cppToolsPath = settingsData.cppToolsPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if (settingsPanel == null)
|
||||
return;
|
||||
val cppSettings = WinDebuggerConfigService.getInstance();
|
||||
settingsPanel.setData(new WinDebuggerSettingsPanel.SettingsData(cppSettings.cppToolsPath));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disposeUIResources() {
|
||||
if (settingsPanel == null)
|
||||
return;
|
||||
Disposer.dispose(settingsPanel);
|
||||
settingsPanel = null;
|
||||
}
|
||||
}
|
|
@ -1,99 +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.debugger.win.config;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.StringUtil;
|
||||
import com.falsepattern.zigbrains.common.util.TextFieldUtil;
|
||||
import com.falsepattern.zigbrains.project.openapi.MyDisposable;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.dsl.builder.AlignX;
|
||||
import com.intellij.ui.dsl.builder.AlignY;
|
||||
import com.intellij.ui.dsl.builder.Panel;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import java.util.Optional;
|
||||
|
||||
public class WinDebuggerSettingsPanel implements MyDisposable {
|
||||
@Getter
|
||||
private boolean disposed = false;
|
||||
|
||||
public record SettingsData(@Nullable String cppToolsPath) {}
|
||||
|
||||
@SuppressWarnings("DialogTitleCapitalization")
|
||||
private final TextFieldWithBrowseButton pathToArchive = TextFieldUtil.pathToFileTextField(this,
|
||||
"Path to \"cpptools-win**.vsix\"",
|
||||
() -> {});
|
||||
|
||||
public SettingsData getData() {
|
||||
return new SettingsData(StringUtil.blankToNull(pathToArchive.getText()));
|
||||
}
|
||||
|
||||
public void setData(SettingsData value) {
|
||||
pathToArchive.setText(Optional.ofNullable(value.cppToolsPath()).orElse(""));
|
||||
}
|
||||
|
||||
private static HyperlinkLabel link(String url) {
|
||||
val href = new HyperlinkLabel(url);
|
||||
href.setHyperlinkTarget(url);
|
||||
return href;
|
||||
}
|
||||
|
||||
public void attachPanelTo(Panel panel) {
|
||||
panel.panel(p -> {
|
||||
p.row("Debugging Zig on Windows requires you to manually install the MSVC toolchain.",
|
||||
(r) -> null);
|
||||
|
||||
p.row("To install the MSVC debugger, follow setup 3 under Prerequisites on the following page:",
|
||||
(r) -> null);
|
||||
return null;
|
||||
});
|
||||
panel.panel(p -> {
|
||||
p.row((JLabel) null, (r) -> {
|
||||
r.cell(link("https://code.visualstudio.com/docs/cpp/config-msvc"));
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
panel.panel(p -> {
|
||||
p.row("After you've installed MSVC, you also need download the vscode plugin with the debugger adapter.", (r) -> null);
|
||||
p.row("Latest known working version: 1.19.6. Newer versions may or may not work.", (r) -> null);
|
||||
return null;
|
||||
});
|
||||
panel.panel(p -> {
|
||||
p.row("You can download the latest version here:", (r) -> {
|
||||
r.cell(link("https://github.com/microsoft/vscode-cpptools/releases"));
|
||||
return null;
|
||||
});
|
||||
p.row("Put the path to the downloaded file here:", (r) -> {
|
||||
r.cell(pathToArchive).resizableColumn().align(AlignX.FILL).align(AlignY.FILL);
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
disposed = true;
|
||||
Disposer.dispose(pathToArchive);
|
||||
}
|
||||
}
|
|
@ -14,10 +14,12 @@
|
|||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<idea-plugin package="com.falsepattern.zigbrains.cpp">
|
||||
<idea-plugin package="com.falsepattern.zigbrains.clion">
|
||||
<depends>com.intellij.modules.clion</depends>
|
||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
||||
<debuggerDriverProvider implementation="com.falsepattern.zigbrains.cpp.CPPDebuggerDriverProvider"/>
|
||||
<debuggerDriverProvider id="ZigClionDebuggerDriverConfiguration"
|
||||
implementation="com.falsepattern.zigbrains.clion.ZigClionDebuggerDriverConfigurationProvider"
|
||||
order="before ZigDefaultDebuggerDriverConfigurationProvider"/>
|
||||
</extensions>
|
||||
|
||||
</idea-plugin>
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
<idea-plugin package="com.falsepattern.zigbrains.debugger">
|
||||
<depends>com.intellij.modules.cidr.debugger</depends>
|
||||
<resource-bundle>zigbrains.debugger.Bundle</resource-bundle>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<configurationType implementation="com.falsepattern.zigbrains.debugger.execution.binary.ConfigTypeBinary"/>
|
||||
|
@ -30,21 +29,27 @@
|
|||
<programRunner implementation="com.falsepattern.zigbrains.debugger.runner.binary.ZigDebugRunnerBinary"
|
||||
id="ZigDebugRunnerBinary"/>
|
||||
|
||||
<xdebugger.settings implementation="com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings"/>
|
||||
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.debugger.Bundle"
|
||||
key="notif-debug-error"
|
||||
id="ZigBrains.Debugger.Error"/>
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-debug-info"
|
||||
id="ZigBrains.Debugger.Info"/>
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.debugger.Bundle"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-debug-warn"
|
||||
id="ZigBrains.Debugger.Warn"/>
|
||||
<applicationConfigurable parentId="project.propDebugger"
|
||||
instance="com.falsepattern.zigbrains.debugger.win.config.WinDebuggerConfigurable"
|
||||
displayName="Zig (Windows)"/>
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-debug-error"
|
||||
id="ZigBrains.Debugger.Error"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="com.falsepattern.zigbrains">
|
||||
<featureProvider implementation="com.falsepattern.zigbrains.debugger.DebuggerFeatures"/>
|
||||
<debuggerDriverProvider id="ZigDefaultDebuggerDriverConfigurationProvider"
|
||||
implementation="com.falsepattern.zigbrains.debugger.ZigDefaultDebuggerDriverConfigurationProvider"
|
||||
order="last"/>
|
||||
</extensions>
|
||||
|
||||
<extensions defaultExtensionNs="cidr.debugger">
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
notif-debug-warn=ZigBrains debugger warning
|
||||
notif-debug-error=ZigBrains debugger error
|
|
@ -32,7 +32,6 @@ import org.jdom.Element;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ import org.jetbrains.annotations.Nullable;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.*;
|
||||
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.ZigConfigurable;
|
||||
import static com.falsepattern.zigbrains.project.execution.base.ZigConfigEditor.coloredConfigurable;
|
||||
|
||||
@Getter
|
||||
public class ZigExecConfigBuild extends ZigExecConfigBase<ZigExecConfigBuild> {
|
||||
|
|
|
@ -16,36 +16,21 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.ide.newproject;
|
||||
|
||||
import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectConfigurationData;
|
||||
import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectGeneratorPeer;
|
||||
import com.falsepattern.zigbrains.project.ide.project.ZigDefaultTemplate;
|
||||
import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectSettingsStep;
|
||||
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
||||
import com.falsepattern.zigbrains.zig.Icons;
|
||||
import com.falsepattern.zigbrains.zig.settings.ZLSProjectSettingsService;
|
||||
import com.intellij.facet.ui.ValidationResult;
|
||||
import com.intellij.ide.util.projectWizard.AbstractNewProjectStep;
|
||||
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.WriteAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.AbstractActionWithPanel;
|
||||
import com.intellij.platform.DirectoryProjectGenerator;
|
||||
import com.intellij.platform.ProjectGeneratorPeer;
|
||||
import com.intellij.util.ResourceUtil;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ZigDirectoryProjectGenerator implements DirectoryProjectGenerator<ZigProjectConfigurationData>,
|
||||
CustomStepProjectGenerator<ZigProjectConfigurationData> {
|
||||
|
|
|
@ -24,19 +24,15 @@ import com.falsepattern.zigbrains.zig.settings.ZLSSettingsPanel;
|
|||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
|
||||
import com.intellij.ui.ColoredListCellRenderer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.ToolbarDecorator;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.dsl.builder.AlignX;
|
||||
import com.intellij.ui.dsl.builder.AlignY;
|
||||
import com.intellij.ui.dsl.builder.Panel;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import java.util.Arrays;
|
||||
|
|
|
@ -16,14 +16,12 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.ide.newproject;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.FileUtil;
|
||||
import com.intellij.ide.wizard.AbstractNewProjectWizardStep;
|
||||
import com.intellij.ide.wizard.GitNewProjectWizardData;
|
||||
import com.intellij.ide.wizard.LanguageNewProjectWizard;
|
||||
import com.intellij.ide.wizard.NewProjectWizardLanguageStep;
|
||||
import com.intellij.ide.wizard.NewProjectWizardStep;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.ui.dsl.builder.AlignX;
|
||||
import com.intellij.ui.dsl.builder.Panel;
|
||||
import lombok.val;
|
||||
|
|
|
@ -16,21 +16,18 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.ide.newproject;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
|
||||
import com.falsepattern.zigbrains.project.ide.project.ZigDefaultTemplate;
|
||||
import com.falsepattern.zigbrains.project.ide.project.ZigProjectTemplate;
|
||||
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettings;
|
||||
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
||||
import com.falsepattern.zigbrains.zig.settings.ZLSProjectSettingsService;
|
||||
import com.falsepattern.zigbrains.zig.settings.ZLSSettings;
|
||||
import com.intellij.ide.wizard.GitNewProjectWizardData;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.GitRepositoryInitializer;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
@ -41,7 +38,6 @@ import org.jetbrains.annotations.NotNull;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public record ZigProjectConfigurationData(boolean git, ZigProjectSettings projConf, ZLSSettings zlsConf, ZigProjectTemplate selectedTemplate) {
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.ide.newproject;
|
||||
|
||||
import com.falsepattern.zigbrains.project.ide.newproject.ZigProjectConfigurationData;
|
||||
import com.intellij.ide.util.projectWizard.AbstractNewProjectStep;
|
||||
import com.intellij.ide.util.projectWizard.ProjectSettingsStepBase;
|
||||
import com.intellij.platform.DirectoryProjectGenerator;
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
package com.falsepattern.zigbrains.project.openapi.components;
|
||||
|
||||
import com.falsepattern.zigbrains.common.WrappingStateComponent;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class AbstractZigProjectSettingsService<T> extends WrappingStateComponent<T> {
|
||||
|
|
|
@ -16,18 +16,13 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.openapi.components;
|
||||
|
||||
import com.falsepattern.zigbrains.project.ide.project.ZigProjectSettingsPanel;
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain;
|
||||
import com.falsepattern.zigbrains.zig.lsp.ZLSStartupActivity;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(
|
||||
|
|
|
@ -21,11 +21,8 @@ import com.intellij.openapi.util.SystemInfo;
|
|||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class LocalZigToolchainProvider implements ZigToolchainProvider {
|
||||
private static final Map<Path, LocalZigToolchain> tcCache = ContainerUtil.createWeakKeyWeakValueMap();
|
||||
|
|
|
@ -16,15 +16,12 @@
|
|||
|
||||
package com.falsepattern.zigbrains.project.toolchain.stdlib;
|
||||
|
||||
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
|
||||
import com.falsepattern.zigbrains.common.util.PathUtil;
|
||||
import com.falsepattern.zigbrains.project.openapi.components.ZigProjectSettingsService;
|
||||
import com.falsepattern.zigbrains.zig.Icons;
|
||||
import com.falsepattern.zigbrains.zig.parser.ZigFile;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectUtil;
|
||||
import com.intellij.openapi.roots.SyntheticLibrary;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
|
@ -39,7 +36,6 @@ import javax.swing.Icon;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
|
|
@ -27,10 +27,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
|
||||
public class ZigCompilerTool extends AbstractZigTool{
|
||||
public static final String TOOL_NAME = "zig";
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
-->
|
||||
|
||||
<idea-plugin package="com.falsepattern.zigbrains.project">
|
||||
<resource-bundle>zigbrains.project.Bundle</resource-bundle>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<configurationType implementation="com.falsepattern.zigbrains.project.execution.run.ConfigTypeRun"/>
|
||||
<runConfigurationProducer implementation="com.falsepattern.zigbrains.project.execution.run.ConfigProducerRun"/>
|
||||
|
@ -35,7 +34,7 @@
|
|||
<directoryProjectGenerator implementation="com.falsepattern.zigbrains.project.ide.newproject.ZigDirectoryProjectGenerator"/>
|
||||
<newProjectWizard.language implementation="com.falsepattern.zigbrains.project.ide.newproject.ZigNewProjectWizard"/>
|
||||
|
||||
<moduleBuilder builderClass="com.falsepattern.zigbrains.project.ide.util.projectwizard.ZigModuleBuilder"/>
|
||||
<moduleBuilder builderClass="com.falsepattern.zigbrains.project.ide.newproject.ZigModuleBuilder"/>
|
||||
<projectConfigurable parentId="language"
|
||||
instance="com.falsepattern.zigbrains.project.ide.config.ZigConfigurable"
|
||||
id="com.falsepattern.zigbrains.project.ide.config.ZigConfigurable"
|
||||
|
@ -46,7 +45,7 @@
|
|||
id="ZigDebugRunner"/>
|
||||
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.project.Bundle"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-zig-project"
|
||||
id="ZigBrains.Project"/>
|
||||
|
||||
|
|
|
@ -1,17 +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.
|
||||
#
|
||||
|
||||
notif-zig-project=Zig Project Status Notification
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.falsepattern.zigbrains.zig.lsp;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.common.util.ApplicationUtil;
|
||||
import com.falsepattern.zigbrains.common.util.StringUtil;
|
||||
import com.falsepattern.zigbrains.lsp.IntellijLanguageClient;
|
||||
|
@ -23,11 +24,18 @@ import com.falsepattern.zigbrains.lsp.utils.FileUtils;
|
|||
import com.falsepattern.zigbrains.zig.environment.ZLSConfigProvider;
|
||||
import com.falsepattern.zigbrains.zig.settings.ZLSProjectSettingsService;
|
||||
import com.google.gson.Gson;
|
||||
import com.intellij.ide.BrowserUtil;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.plugins.PluginManagerConfigurable;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationAction;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.ProjectActivity;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
|
@ -166,11 +174,42 @@ public class ZLSStartupActivity implements ProjectActivity {
|
|||
return true;
|
||||
}
|
||||
|
||||
private static boolean firstInit = true;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object execute(@NotNull Project project, @NotNull Continuation<? super Unit> continuation) {
|
||||
val svc = ZLSProjectSettingsService.getInstance(project);
|
||||
val state = svc.getState();
|
||||
if (firstInit) {
|
||||
firstInit = false;
|
||||
if (!PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.cidr.debugger")) && PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.nativeDebug-plugin-capable"))) {
|
||||
val notif = new Notification(
|
||||
"ZigBrains",
|
||||
ZigBundle.message("notification.nativedebug.title"),
|
||||
ZigBundle.message("notification.nativedebug.text"),
|
||||
NotificationType.INFORMATION
|
||||
);
|
||||
notif.addAction(new NotificationAction(ZigBundle.message("notification.nativedebug.market")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
|
||||
val configurable = new PluginManagerConfigurable();
|
||||
ShowSettingsUtil.getInstance().editConfigurable((Project)null,
|
||||
configurable,
|
||||
() -> {
|
||||
configurable.openMarketplaceTab("/vendor:\"JetBrains s.r.o.\" /tag:Debugging \"Native Debugging Support\"");
|
||||
});
|
||||
}
|
||||
});
|
||||
notif.addAction(new NotificationAction(ZigBundle.message("notification.nativedebug.browser")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
|
||||
BrowserUtil.browse("https://plugins.jetbrains.com/plugin/12775-native-debugging-support");
|
||||
}
|
||||
});
|
||||
Notifications.Bus.notify(notif);
|
||||
}
|
||||
}
|
||||
var zlsPath = state.zlsPath;
|
||||
|
||||
if (zlsPath == null) {
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
-->
|
||||
|
||||
<idea-plugin package="com.falsepattern.zigbrains.zig">
|
||||
<resource-bundle>zigbrains.zig.Bundle</resource-bundle>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<!-- region LSP -->
|
||||
|
||||
|
@ -68,7 +67,7 @@
|
|||
|
||||
<!-- needed for inlay hints -->
|
||||
<codeInsight.declarativeInlayProvider implementationClass="com.falsepattern.zigbrains.lsp.contributors.LSPInlayHintProvider"
|
||||
bundle="zigbrains.zig.Bundle"
|
||||
bundle="zigbrains.Bundle"
|
||||
nameKey="inlayprovider"
|
||||
providerId="ZigBrains"
|
||||
isEnabledByDefault="true"
|
||||
|
@ -100,8 +99,8 @@
|
|||
|
||||
<postStartupActivity implementation="com.falsepattern.zigbrains.zig.lsp.ZLSStartupActivity"/>
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.zig.Bundle"
|
||||
key="notif-zls"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-zls-error"
|
||||
id="ZigBrains.ZLS"/>
|
||||
|
||||
<codeInsight.parameterInfo language="Zig"
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
inlayprovider=ZLS Inlay Provider
|
||||
notif-zls=ZLS Error Notification
|
|
@ -34,7 +34,11 @@ These art assets are licensed under Creative Commons Attribution-ShareAlike 4.0
|
|||
Parts of the codebase are based on the intellij-zig plugin,
|
||||
developed by HTGAzureX1212 (https://github.com/HTGAzureX1212), licensed under the Apache 2.0 license.
|
||||
--------------------------------
|
||||
Parts of the codebase are based on the intellij-rust plugin,
|
||||
developed by the intellij-rust team (https://github.com/intellij-rust), licensed under the intellij-rust MIT license.
|
||||
--------------------------------
|
||||
|
||||
All of the licenses listed here are available in the following files, bundled with the plugin:
|
||||
- licenses/APACHE_2.0.LICENSE
|
||||
- licenses/CC_BY_SA_4.0.LICENSE
|
||||
- licenses/INTELLIJ-RUST.LICENSE
|
|
@ -1,5 +1,6 @@
|
|||
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
|
||||
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude" require-restart="true">
|
||||
<resource-bundle>zigbrains.Bundle</resource-bundle>
|
||||
<id>com.falsepattern.zigbrains</id>
|
||||
<name>ZigBrains</name>
|
||||
<vendor>FalsePattern</vendor>
|
||||
|
@ -10,8 +11,14 @@
|
|||
<xi:include href="/META-INF/zigbrains-zon.xml"/>
|
||||
<xi:include href="/META-INF/zigbrains-project.xml"/>
|
||||
<depends optional="true" config-file="zigbrains-zig-debugger.xml">com.intellij.modules.cidr.debugger</depends>
|
||||
<depends optional="true" config-file="zigbrains-zig-cpp.xml">com.intellij.modules.clion</depends>
|
||||
<depends optional="true" config-file="zigbrains-zig-clion.xml">com.intellij.modules.clion</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<notificationGroup displayType="BALLOON"
|
||||
bundle="zigbrains.Bundle"
|
||||
key="notif-zb"
|
||||
id="ZigBrains"/>
|
||||
</extensions>
|
||||
<extensionPoints>
|
||||
<extensionPoint
|
||||
interface="com.falsepattern.zigbrains.project.toolchain.flavours.AbstractZigToolchainFlavour" dynamic="true"
|
||||
|
@ -23,7 +30,7 @@
|
|||
interface="com.falsepattern.zigbrains.zig.environment.ZLSConfigProvider" dynamic="true"
|
||||
name="zlsConfigProvider"/>
|
||||
<extensionPoint
|
||||
interface="com.falsepattern.zigbrains.debugbridge.DebuggerDriverProvider" dynamic="true"
|
||||
interface="com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProvider" dynamic="true"
|
||||
name="debuggerDriverProvider"/>
|
||||
<extensionPoint
|
||||
interface="com.falsepattern.zigbrains.common.ZBFeatures" dynamic="true"
|
||||
|
|
22
plugin/src/main/resources/licenses/INTELLIJ-RUST.LICENSE
Normal file
22
plugin/src/main/resources/licenses/INTELLIJ-RUST.LICENSE
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Aleksey Kladov, Evgeny Kurbatsky, Alexey Kudinkin and contributors
|
||||
Copyright (c) 2016 JetBrains
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
Loading…
Add table
Reference in a new issue