From be54f7d635468e01fa900b9866ec86857c1a1864 Mon Sep 17 00:00:00 2001 From: Bela VanderVoort Date: Mon, 26 Feb 2024 19:30:20 -0600 Subject: [PATCH] Better support for dotnet commands. (#1188) * Better support for dotnet commands. closes #893 * Finishing up the changes * update version number --- Src/CSharpier.Rider/CHANGELOG.md | 5 ++ Src/CSharpier.Rider/README.md | 3 + Src/CSharpier.Rider/gradle.properties | 2 +- .../CSharpierProcessPipeMultipleFiles.java | 6 +- .../csharpier/CSharpierProcessProvider.java | 17 ++--- .../csharpier/CSharpierProcessServer.java | 8 +- .../csharpier/CSharpierProcessSingleFile.java | 16 ++-- .../csharpier/CSharpierSettingsComponent.java | 31 +++++++- .../intellij/csharpier/CSharpierStartup.java | 1 + .../csharpier/CustomPathInstaller.java | 21 ++--- .../intellij/csharpier/DotNetProvider.java | 76 +++++++++++++++++++ .../csharpier/InstallGlobalAction.java | 12 ++- .../csharpier/InstallLocalAction.java | 18 +++-- .../intellij/csharpier/InstallerService.java | 4 +- .../com/intellij/csharpier/ProcessHelper.java | 40 ++-------- .../src/main/resources/META-INF/plugin.xml | 1 + 16 files changed, 184 insertions(+), 77 deletions(-) create mode 100644 Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/DotNetProvider.java diff --git a/Src/CSharpier.Rider/CHANGELOG.md b/Src/CSharpier.Rider/CHANGELOG.md index 976fdd4a5..50b9d2b90 100644 --- a/Src/CSharpier.Rider/CHANGELOG.md +++ b/Src/CSharpier.Rider/CHANGELOG.md @@ -2,6 +2,11 @@ # csharpier-rider Changelog +## [1.6.0] +- Better support for dotnet commands. + - Uses the Rider setting for '.NET CLI executable path' for running dotnet commands + - If unable to run dotnet commands, show an error message + ## [1.5.3] - Add experimental support for CSharpier server diff --git a/Src/CSharpier.Rider/README.md b/Src/CSharpier.Rider/README.md index 94c1ecac7..bbf199cef 100644 --- a/Src/CSharpier.Rider/README.md +++ b/Src/CSharpier.Rider/README.md @@ -5,6 +5,9 @@ This plugin makes use of the dotnet tool [CSharpier](https://github.com/belav/cs It uses Roslyn to parse your code and re-prints it using its own rules. The printing process was ported from [prettier](https://prettier.io/) but has evolved over time. +## CSharpier Version +The plugin determines which version of csharpier is needed to format a give file by looking for a dotnet manifest file. If one is not found it looks for a globally installed version of CSharpier. + ### To format files: - Install csharpier - as a local tool versioned to your project with `dotnet tool install csharpier` diff --git a/Src/CSharpier.Rider/gradle.properties b/Src/CSharpier.Rider/gradle.properties index 4f2ca73c0..d6499d072 100644 --- a/Src/CSharpier.Rider/gradle.properties +++ b/Src/CSharpier.Rider/gradle.properties @@ -3,7 +3,7 @@ pluginGroup = com.intellij.csharpier pluginName = csharpier -pluginVersion = 1.5.3 +pluginVersion = 1.6.0 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessPipeMultipleFiles.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessPipeMultipleFiles.java index 2e7efcab3..e66f1dd7e 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessPipeMultipleFiles.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessPipeMultipleFiles.java @@ -2,6 +2,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import java.io.*; import java.nio.charset.Charset; @@ -9,6 +10,7 @@ public class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess, Disposable { private final boolean useUtf8; private final String csharpierPath; + private final DotNetProvider dotNetProvider; private Logger logger = CSharpierLogger.getInstance(); private Process process = null; @@ -16,9 +18,10 @@ public class CSharpierProcessPipeMultipleFiles implements ICSharpierProcess, Dis private BufferedReader stdOut; public boolean processFailedToStart; - public CSharpierProcessPipeMultipleFiles(String csharpierPath, boolean useUtf8) { + public CSharpierProcessPipeMultipleFiles(String csharpierPath, boolean useUtf8, Project project) { this.csharpierPath = csharpierPath; this.useUtf8 = useUtf8; + this.dotNetProvider = DotNetProvider.getInstance(project); this.startProcess(); this.logger.debug("Warm CSharpier with initial format"); @@ -31,6 +34,7 @@ private void startProcess() { try { var processBuilder = new ProcessBuilder(this.csharpierPath, "--pipe-multiple-files"); processBuilder.environment().put("DOTNET_NOLOGO", "1"); + processBuilder.environment().put("DOTNET_ROOT", this.dotNetProvider.getDotNetROot()); this.process = processBuilder.start(); var charset = this.useUtf8 ? "utf-8" : Charset.defaultCharset().toString(); diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessProvider.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessProvider.java index ccf832a6c..7979ac2c3 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessProvider.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessProvider.java @@ -23,6 +23,7 @@ import java.nio.file.Path; import java.time.Instant; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -38,7 +39,7 @@ public class CSharpierProcessProvider implements DocumentListener, Disposable, I public CSharpierProcessProvider(@NotNull Project project) { this.project = project; - this.customPathInstaller = new CustomPathInstaller(CSharpierSettings.getInstance(project)); + this.customPathInstaller = new CustomPathInstaller(project); for (var fileEditor : FileEditorManager.getInstance(project).getAllEditors()) { var path = fileEditor.getFile().getPath(); @@ -55,7 +56,6 @@ static CSharpierProcessProvider getInstance(@NotNull Project project) { return project.getService(CSharpierProcessProvider.class); } - // TODO ideally this would warm on document open/focus. But there doesn't seem to be an event for focus @Override public void documentChanged(@NotNull DocumentEvent event) { var document = event.getDocument(); @@ -157,11 +157,8 @@ private String getCSharpierVersion(String directoryThatContainsFile) { "Unable to find dotnet-tools.json, falling back to running dotnet csharpier --version" ); - Map env = new HashMap<>(); - env.put("DOTNET_NOLOGO", "1"); - - var command = new String[]{"dotnet", "csharpier", "--version"}; - var version = ProcessHelper.ExecuteCommand(command, env, new File(directoryThatContainsFile)); + var command = List.of("csharpier", "--version"); + var version = DotNetProvider.getInstance(this.project).execDotNet(command, new File(directoryThatContainsFile)); if (version == null) { version = ""; @@ -222,7 +219,7 @@ private ICSharpierProcess setupCSharpierProcess(String directory, String version var versionWeCareAbout = Integer.parseInt(installedVersion[1]); if (CSharpierSettings.getInstance(this.project).getUseServer()) { - return new CSharpierProcessServer(customPath); + return new CSharpierProcessServer(customPath, this.project); } if (versionWeCareAbout < 12) { @@ -236,12 +233,12 @@ private ICSharpierProcess setupCSharpierProcess(String directory, String version } - return new CSharpierProcessSingleFile(customPath); + return new CSharpierProcessSingleFile(customPath, this.project); } var useUtf8 = versionWeCareAbout >= 14; - var csharpierProcess = new CSharpierProcessPipeMultipleFiles(customPath, useUtf8); + var csharpierProcess = new CSharpierProcessPipeMultipleFiles(customPath, useUtf8, this.project); if (csharpierProcess.processFailedToStart) { this.displayFailureMessage(); } diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessServer.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessServer.java index bbbf776c2..5581c9989 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessServer.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessServer.java @@ -11,17 +11,20 @@ import java.util.concurrent.TimeoutException; import com.google.gson.Gson; +import com.intellij.openapi.project.Project; public class CSharpierProcessServer implements ICSharpierProcess, Disposable { private final Gson gson = new Gson(); private final String csharpierPath; + private final DotNetProvider dotNetProvider; private Logger logger = CSharpierLogger.getInstance(); private int port; private Process process = null; public boolean processFailedToStart; - public CSharpierProcessServer(String csharpierPath) { + public CSharpierProcessServer(String csharpierPath, Project project) { this.csharpierPath = csharpierPath; + this.dotNetProvider = DotNetProvider.getInstance(project); this.startProcess(); this.logger.debug("Warm CSharpier with initial format"); @@ -35,6 +38,7 @@ private void startProcess() { var processBuilder = new ProcessBuilder(this.csharpierPath, "--server"); processBuilder.redirectErrorStream(true); processBuilder.environment().put("DOTNET_NOLOGO", "1"); + processBuilder.environment().put("DOTNET_ROOT", this.dotNetProvider.getDotNetROot()); this.process = processBuilder.start(); var reader = new BufferedReader(new InputStreamReader(this.process.getInputStream())); @@ -42,7 +46,7 @@ private void startProcess() { var executor = Executors.newSingleThreadExecutor(); var future = executor.submit(() -> reader.readLine()); - String output = null; + String output; try { output = future.get(2, TimeUnit.SECONDS); } catch (TimeoutException e) { diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessSingleFile.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessSingleFile.java index a3791b757..eedbcd39d 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessSingleFile.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierProcessSingleFile.java @@ -1,24 +1,29 @@ package com.intellij.csharpier; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import java.io.BufferedReader; import java.io.InputStreamReader; public class CSharpierProcessSingleFile implements ICSharpierProcess { - Logger logger = CSharpierLogger.getInstance(); - String csharpierPath; + private final DotNetProvider dotNetProvider; + private final Logger logger = CSharpierLogger.getInstance(); + private final String csharpierPath; - public CSharpierProcessSingleFile(String csharpierPath) { + public CSharpierProcessSingleFile(String csharpierPath, Project project) { this.csharpierPath = csharpierPath; + this.dotNetProvider = DotNetProvider.getInstance(project); } @Override public String formatFile(String content, String fileName) { + try { this.logger.debug("Running " + this.csharpierPath + " --write-stdout"); var processBuilder = new ProcessBuilder(this.csharpierPath, "--write-stdout"); processBuilder.environment().put("DOTNET_NOLOGO", "1"); + processBuilder.environment().put("DOTNET_ROOT", this.dotNetProvider.getDotNetROot()); processBuilder.redirectErrorStream(true); var process = processBuilder.start(); @@ -32,7 +37,7 @@ public String formatFile(String content, String fileName) { var nextCharacter = stdOut.read(); while (nextCharacter != -1) { - output.append((char)nextCharacter); + output.append((char) nextCharacter); nextCharacter = stdOut.read(); } @@ -40,8 +45,7 @@ public String formatFile(String content, String fileName) { if (process.exitValue() == 0 && !result.contains("Failed to compile so was not formatted.")) { return result; - } - else { + } else { this.logger.error(result); } } catch (Exception e) { diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierSettingsComponent.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierSettingsComponent.java index 27341eea9..fbc402e7d 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierSettingsComponent.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierSettingsComponent.java @@ -12,6 +12,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; public class CSharpierSettingsComponent implements SearchableConfigurable { @@ -36,17 +38,42 @@ public String getDisplayName() { return "CSharpier"; } + private JComponent createSectionHeader(String label) { + var panel = new JPanel(new GridBagLayout()); + var gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + + panel.add(new JBLabel(label), gbc); + + gbc = new GridBagConstraints(); + gbc.gridy = 0; + gbc.gridx = 1; + gbc.weightx = 1.0; + gbc.insets = new Insets(1, 6, 0, 0); + gbc.fill = GridBagConstraints.HORIZONTAL; + + var separator = new JSeparator(SwingConstants.HORIZONTAL); + panel.add(separator, gbc); + + return panel; + } + @Override public @Nullable JComponent createComponent() { var leftIndent = 20; var topInset = 10; + + + return FormBuilder.createFormBuilder() - .addLabeledComponent(new JBLabel("General Settings"), new JSeparator()) + .addComponent(createSectionHeader("General Settings")) .setFormLeftIndent(leftIndent) .addComponent(this.runOnSaveCheckBox, topInset) .setFormLeftIndent(0) - .addLabeledComponent(new JBLabel("Developer Settings"), new JSeparator(), 20) + .addComponent(createSectionHeader("Developer Settings"), 20) .setFormLeftIndent(leftIndent) .addLabeledComponent(new JBLabel("Directory of custom dotnet-csharpier:"), this.customPathTextField, topInset, false) .addComponent(this.useServerCheckBox, topInset) diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierStartup.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierStartup.java index 67c639539..2bf60c766 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierStartup.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CSharpierStartup.java @@ -9,6 +9,7 @@ public class CSharpierStartup implements StartupActivity, DumbAware { @Override public void runActivity(@NotNull Project project) { + DotNetProvider.getInstance(project); CSharpierProcessProvider.getInstance(project); ApplicationManager.getApplication().getService(ReformatWithCSharpierOnSave.class); } diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java index 95a242357..d8b218ff7 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/CustomPathInstaller.java @@ -1,20 +1,24 @@ package com.intellij.csharpier; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import org.apache.commons.lang.SystemUtils; import java.io.File; import java.nio.file.Path; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.regex.Pattern; public class CustomPathInstaller { + private final DotNetProvider dotNetProvider; Logger logger = CSharpierLogger.getInstance(); String customPath; - public CustomPathInstaller(CSharpierSettings settings) { - this.customPath = settings.getCustomPath(); + public CustomPathInstaller(Project project) { + this.customPath = CSharpierSettings.getInstance(project).getCustomPath(); + this.dotNetProvider = DotNetProvider.getInstance(project); } public boolean ensureVersionInstalled(String version) throws Exception { @@ -39,21 +43,20 @@ public boolean ensureVersionInstalled(String version) throws Exception { deleteDirectory(directoryForVersion); } - var command = new String[]{"dotnet", "tool", "install", "csharpier", "--version", version, "--tool-path", pathToDirectoryForVersion}; - ProcessHelper.ExecuteCommand(command, null, null); + var command = List.of("tool", "install", "csharpier", "--version", version, "--tool-path", pathToDirectoryForVersion); + this.dotNetProvider.execDotNet(command, null); return this.validateInstall(pathToDirectoryForVersion, version); } private boolean validateInstall(String pathToDirectoryForVersion, String version) { try { - Map env = new HashMap<>(); - env.put("DOTNET_NOLOGO", "1"); + var env = Map.of("DOTNET_ROOT", this.dotNetProvider.getDotNetROot()); - var command = new String[] { this.getPathForVersion(version), "--version" }; - var output = ProcessHelper.ExecuteCommand(command, env, new File(pathToDirectoryForVersion)).trim(); + var command = List.of(this.getPathForVersion(version), "--version" ); + var output = ProcessHelper.executeCommand(command, env, new File(pathToDirectoryForVersion)).trim(); - this.logger.debug("dotnet csharpier --version output: " + version); + this.logger.debug(this.getPathForVersion(version) +"--version output: " + version); var versionWithoutHash = output.split(Pattern.quote("+"))[0]; this.logger.debug("Using " + versionWithoutHash + " as the version number."); diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/DotNetProvider.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/DotNetProvider.java new file mode 100644 index 000000000..220e1202d --- /dev/null +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/DotNetProvider.java @@ -0,0 +1,76 @@ +package com.intellij.csharpier; + +import com.intellij.notification.NotificationGroupManager; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.jetbrains.rider.runtime.RiderDotNetActiveRuntimeHost; +import com.jetbrains.rider.runtime.dotNetCore.DotNetCoreRuntime; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Map; +import java.util.List; + +public class DotNetProvider { + private final Logger logger = CSharpierLogger.getInstance(); + private final Project project; + private String dotNetRoot; + private DotNetCoreRuntime dotNetCoreRuntime; + + public DotNetProvider(@NotNull Project project) { + this.project = project; + + var foundDotNet = this.findDotNet(); + if (!foundDotNet) { + + var title = "CSharpier unable to run dotnet commands"; + var message = "CSharpier was unable to determine how to run dotnet commands. Ensure that '.NET CLI executable path' is set properly in your settings and restart."; + var notification = NotificationGroupManager.getInstance().getNotificationGroup("CSharpier") + .createNotification(title, message, NotificationType.WARNING); + notification.notify(this.project); + } + } + + static DotNetProvider getInstance(@NotNull Project project) { + return project.getService(DotNetProvider.class); + } + + private boolean findDotNet() { + try { + this.dotNetCoreRuntime = RiderDotNetActiveRuntimeHost.Companion.getInstance(project).getDotNetCoreRuntime().getValue(); + + if (dotNetCoreRuntime.getCliExePath() != null) { + logger.debug("Using dotnet found from RiderDotNetActiveRuntimeHost at " + dotNetCoreRuntime.getCliExePath()); + } else { + return false; + } + + dotNetRoot = Paths.get(dotNetCoreRuntime.getCliExePath()).getParent().toString(); + + return true; + } catch (Exception ex) { + logger.error(ex); + + return false; + } + } + + public String execDotNet(List command, File workingDirectory) { + var commands = new ArrayList<>(command); + commands.add(0, this.dotNetCoreRuntime.getCliExePath()); + + var env = Map.of( + "DOTNET_NOLOGO", "1", + "DOTNET_CLI_TELEMETRY_OPTOUT", "1", + "DOTNET_SKIP_FIRST_TIME_EXPERIENCE", "1"); + + return ProcessHelper.executeCommand(commands, env, workingDirectory); + } + + public String getDotNetROot() { + return this.dotNetRoot; + } +} diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallGlobalAction.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallGlobalAction.java index 1ffdbade8..1c2393f21 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallGlobalAction.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallGlobalAction.java @@ -3,26 +3,32 @@ import com.intellij.notification.Notification; import com.intellij.notification.NotificationAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsContexts; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + public class InstallGlobalAction extends NotificationAction { private final IProcessKiller processKiller; + private final DotNetProvider dotNetProvider; public InstallGlobalAction( @Nullable @NlsContexts.NotificationContent String text, - IProcessKiller processKiller + IProcessKiller processKiller, + Project project ) { super(text); this.processKiller = processKiller; + this.dotNetProvider = DotNetProvider.getInstance(project); } @Override public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) { - var command2 = new String[]{"dotnet", "tool", "install", "-g", "csharpier"}; - ProcessHelper.ExecuteCommand(command2, null, null); + var command = List.of("tool", "install", "-g", "csharpier"); + this.dotNetProvider.execDotNet(command, null); this.processKiller.killRunningProcesses(); notification.expire(); diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallLocalAction.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallLocalAction.java index 8e976a27d..900f537db 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallLocalAction.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallLocalAction.java @@ -4,26 +4,30 @@ import com.intellij.notification.NotificationAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsContexts; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.nio.file.Path; +import java.util.List; public class InstallLocalAction extends NotificationAction { + private final DotNetProvider dotNetProvider; private Logger logger = CSharpierLogger.getInstance(); private final IProcessKiller processKiller; private final String projectPath; public InstallLocalAction( @Nullable @NlsContexts.NotificationContent String text, - String projectPath, - IProcessKiller processKiller + IProcessKiller processKiller, + Project project ) { super(text); - this.projectPath = projectPath; + this.projectPath = project.getBasePath(); this.processKiller = processKiller; + this.dotNetProvider = DotNetProvider.getInstance(project); } @Override @@ -32,12 +36,12 @@ public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification noti this.logger.info("Installing csharpier in " + manifestPath); if (!new File(manifestPath).exists()) { - var command = new String[]{"dotnet", "new", "tool-manifest"}; - ProcessHelper.ExecuteCommand(command, null, new File(this.projectPath)); + var command = List.of("new", "tool-manifest"); + this.dotNetProvider.execDotNet(command, new File(this.projectPath)); } - var command2 = new String[]{"dotnet", "tool", "install", "csharpier"}; - ProcessHelper.ExecuteCommand(command2, null, new File(this.projectPath)); + var command2 = List.of("tool", "install", "csharpier"); + this.dotNetProvider.execDotNet(command2, new File(this.projectPath)); this.processKiller.killRunningProcesses(); notification.expire(); diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallerService.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallerService.java index 08490c841..fd6a842f4 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallerService.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/InstallerService.java @@ -38,10 +38,10 @@ public void displayInstallNeededMessage(String directoryThatContainsFile, IProce var notification = NotificationGroupManager.getInstance().getNotificationGroup("CSharpier") .createNotification(message, NotificationType.WARNING); - notification.addAction(new InstallGlobalAction("Install CSharpier Globally", processKiller)); + notification.addAction(new InstallGlobalAction("Install CSharpier Globally", processKiller, this.project)); if (!isOnlyGlobal) { notification.addAction( - new InstallLocalAction("Install CSharpier Locally", project.getBasePath(), processKiller) + new InstallLocalAction("Install CSharpier Locally", processKiller, project) ); } diff --git a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/ProcessHelper.java b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/ProcessHelper.java index 8e9c014ab..374f936b1 100644 --- a/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/ProcessHelper.java +++ b/Src/CSharpier.Rider/src/main/java/com/intellij/csharpier/ProcessHelper.java @@ -1,26 +1,25 @@ package com.intellij.csharpier; -import org.apache.commons.lang.SystemUtils; import java.io.*; import java.util.HashMap; +import java.util.List; import java.util.Map; public class ProcessHelper { - public static String ExecuteCommand(String[] command, Map env, File workingDirectory) { + public static String executeCommand(List command, Map env, File workingDirectory) { var logger = CSharpierLogger.getInstance(); try { var directoryToLog = workingDirectory == null ? "" : " in " + workingDirectory; logger.debug("Running " + String.join(" ", command) + directoryToLog); - var processBuilder = new ProcessBuilder(GetShellCommandIfNeeded(command)); + var processBuilder = new ProcessBuilder(command); if (env == null) { env = new HashMap<>(); } - - if (!env.containsKey("PATH")) { - env.put("PATH", GetPathWithDotNetBinary()); + else { + env = new HashMap<>(env); } processBuilder.environment().putAll(env); @@ -50,35 +49,8 @@ public static String ExecuteCommand(String[] command, Map env, F } logger.debug(errorResult.toString()); } catch (Exception e) { - logger.error(e.getMessage()); - e.printStackTrace(); - + logger.error(e); } return null; } - - private static String GetPathWithDotNetBinary() { - var path = System.getenv("PATH"); - - // For Mac, the .NET binary isn't available for ProcessBuilder, so we'll add the default - // installation location to the PATH. We'll prefer the ARM version and fallback to the x64. - if (SystemUtils.IS_OS_MAC) { - return path + ":/usr/local/share/dotnet:/usr/local/share/dotnet/x64/dotnet"; - } - - // For others, it seems the .NET binary is already available to ProcessBuilder by default. - // So we'll just return the PATH as is. - return path; - } - - // For Mac, we'll have updated the PATH to include the .NET binary. However, setting - // the PATH doesn't affect the ProcessBuilder's command, but it will apply to - // spawned processes, so we'll run the desired command in the OS's default shell. - private static String[] GetShellCommandIfNeeded(String[] command) { - if (SystemUtils.IS_OS_MAC) { - return new String[] {"/bin/zsh", "-c", String.join(" ", command)}; - } - - return command; - } } diff --git a/Src/CSharpier.Rider/src/main/resources/META-INF/plugin.xml b/Src/CSharpier.Rider/src/main/resources/META-INF/plugin.xml index 2a5b7710e..702c53703 100644 --- a/Src/CSharpier.Rider/src/main/resources/META-INF/plugin.xml +++ b/Src/CSharpier.Rider/src/main/resources/META-INF/plugin.xml @@ -8,6 +8,7 @@ +