backport: 16.1.3
This commit is contained in:
parent
2d15e0b6e3
commit
4ca75e38ae
8 changed files with 160 additions and 59 deletions
|
@ -17,6 +17,15 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [16.1.3]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Debugger (Windows)
|
||||||
|
- MSVC debugger metadata download now requires consent from the user
|
||||||
|
- Metadata download is now cached after the first fetch
|
||||||
|
- Metadata download timeout has been set to 3 seconds, after which it reverts to the fallback file
|
||||||
|
|
||||||
## [16.1.2]
|
## [16.1.2]
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -11,7 +11,7 @@ baseIDE=clion
|
||||||
ideaVersion=2023.2.7
|
ideaVersion=2023.2.7
|
||||||
clionVersion=2023.2.4
|
clionVersion=2023.2.4
|
||||||
|
|
||||||
pluginVersion=16.1.2
|
pluginVersion=16.1.3
|
||||||
|
|
||||||
# Gradle Releases -> https://github.com/gradle/gradle/releases
|
# Gradle Releases -> https://github.com/gradle/gradle/releases
|
||||||
gradleVersion=8.9
|
gradleVersion=8.9
|
||||||
|
|
|
@ -13,7 +13,7 @@ notification.nativedebug.browser=Open in Browser
|
||||||
notification.title.debugger=Debugger
|
notification.title.debugger=Debugger
|
||||||
notification.content.debugger.successfully.downloaded=Debugger successfully downloaded
|
notification.content.debugger.successfully.downloaded=Debugger successfully downloaded
|
||||||
notification.content.debugger.downloading.failed=Debugger downloading failed
|
notification.content.debugger.downloading.failed=Debugger downloading failed
|
||||||
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed
|
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed, switching to fallback
|
||||||
notification.content.debugger.metadata.fallback.fetch.failed=Debugger fallback metadata fetch failed
|
notification.content.debugger.metadata.fallback.fetch.failed=Debugger fallback metadata fetch failed
|
||||||
notification.content.debugger.metadata.fallback.parse.failed=Debugger fallback metadata parse failed
|
notification.content.debugger.metadata.fallback.parse.failed=Debugger fallback metadata parse failed
|
||||||
settings.debugger.toolchain.download.debugger.automatically.checkbox=Download and update the debugger automatically
|
settings.debugger.toolchain.download.debugger.automatically.checkbox=Download and update the debugger automatically
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.falsepattern.zigbrains.debugger.settings;
|
||||||
|
|
||||||
|
public enum MSVCDownloadPermission {
|
||||||
|
AskMe,
|
||||||
|
Allow,
|
||||||
|
Deny
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ public class ZigDebuggerSettings extends XDebuggerSettings<ZigDebuggerSettings>
|
||||||
|
|
||||||
public boolean downloadAutomatically = false;
|
public boolean downloadAutomatically = false;
|
||||||
public boolean useClion = true;
|
public boolean useClion = true;
|
||||||
|
public MSVCDownloadPermission msvcConsent = MSVCDownloadPermission.AskMe;
|
||||||
|
|
||||||
protected ZigDebuggerSettings() {
|
protected ZigDebuggerSettings() {
|
||||||
super("Zig");
|
super("Zig");
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.intellij.openapi.extensions.PluginId;
|
||||||
import com.intellij.openapi.observable.util.ListenerUiUtil;
|
import com.intellij.openapi.observable.util.ListenerUiUtil;
|
||||||
import com.intellij.openapi.options.ConfigurationException;
|
import com.intellij.openapi.options.ConfigurationException;
|
||||||
import com.intellij.openapi.ui.ComboBox;
|
import com.intellij.openapi.ui.ComboBox;
|
||||||
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
import com.intellij.ui.components.JBCheckBox;
|
import com.intellij.ui.components.JBCheckBox;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -79,7 +80,7 @@ public class ZigDebuggerToolchainConfigurableUi extends ZigDebuggerUiComponent {
|
||||||
panel.row(r -> {
|
panel.row(r -> {
|
||||||
r.cell(downloadAutomaticallyCheckBox);
|
r.cell(downloadAutomaticallyCheckBox);
|
||||||
});
|
});
|
||||||
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion"))) {
|
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion")) && !SystemInfo.isWindows) {
|
||||||
panel.row(r -> {
|
panel.row(r -> {
|
||||||
r.cell(useClion);
|
r.cell(useClion);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
package com.falsepattern.zigbrains.debugger.toolchain;
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.ZigBundle;
|
||||||
|
import com.falsepattern.zigbrains.debugger.settings.MSVCDownloadPermission;
|
||||||
|
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||||
|
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.ui.DialogBuilder;
|
||||||
|
import com.intellij.ui.components.JBLabel;
|
||||||
|
import com.intellij.ui.components.JBPanel;
|
||||||
|
import com.intellij.util.download.DownloadableFileService;
|
||||||
|
import lombok.Cleanup;
|
||||||
|
import lombok.val;
|
||||||
|
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService.downloadPath;
|
||||||
|
|
||||||
|
class MSVCMetadataProvider {
|
||||||
|
private Properties cached;
|
||||||
|
private Future<Properties> downloadMSVCProps() {
|
||||||
|
val future = new CompletableFuture<Properties>();
|
||||||
|
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||||
|
try {
|
||||||
|
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();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
future.complete(prop);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
future.completeExceptionally(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties fetchBuiltinMSVCProps() {
|
||||||
|
val prop = new Properties();
|
||||||
|
try {
|
||||||
|
@Cleanup val resource = ZigDebuggerToolchainService.class.getResourceAsStream("/msvc.properties");
|
||||||
|
if (resource == null) {
|
||||||
|
Notifications.Bus.notify(new Notification(
|
||||||
|
"ZigBrains.Debugger.Error",
|
||||||
|
ZigBundle.message("notification.title.debugger"),
|
||||||
|
ZigBundle.message("notification.content.debugger.metadata.fallback.fetch.failed"),
|
||||||
|
NotificationType.ERROR
|
||||||
|
));
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
val reader = new InputStreamReader(resource);
|
||||||
|
prop.load(reader);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
Notifications.Bus.notify(new Notification(
|
||||||
|
"ZigBrains.Debugger.Error",
|
||||||
|
ZigBundle.message("notification.title.debugger"),
|
||||||
|
ZigBundle.message("notification.content.debugger.metadata.fallback.parse.failed"),
|
||||||
|
NotificationType.ERROR
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Properties msvcProperties() {
|
||||||
|
if (cached != null)
|
||||||
|
return cached;
|
||||||
|
val settings = ZigDebuggerSettings.getInstance();
|
||||||
|
var permission = settings.msvcConsent;
|
||||||
|
if (permission == MSVCDownloadPermission.AskMe) {
|
||||||
|
AtomicReference<Boolean> accepted = new AtomicReference<>(false);
|
||||||
|
ApplicationManager.getApplication().invokeAndWait(() -> {
|
||||||
|
val dialog = new DialogBuilder();
|
||||||
|
dialog.setTitle("Network Request Consent");
|
||||||
|
dialog.addCancelAction().setText("Deny");
|
||||||
|
dialog.addOkAction().setText("Allow");
|
||||||
|
val centerPanel = new JBPanel<>();
|
||||||
|
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
|
||||||
|
centerPanel.add(new JBLabel("ZigBrains needs to download some metadata from the internet for debugging on Windows."));
|
||||||
|
centerPanel.add(new JBLabel("ZigBrains will use the fallback metadata shipped inside the plugin if the request is denied."));
|
||||||
|
centerPanel.add(new JBLabel("Would you like to allow this network request?"));
|
||||||
|
dialog.centerPanel(centerPanel);
|
||||||
|
accepted.set(dialog.showAndGet());
|
||||||
|
});
|
||||||
|
permission = settings.msvcConsent = accepted.get() ? MSVCDownloadPermission.Allow : MSVCDownloadPermission.Deny;
|
||||||
|
}
|
||||||
|
return switch (permission) {
|
||||||
|
//noinspection DataFlowIssue
|
||||||
|
case AskMe, Deny -> cached = fetchBuiltinMSVCProps();
|
||||||
|
case Allow -> {
|
||||||
|
val future = downloadMSVCProps();
|
||||||
|
try {
|
||||||
|
yield future.get(3, TimeUnit.SECONDS);
|
||||||
|
} catch (ExecutionException | InterruptedException | TimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Notifications.Bus.notify(new Notification(
|
||||||
|
"ZigBrains.Debugger.Error",
|
||||||
|
ZigBundle.message("notification.title.debugger"),
|
||||||
|
ZigBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
||||||
|
NotificationType.ERROR
|
||||||
|
));
|
||||||
|
settings.msvcConsent = MSVCDownloadPermission.Deny;
|
||||||
|
yield cached = fetchBuiltinMSVCProps();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@ package com.falsepattern.zigbrains.debugger.toolchain;
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.ZigBundle;
|
import com.falsepattern.zigbrains.ZigBundle;
|
||||||
import com.falsepattern.zigbrains.common.ZigPathManager;
|
import com.falsepattern.zigbrains.common.ZigPathManager;
|
||||||
|
import com.falsepattern.zigbrains.debugger.settings.MSVCDownloadPermission;
|
||||||
|
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||||
import com.intellij.notification.Notification;
|
import com.intellij.notification.Notification;
|
||||||
import com.intellij.notification.NotificationType;
|
import com.intellij.notification.NotificationType;
|
||||||
import com.intellij.notification.Notifications;
|
import com.intellij.notification.Notifications;
|
||||||
|
@ -15,6 +17,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.ui.BrowserHyperlinkListener;
|
import com.intellij.ui.BrowserHyperlinkListener;
|
||||||
import com.intellij.ui.HyperlinkLabel;
|
import com.intellij.ui.HyperlinkLabel;
|
||||||
|
import com.intellij.ui.components.JBLabel;
|
||||||
import com.intellij.ui.components.JBPanel;
|
import com.intellij.ui.components.JBPanel;
|
||||||
import com.intellij.util.download.DownloadableFileService;
|
import com.intellij.util.download.DownloadableFileService;
|
||||||
import com.intellij.util.io.Decompressor;
|
import com.intellij.util.io.Decompressor;
|
||||||
|
@ -24,17 +27,13 @@ import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager;
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider;
|
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider;
|
||||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Cleanup;
|
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.val;
|
import lombok.val;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
@ -43,10 +42,14 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@Service(Service.Level.APP)
|
@Service(Service.Level.APP)
|
||||||
public final class ZigDebuggerToolchainService {
|
public final class ZigDebuggerToolchainService {
|
||||||
|
private MSVCMetadataProvider msvcProvider = new MSVCMetadataProvider();
|
||||||
public static ZigDebuggerToolchainService getInstance() {
|
public static ZigDebuggerToolchainService getInstance() {
|
||||||
return ApplicationManager.getApplication().getService(ZigDebuggerToolchainService.class);
|
return ApplicationManager.getApplication().getService(ZigDebuggerToolchainService.class);
|
||||||
}
|
}
|
||||||
|
@ -320,7 +323,7 @@ public final class ZigDebuggerToolchainService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Path downloadPath() {
|
static Path downloadPath() {
|
||||||
return Paths.get(PathManager.getTempPath());
|
return Paths.get(PathManager.getTempPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,56 +357,6 @@ public final class ZigDebuggerToolchainService {
|
||||||
return UrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT);
|
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(
|
|
||||||
"ZigBrains.Debugger.Error",
|
|
||||||
ZigBundle.message("notification.title.debugger"),
|
|
||||||
ZigBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
));
|
|
||||||
//Try to load fallback file
|
|
||||||
try {
|
|
||||||
@Cleanup val resource = ZigDebuggerToolchainService.class.getResourceAsStream("msvc.properties");
|
|
||||||
if (resource == null) {
|
|
||||||
Notifications.Bus.notify(new Notification(
|
|
||||||
"ZigBrains.Debugger.Error",
|
|
||||||
ZigBundle.message("notification.title.debugger"),
|
|
||||||
ZigBundle.message("notification.content.debugger.metadata.fallback.fetch.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
));
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
val reader = new InputStreamReader(resource);
|
|
||||||
prop.load(reader);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
Notifications.Bus.notify(new Notification(
|
|
||||||
"ZigBrains.Debugger.Error",
|
|
||||||
ZigBundle.message("notification.title.debugger"),
|
|
||||||
ZigBundle.message("notification.content.debugger.metadata.fallback.parse.failed"),
|
|
||||||
NotificationType.ERROR
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MSVCUrl msvcUrl() {
|
private MSVCUrl msvcUrl() {
|
||||||
String dlKey = switch (CpuArch.CURRENT) {
|
String dlKey = switch (CpuArch.CURRENT) {
|
||||||
case X86 -> "downloadX86";
|
case X86 -> "downloadX86";
|
||||||
|
@ -414,7 +367,7 @@ public final class ZigDebuggerToolchainService {
|
||||||
if (dlKey == null)
|
if (dlKey == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
val props = msvcProperties();
|
val props = msvcProvider.msvcProperties();
|
||||||
val version = props.getProperty("version");
|
val version = props.getProperty("version");
|
||||||
val url = props.getProperty(dlKey);
|
val url = props.getProperty(dlKey);
|
||||||
if (url == null || version == null)
|
if (url == null || version == null)
|
||||||
|
|
Loading…
Add table
Reference in a new issue