You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Merge pull request #106031 from samuelll3d/fix-slnpath-resolve
C#: Fix loading correct solution file for projects in subdirectories
This commit is contained in:
@@ -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