Add support for Rider 2021, use latest detected version of Rider

Handles additional registry location where installation paths are stored
for Rider 2021. The detected installations are now sorted by version, so
the latest detected version is always used when opening the scripts
project.
This commit is contained in:
GoaLitiuM
2021-05-26 19:56:39 +03:00
parent 64a8408600
commit a6ed117088

View File

@@ -10,12 +10,24 @@
#if PLATFORM_WINDOWS
#include "Engine/Core/Collections/Sorting.h"
#include "Engine/Platform/File.h"
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
#include "Engine/Serialization/Json.h"
namespace
{
struct RiderInstallation
{
String path;
String version;
RiderInstallation(const String& path_, const String& version_)
: path(path_), version(version_)
{
}
};
bool FindRegistryKeyItems(HKEY hKey, Array<String>& results)
{
Char nameBuffer[256];
@@ -31,7 +43,7 @@ namespace
return true;
}
void SearchDirectory(Array<CodeEditor*>* output, const String& directory)
void SearchDirectory(Array<RiderInstallation*>* installations, const String& directory)
{
if (!FileSystem::DirectoryExists(directory))
return;
@@ -46,24 +58,29 @@ namespace
if (document.HasParseError())
return;
// Find version
auto versionMember = document.FindMember("version");
if (versionMember == document.MemberEnd())
return;
// Find executable file path
auto launchMember = document.FindMember("launch");
if (launchMember != document.MemberEnd() && launchMember->value.IsArray() && launchMember->value.Size() > 0)
{
auto launcherPathMember = launchMember->value[0].FindMember("launcherPath");
if (launcherPathMember != launchMember->value[0].MemberEnd())
{
auto launcherPath = launcherPathMember->value.GetText();
auto exePath = directory / launcherPath;
if (launcherPath.HasChars() && FileSystem::FileExists(exePath))
{
output->Add(New<RiderCodeEditor>(exePath));
}
}
}
if (launchMember == document.MemberEnd() || !launchMember->value.IsArray() || launchMember->value.Size() == 0)
return;
auto launcherPathMember = launchMember->value[0].FindMember("launcherPath");
if (launcherPathMember == launchMember->value[0].MemberEnd())
return;
auto launcherPath = launcherPathMember->value.GetText();
auto exePath = directory / launcherPath;
if (!launcherPath.HasChars() || !FileSystem::FileExists(exePath))
return;
installations->Add(New<RiderInstallation>(exePath, versionMember->value.GetText()));
}
void SearchRegistry(Array<CodeEditor*>* output, HKEY root, const Char* key)
void SearchRegistry(Array<RiderInstallation*>* installations, HKEY root, const Char* key, const Char* valueName = TEXT(""))
{
// Open key
HKEY keyH;
@@ -83,14 +100,14 @@ namespace
// Read subkey value
DWORD type;
DWORD cbData;
if (RegQueryValueExW(subKeyH, TEXT(""), nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS || type != REG_SZ)
if (RegQueryValueExW(subKeyH, valueName, nullptr, &type, nullptr, &cbData) != ERROR_SUCCESS || type != REG_SZ)
{
RegCloseKey(subKeyH);
continue;
}
Array<Char> data;
data.Resize((int32)cbData / sizeof(Char));
if (RegQueryValueExW(subKeyH, TEXT(""), nullptr, nullptr, reinterpret_cast<LPBYTE>(data.Get()), &cbData) != ERROR_SUCCESS)
if (RegQueryValueExW(subKeyH, valueName, nullptr, nullptr, reinterpret_cast<LPBYTE>(data.Get()), &cbData) != ERROR_SUCCESS)
{
RegCloseKey(subKeyH);
continue;
@@ -98,7 +115,7 @@ namespace
// Check if it's a valid installation path
String path(data.Get(), data.Count() - 1);
SearchDirectory(output, path);
SearchDirectory(installations, path);
RegCloseKey(subKeyH);
}
@@ -108,6 +125,31 @@ namespace
}
}
bool sortInstallations(RiderInstallation* const& i1, RiderInstallation* const& i2)
{
Array<String> values1, values2;
i1->version.Split('.', values1);
i2->version.Split('.', values2);
int32 version1[3] = { 0 };
int32 version2[3] = { 0 };
StringUtils::Parse(values1[0].Get(), &version1[0]);
StringUtils::Parse(values1[1].Get(), &version1[1]);
StringUtils::Parse(values1[2].Get(), &version1[2]);
StringUtils::Parse(values2[0].Get(), &version2[0]);
StringUtils::Parse(values2[1].Get(), &version2[1]);
StringUtils::Parse(values2[2].Get(), &version2[2]);
// Compare by MAJOR.MINOR.BUILD
if (version1[0] == version2[0])
{
if (version1[1] == version2[1])
return version1[2] > version2[2];
return version1[1] > version2[1];
}
return version1[0] > version2[0];
}
#endif
RiderCodeEditor::RiderCodeEditor(const String& execPath)
@@ -119,8 +161,23 @@ RiderCodeEditor::RiderCodeEditor(const String& execPath)
void RiderCodeEditor::FindEditors(Array<CodeEditor*>* output)
{
#if PLATFORM_WINDOWS
SearchRegistry(output, HKEY_CURRENT_USER, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
SearchRegistry(output, HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
Array<RiderInstallation*> installations;
// For versions 2021 or later
SearchRegistry(&installations, HKEY_CURRENT_USER, TEXT("SOFTWARE\\JetBrains\\Rider"), TEXT("InstallDir"));
// For versions 2020 or earlier
SearchRegistry(&installations, HKEY_CURRENT_USER, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
SearchRegistry(&installations, HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\WOW6432Node\\JetBrains\\JetBrains Rider"));
// Sort found installations by version number
Sorting::QuickSort(installations.Get(), installations.Count(), &sortInstallations);
for (RiderInstallation* installation : installations)
{
output->Add(New<RiderCodeEditor>(installation->path));
Delete(installation);
}
#endif
}