1
0
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:
samuelll3d
2025-06-28 15:02:46 +03:00
committed by Rémi Verschelde
parent 07f4c06601
commit b53af55462
2 changed files with 63 additions and 6 deletions

View File

@@ -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>

View File

@@ -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;