summaryrefslogtreecommitdiffstats
path: root/modules/mono
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2023-07-08 18:19:01 +0200
committerRémi Verschelde <rverschelde@gmail.com>2023-07-08 18:19:01 +0200
commit4a3c6629be0af0c05738e8d4ae5eb466ff350363 (patch)
tree4e042972cfb3eafffe33387b63e27ca9a6af14b6 /modules/mono
parent43c0fa7f4b2f1049e8f00501aebd6f065043b943 (diff)
parentbf3af9fd48aceda699bb558558bd805a7e522760 (diff)
downloadredot-engine-4a3c6629be0af0c05738e8d4ae5eb466ff350363.tar.gz
Merge pull request #78832 from van800/path_locator_4x
Update the RiderPathLocator to support the JetBrains Toolbox 2.0
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs51
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs474
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs8
4 files changed, 60 insertions, 476 deletions
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index 30525ba04a..4a0b7f9bed 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -28,10 +28,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
+ <PackageReference Include="JetBrains.Rider.PathLocator" Version="1.0.1" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
- <!-- For RiderPathLocator -->
- <PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<Reference Include="GodotSharp">
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
<Private>False</Private>
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs
new file mode 100644
index 0000000000..7e08d8c01d
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderLocatorEnvironment.cs
@@ -0,0 +1,51 @@
+using System;
+using Godot;
+using JetBrains.Rider.PathLocator;
+using Newtonsoft.Json;
+using OS = GodotTools.Utils.OS;
+
+namespace GodotTools.Ides.Rider;
+
+public class RiderLocatorEnvironment : IRiderLocatorEnvironment
+{
+ public JetBrains.Rider.PathLocator.OS CurrentOS
+ {
+ get
+ {
+ if (OS.IsWindows)
+ return JetBrains.Rider.PathLocator.OS.Windows;
+ if (OS.IsMacOS) return JetBrains.Rider.PathLocator.OS.MacOSX;
+ if (OS.IsUnixLike) return JetBrains.Rider.PathLocator.OS.Linux;
+ return JetBrains.Rider.PathLocator.OS.Other;
+ }
+ }
+
+ public T FromJson<T>(string json)
+ {
+ return JsonConvert.DeserializeObject<T>(json);
+ }
+
+ public void Info(string message, Exception e = null)
+ {
+ if (e == null)
+ GD.Print(message);
+ else
+ GD.Print(message, e);
+ }
+
+ public void Warn(string message, Exception e = null)
+ {
+ if (e == null)
+ GD.PushWarning(message);
+ else
+ GD.PushWarning(message, e);
+ }
+
+ public void Error(string message, Exception e = null)
+ {
+ if (e == null)
+ GD.PushError(message);
+ else
+ GD.PushError(message, e);
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
deleted file mode 100644
index dad6e35344..0000000000
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs
+++ /dev/null
@@ -1,474 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Linq;
-using System.Runtime.Versioning;
-using Godot;
-using Microsoft.Win32;
-using Newtonsoft.Json;
-using Directory = System.IO.Directory;
-using Environment = System.Environment;
-using File = System.IO.File;
-using Path = System.IO.Path;
-using OS = GodotTools.Utils.OS;
-
-// ReSharper disable UnassignedField.Local
-// ReSharper disable InconsistentNaming
-// ReSharper disable UnassignedField.Global
-// ReSharper disable MemberHidesStaticFromOuterClass
-
-namespace GodotTools.Ides.Rider
-{
- /// <summary>
- /// This code is a modified version of the JetBrains resharper-unity plugin listed under Apache License 2.0 license:
- /// https://github.com/JetBrains/resharper-unity/blob/master/unity/JetBrains.Rider.Unity.Editor/EditorPlugin/RiderPathLocator.cs
- /// </summary>
- public static class RiderPathLocator
- {
- public static RiderInfo[] GetAllRiderPaths()
- {
- try
- {
- if (OS.IsWindows)
- {
- return CollectRiderInfosWindows();
- }
- if (OS.IsMacOS)
- {
- return CollectRiderInfosMac();
- }
- if (OS.IsUnixLike)
- {
- return CollectAllRiderPathsLinux();
- }
- throw new InvalidOperationException("Unexpected OS.");
- }
- catch (Exception e)
- {
- GD.PushWarning(e.Message);
- }
-
- return Array.Empty<RiderInfo>();
- }
-
- private static RiderInfo[] CollectAllRiderPathsLinux()
- {
- var installInfos = new List<RiderInfo>();
- string home = Environment.GetEnvironmentVariable("HOME");
- if (!string.IsNullOrEmpty(home))
- {
- string toolboxRiderRootPath = GetToolboxBaseDir();
- installInfos.AddRange(CollectPathsFromToolbox(toolboxRiderRootPath, "bin", "rider.sh", false)
- .Select(a => new RiderInfo(a, true)).ToList());
-
- //$Home/.local/share/applications/jetbrains-rider.desktop
- var shortcut = new FileInfo(Path.Combine(home, @".local/share/applications/jetbrains-rider.desktop"));
-
- if (shortcut.Exists)
- {
- string[] lines = File.ReadAllLines(shortcut.FullName);
- foreach (string line in lines)
- {
- if (!line.StartsWith("Exec=\""))
- continue;
- string path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault();
- if (string.IsNullOrEmpty(path))
- continue;
-
- if (installInfos.Any(a => a.Path == path)) // avoid adding similar build as from toolbox
- continue;
- installInfos.Add(new RiderInfo(path, false));
- }
- }
- }
-
- // snap install
- string snapInstallPath = "/snap/rider/current/bin/rider.sh";
- if (new FileInfo(snapInstallPath).Exists)
- installInfos.Add(new RiderInfo(snapInstallPath, false));
-
- return installInfos.ToArray();
- }
-
- private static RiderInfo[] CollectRiderInfosMac()
- {
- var installInfos = new List<RiderInfo>();
- // "/Applications/*Rider*.app"
- // should be combined with "Contents/MacOS/rider"
- var folder = new DirectoryInfo("/Applications");
- if (folder.Exists)
- {
- installInfos.AddRange(folder.GetDirectories("*Rider*.app")
- .Select(a => new RiderInfo(Path.Combine(a.FullName, "Contents/MacOS/rider"), false))
- .ToList());
- }
-
- // /Users/user/Library/Application Support/JetBrains/Toolbox/apps/Rider/ch-1/181.3870.267/Rider EAP.app
- // should be combined with "Contents/MacOS/rider"
- string toolboxRiderRootPath = GetToolboxBaseDir();
- var paths = CollectPathsFromToolbox(toolboxRiderRootPath, "", "Rider*.app", true)
- .Select(a => new RiderInfo(Path.Combine(a, "Contents/MacOS/rider"), true));
- installInfos.AddRange(paths);
-
- return installInfos.ToArray();
- }
-
- [SupportedOSPlatform("windows")]
- private static RiderInfo[] CollectRiderInfosWindows()
- {
- var installInfos = new List<RiderInfo>();
- var toolboxRiderRootPath = GetToolboxBaseDir();
- var installPathsToolbox = CollectPathsFromToolbox(toolboxRiderRootPath, "bin", "rider64.exe", false).ToList();
- installInfos.AddRange(installPathsToolbox.Select(a => new RiderInfo(a, true)).ToList());
-
- var installPaths = new List<string>();
- const string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
- CollectPathsFromRegistry(registryKey, installPaths);
- const string wowRegistryKey = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall";
- CollectPathsFromRegistry(wowRegistryKey, installPaths);
-
- installInfos.AddRange(installPaths.Select(a => new RiderInfo(a, false)).ToList());
-
- return installInfos.ToArray();
- }
-
- private static string GetToolboxBaseDir()
- {
- if (OS.IsWindows)
- {
- string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
- return GetToolboxRiderRootPath(localAppData);
- }
-
- if (OS.IsMacOS)
- {
- var home = Environment.GetEnvironmentVariable("HOME");
- if (string.IsNullOrEmpty(home))
- return string.Empty;
- var localAppData = Path.Combine(home, @"Library/Application Support");
- return GetToolboxRiderRootPath(localAppData);
- }
-
- if (OS.IsUnixLike)
- {
- var home = Environment.GetEnvironmentVariable("HOME");
- if (string.IsNullOrEmpty(home))
- return string.Empty;
- var localAppData = Path.Combine(home, @".local/share");
- return GetToolboxRiderRootPath(localAppData);
- }
-
- return string.Empty;
- }
-
-
- private static string GetToolboxRiderRootPath(string localAppData)
- {
- var toolboxPath = Path.Combine(localAppData, @"JetBrains/Toolbox");
- var settingsJson = Path.Combine(toolboxPath, ".settings.json");
-
- if (File.Exists(settingsJson))
- {
- var path = SettingsJson.GetInstallLocationFromJson(File.ReadAllText(settingsJson));
- if (!string.IsNullOrEmpty(path))
- toolboxPath = path;
- }
-
- var toolboxRiderRootPath = Path.Combine(toolboxPath, @"apps/Rider");
- return toolboxRiderRootPath;
- }
-
- internal static ProductInfo GetBuildVersion(string path)
- {
- var buildTxtFileInfo = new FileInfo(Path.Combine(path, GetRelativePathToBuildTxt()));
- var dir = buildTxtFileInfo.DirectoryName;
- if (!Directory.Exists(dir))
- return null;
- var buildVersionFile = new FileInfo(Path.Combine(dir, "product-info.json"));
- if (!buildVersionFile.Exists)
- return null;
- var json = File.ReadAllText(buildVersionFile.FullName);
- return ProductInfo.GetProductInfo(json);
- }
-
- internal static Version GetBuildNumber(string path)
- {
- var file = new FileInfo(Path.Combine(path, GetRelativePathToBuildTxt()));
- if (!file.Exists)
- return null;
- var text = File.ReadAllText(file.FullName);
- if (text.Length <= 3)
- return null;
-
- var versionText = text.Substring(3);
- return Version.TryParse(versionText, out var v) ? v : null;
- }
-
- internal static bool IsToolbox(string path)
- {
- return path.StartsWith(GetToolboxBaseDir());
- }
-
- private static string GetRelativePathToBuildTxt()
- {
- if (OS.IsWindows || OS.IsUnixLike)
- return "../../build.txt";
- if (OS.IsMacOS)
- return "Contents/Resources/build.txt";
- throw new InvalidOperationException("Unknown OS.");
- }
-
- [SupportedOSPlatform("windows")]
- private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
- {
- using (var key = Registry.CurrentUser.OpenSubKey(registryKey))
- {
- CollectPathsFromRegistry(installPaths, key);
- }
- using (var key = Registry.LocalMachine.OpenSubKey(registryKey))
- {
- CollectPathsFromRegistry(installPaths, key);
- }
- }
-
- [SupportedOSPlatform("windows")]
- private static void CollectPathsFromRegistry(List<string> installPaths, RegistryKey key)
- {
- if (key == null) return;
- foreach (var subkeyName in key.GetSubKeyNames().Where(a => a.Contains("Rider")))
- {
- using (var subkey = key.OpenSubKey(subkeyName))
- {
- var folderObject = subkey?.GetValue("InstallLocation");
- if (folderObject == null) continue;
- var folder = folderObject.ToString();
- var possiblePath = Path.Combine(folder, @"bin\rider64.exe");
- if (File.Exists(possiblePath))
- installPaths.Add(possiblePath);
- }
- }
- }
-
- private static string[] CollectPathsFromToolbox(string toolboxRiderRootPath, string dirName, string searchPattern,
- bool isMac)
- {
- if (!Directory.Exists(toolboxRiderRootPath))
- return Array.Empty<string>();
-
- var channelDirs = Directory.GetDirectories(toolboxRiderRootPath);
- var paths = channelDirs.SelectMany(channelDir =>
- {
- try
- {
- // use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D
- var historyFile = Path.Combine(channelDir, ".history.json");
- if (File.Exists(historyFile))
- {
- var json = File.ReadAllText(historyFile);
- var build = ToolboxHistory.GetLatestBuildFromJson(json);
- if (build != null)
- {
- var buildDir = Path.Combine(channelDir, build);
- var executablePaths = GetExecutablePaths(dirName, searchPattern, isMac, buildDir);
- if (executablePaths.Any())
- return executablePaths;
- }
- }
-
- var channelFile = Path.Combine(channelDir, ".channel.settings.json");
- if (File.Exists(channelFile))
- {
- var json = File.ReadAllText(channelFile).Replace("active-application", "active_application");
- var build = ToolboxInstallData.GetLatestBuildFromJson(json);
- if (build != null)
- {
- var buildDir = Path.Combine(channelDir, build);
- var executablePaths = GetExecutablePaths(dirName, searchPattern, isMac, buildDir);
- if (executablePaths.Any())
- return executablePaths;
- }
- }
-
- // changes in toolbox json files format may brake the logic above, so return all found Rider installations
- return Directory.GetDirectories(channelDir)
- .SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir));
- }
- catch (Exception e)
- {
- // do not write to Debug.Log, just log it.
- Logger.Warn($"Failed to get RiderPath from {channelDir}", e);
- }
-
- return Array.Empty<string>();
- })
- .Where(c => !string.IsNullOrEmpty(c))
- .ToArray();
- return paths;
- }
-
- private static string[] GetExecutablePaths(string dirName, string searchPattern, bool isMac, string buildDir)
- {
- var folder = new DirectoryInfo(Path.Combine(buildDir, dirName));
- if (!folder.Exists)
- return Array.Empty<string>();
-
- if (!isMac)
- return new[] { Path.Combine(folder.FullName, searchPattern) }.Where(File.Exists).ToArray();
- return folder.GetDirectories(searchPattern).Select(f => f.FullName)
- .Where(Directory.Exists).ToArray();
- }
-
- // Disable the "field is never assigned" compiler warning. We never assign it, but Unity does.
- // Note that Unity disable this warning in the generated C# projects
-#pragma warning disable 0649
-
- [Serializable]
- class SettingsJson
- {
- public string install_location;
-
- [return: MaybeNull]
- public static string GetInstallLocationFromJson(string json)
- {
- try
- {
- return JsonConvert.DeserializeObject<SettingsJson>(json).install_location;
- }
- catch (Exception)
- {
- Logger.Warn($"Failed to get install_location from json {json}");
- }
-
- return null;
- }
- }
-
- [Serializable]
- class ToolboxHistory
- {
- public List<ItemNode> history;
-
- public static string GetLatestBuildFromJson(string json)
- {
- try
- {
- return JsonConvert.DeserializeObject<ToolboxHistory>(json).history.LastOrDefault()?.item.build;
- }
- catch (Exception)
- {
- Logger.Warn($"Failed to get latest build from json {json}");
- }
-
- return null;
- }
- }
-
- [Serializable]
- class ItemNode
- {
- public BuildNode item;
- }
-
- [Serializable]
- class BuildNode
- {
- public string build;
- }
-
- [Serializable]
- public class ProductInfo
- {
- public string version;
- public string versionSuffix;
-
- [return: MaybeNull]
- internal static ProductInfo GetProductInfo(string json)
- {
- try
- {
- var productInfo = JsonConvert.DeserializeObject<ProductInfo>(json);
- return productInfo;
- }
- catch (Exception)
- {
- Logger.Warn($"Failed to get version from json {json}");
- }
-
- return null;
- }
- }
-
- // ReSharper disable once ClassNeverInstantiated.Global
- [Serializable]
- class ToolboxInstallData
- {
- // ReSharper disable once InconsistentNaming
- public ActiveApplication active_application;
-
- [return: MaybeNull]
- public static string GetLatestBuildFromJson(string json)
- {
- try
- {
- var toolbox = JsonConvert.DeserializeObject<ToolboxInstallData>(json);
- var builds = toolbox.active_application.builds;
- if (builds != null && builds.Any())
- return builds.First();
- }
- catch (Exception)
- {
- Logger.Warn($"Failed to get latest build from json {json}");
- }
-
- return null;
- }
- }
-
- [Serializable]
- class ActiveApplication
- {
- public List<string> builds;
- }
-
-#pragma warning restore 0649
-
- public struct RiderInfo
- {
- // ReSharper disable once NotAccessedField.Global
- public bool IsToolbox;
- public string Presentation;
- public Version BuildNumber;
- public ProductInfo ProductInfo;
- public string Path;
-
- public RiderInfo(string path, bool isToolbox)
- {
- BuildNumber = GetBuildNumber(path);
- ProductInfo = GetBuildVersion(path);
- Path = new FileInfo(path).FullName; // normalize separators
- var presentation = $"Rider {BuildNumber}";
-
- if (ProductInfo != null && !string.IsNullOrEmpty(ProductInfo.version))
- {
- var suffix = string.IsNullOrEmpty(ProductInfo.versionSuffix) ? "" : $" {ProductInfo.versionSuffix}";
- presentation = $"Rider {ProductInfo.version}{suffix}";
- }
-
- if (isToolbox)
- presentation += " (JetBrains Toolbox)";
-
- Presentation = presentation;
- IsToolbox = isToolbox;
- }
- }
-
- private static class Logger
- {
- internal static void Warn(string message, Exception e = null)
- {
- throw new Exception(message, e);
- }
- }
- }
-}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
index f55ca4c7d7..5c09f1f83a 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs
@@ -4,11 +4,19 @@ using System.IO;
using System.Linq;
using Godot;
using GodotTools.Internals;
+using JetBrains.Rider.PathLocator;
namespace GodotTools.Ides.Rider
{
public static class RiderPathManager
{
+ private static readonly RiderPathLocator RiderPathLocator;
+
+ static RiderPathManager()
+ {
+ RiderPathLocator = new RiderPathLocator(new RiderLocatorEnvironment());
+ }
+
public static readonly string EditorPathSettingName = "dotnet/editor/editor_path_optional";
private static string GetRiderPathFromSettings()