You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Find solution file by project assembly name
Instead of looking for a solution file with the same name as the project and its assembly, this commit updates the logic to find all .sln and .slnx files in the specified solution directory. If no matching solution is found, it will fall back to the old behaviour. This commit will also consider .. markings to go up one directory level allowing for Godot projects as part of multi-project solutions. Co-authored-by: Eric Johnson <eric.johnson@revention.com>
This commit is contained in:
committed by
Rémi Verschelde
parent
07f4c06601
commit
b53af55462
@@ -37,6 +37,7 @@
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.11.0" />
|
||||
<PackageReference Include="JetBrains.Rider.PathLocator" Version="1.0.12" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.SolutionPersistence" Version="1.0.52" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<Reference Include="GodotSharp">
|
||||
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
using GodotTools.Core;
|
||||
using static GodotTools.Internals.Globals;
|
||||
using Microsoft.VisualStudio.SolutionPersistence;
|
||||
using Microsoft.VisualStudio.SolutionPersistence.Serializer;
|
||||
|
||||
namespace GodotTools.Internals
|
||||
{
|
||||
@@ -73,17 +76,70 @@ namespace GodotTools.Internals
|
||||
string? slnParentDir = (string?)ProjectSettings.GetSetting("dotnet/project/solution_directory");
|
||||
if (string.IsNullOrEmpty(slnParentDir))
|
||||
slnParentDir = "res://";
|
||||
else if (!slnParentDir.StartsWith("res://", System.StringComparison.Ordinal))
|
||||
else if (!slnParentDir.StartsWith("res://", StringComparison.Ordinal))
|
||||
slnParentDir = "res://" + slnParentDir;
|
||||
|
||||
// The csproj should be in the same folder as project.godot.
|
||||
string csprojParentDir = "res://";
|
||||
|
||||
_projectSlnPath = Path.Combine(ProjectSettings.GlobalizePath(slnParentDir),
|
||||
string.Concat(_projectAssemblyName, ".sln"));
|
||||
|
||||
// Set csproj path first and use it to find the sln/slnx file with the assembly
|
||||
_projectCsProjPath = Path.Combine(ProjectSettings.GlobalizePath(csprojParentDir),
|
||||
string.Concat(_projectAssemblyName, ".csproj"));
|
||||
|
||||
_projectSlnPath = FindSolutionFileWithAssemblyName(slnParentDir, _projectAssemblyName);
|
||||
}
|
||||
|
||||
private static string FindSolutionFileWithAssemblyName(string directory, string assemblyName)
|
||||
{
|
||||
// Will convert ".." to load solutions from parent directory when appropriate
|
||||
string slnAbsolutePath = Path.GetFullPath(ProjectSettings.GlobalizePath(directory));
|
||||
|
||||
List<string> solutionFilePaths = new();
|
||||
solutionFilePaths.AddRange(Directory.GetFiles(slnAbsolutePath, "*.sln"));
|
||||
solutionFilePaths.AddRange(Directory.GetFiles(slnAbsolutePath, "*.slnx"));
|
||||
|
||||
if (solutionFilePaths.Count == 0)
|
||||
return Path.Combine(slnAbsolutePath, $"{assemblyName}.sln");
|
||||
|
||||
List<string> matchingSolutions = new();
|
||||
|
||||
foreach (string solutionFilePath in solutionFilePaths)
|
||||
{
|
||||
ISolutionSerializer? serializer = SolutionSerializers.GetSerializerByMoniker(solutionFilePath);
|
||||
if (serializer is null)
|
||||
continue;
|
||||
|
||||
string? solutionDirectory = Path.GetDirectoryName(solutionFilePath);
|
||||
if (solutionDirectory is null)
|
||||
continue;
|
||||
|
||||
var solution = serializer.OpenAsync(solutionFilePath, CancellationToken.None).Result;
|
||||
|
||||
foreach (var project in solution.SolutionProjects)
|
||||
{
|
||||
// Convert '\' path separators on Windows to '/' to match Godot's Unix style separators
|
||||
var absoluteProjectFilePath = Path.GetFullPath(project.FilePath, solutionDirectory).Replace('\\', '/');
|
||||
|
||||
if (string.Equals(absoluteProjectFilePath, _projectCsProjPath, StringComparison.Ordinal))
|
||||
matchingSolutions.Add(solutionFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
switch (matchingSolutions.Count)
|
||||
{
|
||||
case 1:
|
||||
return matchingSolutions[0];
|
||||
|
||||
case > 1:
|
||||
GD.PushError(
|
||||
$"Multiple solutions containing a project with assembly name '{assemblyName}' were found:\n"
|
||||
+ $"{string.Join('\n', matchingSolutions).Replace('\\', '/')}\n"
|
||||
+ "Please ensure only one solution contains the project assembly.\n"
|
||||
+ "If you have recently migrated to .slnx please ensure that you have removed the unused .sln.");
|
||||
break;
|
||||
}
|
||||
|
||||
return Path.Combine(slnAbsolutePath, $"{assemblyName}.sln");
|
||||
}
|
||||
|
||||
private static string? _projectAssemblyName;
|
||||
|
||||
Reference in New Issue
Block a user