diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index f663fe1..4c7f8fb 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,6 +13,6 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 6.0.x
+ dotnet-version: 10.0.x
- name: Run Build and Test using Nuke
run: ./build.ps1 -Target Test -Configuration Release
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4de53c3..f0ed802 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -16,6 +16,6 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 6.0.x
+ dotnet-version: 10.0.x
- name: Run Publish using Nuke
run: ./build.ps1 -Target Publish -Configuration Release --nuget_api_key ${{ secrets.NUGET_API_KEY }}
diff --git a/README.md b/README.md
index d30c813..449c011 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[](https://github.com/OptiSchmopti/CsvProc9000/network/members)
[](https://github.com/OptiSchmopti/CsvProc9000/watchers)
-🛠️ .NET: Easy (to use) Parser for your .NET Solution (.sln) Files. This project targets `netstandard2.0` so it can basically be used anywhere you want. I've not yet run any performance tests.
+🛠️ .NET: Easy (to use) Parser for your .NET Solution (s, .slnx) Files. This project targets `netstandard2.0` so it can basically be used anywhere you want. I've not yet run any performance tests.
## 💻 Usage
@@ -18,7 +18,7 @@
```cs
var parser = new SolutionParser();
-var parsedSolution = parser.Parse("path/to/your/solution.sln");
+var parsedSolution = parser.Parse("path/to/your/solution.sln"); // or ".slnx"
```
diff --git a/build/Build.cs b/build/Build.cs
index 25a3a38..b241557 100644
--- a/build/Build.cs
+++ b/build/Build.cs
@@ -1,16 +1,15 @@
+using System.IO;
using System.Linq;
using Nuke.Common;
using Nuke.Common.CI;
-using Nuke.Common.Execution;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.GitVersion;
using Nuke.Common.Utilities.Collections;
-using static Nuke.Common.IO.FileSystemTasks;
+using Serilog;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
-[CheckBuildProjectConfigurations]
[ShutdownDotNetAfterServerBuild]
public class Build : NukeBuild
{
@@ -31,8 +30,8 @@ public class Build : NukeBuild
.Before(Restore)
.Executes(() =>
{
- SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(DeleteDirectory);
- BuildDirectory.GlobDirectories("**/.output").ForEach(DeleteDirectory);
+ SourceDirectory.GlobDirectories("**/bin", "**/obj").ForEach(dir => Directory.Delete(dir, true));
+ BuildDirectory.GlobDirectories("**/.output").ForEach(dir => Directory.Delete(dir, true));
});
Target Restore => _ => _
@@ -48,8 +47,10 @@ public class Build : NukeBuild
.Executes(() =>
{
if (GitVersion == null)
- Logger.Warn(
+ {
+ Log.Warning(
"GitVersion appears to be null. Have a look at it! Versions are defaulting to 0.1.0 for now...");
+ }
DotNetBuild(s => s
.SetProjectFile(Solution)
@@ -83,7 +84,7 @@ public class Build : NukeBuild
foreach (var packProject in packProjects)
{
- using var block = Logger.Block($"Packing {packProject.Name}");
+ Log.Information("Packing {ProjectName}...", packProject.Name);
DotNetPack(s => s
.SetProject(packProject.Path)
.SetVersion(GitVersion?.NuGetVersionV2 ?? "0.1.0")
@@ -107,7 +108,7 @@ public class Build : NukeBuild
foreach (var package in packages)
{
- Logger.Info($"Publishing {package}");
+ Log.Information("Publishing {PackageName}...", package);
DotNetNuGetPush(s => s
.SetApiKey(NuGetApiKey)
.SetSymbolApiKey(NuGetApiKey)
diff --git a/build/SlnParser.Build.csproj b/build/SlnParser.Build.csproj
index bd66f25..a1e9e6d 100644
--- a/build/SlnParser.Build.csproj
+++ b/build/SlnParser.Build.csproj
@@ -2,7 +2,7 @@
Exe
- net6.0
+ net10.0
CS0649;CS0169
..
@@ -11,7 +11,7 @@
-
+
diff --git a/src/SlnParser.Tests/IntegrationTests.cs b/src/SlnParser.Tests/IntegrationTests.cs
index 08e761f..ea0c7df 100644
--- a/src/SlnParser.Tests/IntegrationTests.cs
+++ b/src/SlnParser.Tests/IntegrationTests.cs
@@ -1,448 +1,744 @@
-using FluentAssertions;
+using AwesomeAssertions;
using SlnParser.Contracts;
using System.ComponentModel;
using System.IO;
using System.Linq;
using Xunit;
-namespace SlnParser.Tests
+namespace SlnParser.Tests;
+
+public class IntegrationTests
{
- public class IntegrationTests
+ [Fact]
+ [Category("ParseSolution:Empty")]
+ public void Parse_WithEmptySolutionFile_IsParsedCorrectly()
+ {
+ var solutionFile = LoadSolution("Empty");
+
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .FileFormatVersion
+ .Should()
+ .Be(string.Empty);
+
+ var visualStudioVersion = solution.VisualStudioVersion;
+
+ visualStudioVersion
+ .MinimumVersion
+ .Should()
+ .Be(string.Empty);
+
+ visualStudioVersion
+ .Version
+ .Should()
+ .Be(string.Empty);
+
+ solution
+ .Guid
+ .Should()
+ .Be(null);
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(0);
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(0);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(0);
+ }
+
+ [Fact]
+ [Category("ParseSolution:SlnParser")]
+ public void Should_Be_Able_To_Parse_SlnParser_Solution_Correctly()
{
- [Fact]
- public void Parse_WithEmptySolutionFile_IsParsedCorrectly()
- {
- var solutionFile = LoadSolution("Empty");
-
- var sut = new SolutionParser();
-
- var solution = sut.Parse(solutionFile);
-
- solution
- .FileFormatVersion
- .Should()
- .Be(string.Empty);
-
- var visualStudioVersion = solution.VisualStudioVersion;
-
- visualStudioVersion
- .MinimumVersion
- .Should()
- .Be(string.Empty);
-
- visualStudioVersion
- .Version
- .Should()
- .Be(string.Empty);
-
- solution
- .Guid
- .Should()
- .Be(null);
-
- solution
- .ConfigurationPlatforms
- .Should()
- .HaveCount(0);
-
- solution
- .AllProjects
- .Should()
- .HaveCount(0);
-
- solution
- .Projects
- .Should()
- .HaveCount(0);
- }
-
- [Fact]
- [Category("ParseSolution:SlnParser")]
- public void Should_Be_Able_To_Parse_SlnParser_Solution_Correctly()
- {
- var solutionFile = LoadSolution("SlnParser");
- var sut = new SolutionParser();
-
- var solution = sut.Parse(solutionFile);
-
- solution
- .Name
- .Should()
- .Be("SlnParser");
- solution
- .File
- .FullName
- .Should()
- .Contain(@"Solutions\SlnParser.sln");
-
- solution
- .FileFormatVersion
- .Should()
- .Be("12.00");
-
- solution
- .VisualStudioVersion
- .Version
- .Should()
- .Be("17.0.31410.414");
-
- solution
- .VisualStudioVersion
- .MinimumVersion
- .Should()
- .Be("10.0.40219.1");
-
- // -- Solution Configuration Platforms
-
- solution
- .ConfigurationPlatforms
- .Should()
- .HaveCount(6);
-
- solution
- .ConfigurationPlatforms
- .ElementAt(0)
- .Name
- .Should()
- .Be("Debug|Any CPU");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(0)
- .Configuration
- .Should()
- .Be("Debug");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(0)
- .Platform
- .Should()
- .Be("Any CPU");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(1)
- .Name
- .Should()
- .Be("Debug|x64");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(1)
- .Configuration
- .Should()
- .Be("Debug");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(1)
- .Platform
- .Should()
- .Be("x64");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(2)
- .Name
- .Should()
- .Be("Debug|x86");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(2)
- .Configuration
- .Should()
- .Be("Debug");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(2)
- .Platform
- .Should()
- .Be("x86");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(3)
- .Name
- .Should()
- .Be("Release|Any CPU");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(3)
- .Configuration
- .Should()
- .Be("Release");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(3)
- .Platform
- .Should()
- .Be("Any CPU");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(4)
- .Name
- .Should()
- .Be("Release|x64");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(4)
- .Configuration
- .Should()
- .Be("Release");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(4)
- .Platform
- .Should()
- .Be("x64");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(5)
- .Name
- .Should()
- .Be("Release|x86");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(5)
- .Configuration
- .Should()
- .Be("Release");
-
- solution
- .ConfigurationPlatforms
- .ElementAt(5)
- .Platform
- .Should()
- .Be("x86");
-
- // -- Projects
- solution
- .AllProjects
- .Should()
- .HaveCount(3);
-
- // 1. Project - ClassLib
- solution
- .AllProjects
- .ElementAt(0)
- .Should()
- .BeOfType();
- solution
- .AllProjects
- .ElementAt(0)
- .Name
- .Should()
- .Be("SlnParser");
- solution
- .AllProjects
- .ElementAt(0)
- .As()
- .File
- .FullName
- .Should()
- .Contain(@"SlnParser\SlnParser.csproj");
- solution
- .AllProjects
- .ElementAt(0)
- .Type
- .Should()
- .Be(ProjectType.CSharp);
-
- solution
- .AllProjects
- .ElementAt(0)
- .As()
- .ConfigurationPlatforms
- .Should()
- .Contain(config => config.Name.Equals("Debug|Any CPU.ActiveCfg"));
-
- // 2. Project - Solution Folder
- solution
- .AllProjects
- .ElementAt(1)
- .Should()
- .BeOfType();
- solution
- .AllProjects
- .ElementAt(1)
- .Name
- .Should()
- .Be("Solution Items");
- solution
- .AllProjects
- .ElementAt(1)
- .As()
- .Projects
- .Should()
- .BeEmpty();
- solution
- .AllProjects
- .ElementAt(1)
- .Type
- .Should()
- .Be(ProjectType.SolutionFolder);
-
- // 3. Project - Test Project
- solution
- .AllProjects
- .ElementAt(2)
- .Should()
- .BeOfType();
- solution
- .AllProjects
- .ElementAt(2)
- .Name
- .Should()
- .Be("SlnParser.Tests");
- solution
- .AllProjects
- .ElementAt(2)
- .As()
- .File
- .FullName
- .Should()
- .Contain(@"SlnParser.Tests\SlnParser.Tests.csproj");
- solution
- .AllProjects
- .ElementAt(2)
- .Type
- .Should()
- .Be(ProjectType.CSharp);
-
- solution
- .AllProjects
- .ElementAt(2)
- .As()
- .ConfigurationPlatforms
- .Should()
- .Contain(config => config.Name.Equals("Debug|x86.Build.0"));
- }
-
- [Fact]
- [Category("ParseSolution:TestSln")]
- public void Should_Be_Able_To_Parse_TestSln_Solution_Correctly()
- {
- var solutionFile = LoadSolution("TestSln");
- var sut = new SolutionParser();
-
- var solution = sut.Parse(solutionFile);
-
- solution
- .AllProjects
- .Should()
- .HaveCount(8);
-
- solution
- .Projects
- .Should()
- .HaveCount(4);
-
- var firstSolutionFolder = solution
- .AllProjects
- .OfType()
- .FirstOrDefault(folder => folder.Name == "SolutionFolder1");
-
- Assert.NotNull(firstSolutionFolder);
-
- firstSolutionFolder
- .Files
- .Should()
- .Contain(file => file.Name == "something.txt" ||
- file.Name == "test123.txt" ||
- file.Name == "test456.txt");
-
- var nestedSolutionFolder = solution
- .AllProjects
- .OfType()
- .FirstOrDefault(folder => folder.Name == "NestedSolutionFolder");
-
- Assert.NotNull(nestedSolutionFolder);
-
- nestedSolutionFolder
- .Files
- .Should()
- .Contain(file => file.Name == "testNested1.txt");
- }
-
- [Fact]
- public void Parse_WithProjectWithoutPlatform_IsParsedCorrectly()
- {
- var solutionFile = LoadSolution("ProjectWithoutPlatform");
-
- var sut = new SolutionParser();
-
- var solution = sut.Parse(solutionFile);
-
- solution
- .ConfigurationPlatforms
- .Should()
- .HaveCount(1);
-
- var configurationPlatform = solution
- .ConfigurationPlatforms
- .Single();
-
- configurationPlatform
- .Configuration
- .Should()
- .Be("SolutionConfigurationName");
-
- configurationPlatform
- .Platform
- .Should()
- .Be("SolutionPlatformName");
-
- solution
- .AllProjects
- .Should()
- .HaveCount(1);
-
- solution
- .Projects
- .Should()
- .HaveCount(1);
-
- var project = solution.Projects.Single();
- project.Id.Should().Be("D5BDBC46-CEAF-4C92-8335-31450B76914F");
- project.Name.Should().Be("Test");
- project.TypeGuid.Should().Be("D183A3D8-5FD8-494B-B014-37F57B35E655");
- project.Type.Should().Be(ProjectType.Unknown);
- }
+ var solutionFile = LoadSolution("SlnParser");
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .Name
+ .Should()
+ .Be("SlnParser");
+ solution
+ .File
+ .FullName
+ .Should()
+ .Contain(@"Solutions\SlnParser.sln");
+
+ solution
+ .FileFormatVersion
+ .Should()
+ .Be("12.00");
+
+ solution
+ .VisualStudioVersion
+ .Version
+ .Should()
+ .Be("17.0.31410.414");
+
+ solution
+ .VisualStudioVersion
+ .MinimumVersion
+ .Should()
+ .Be("10.0.40219.1");
+
+ // -- Solution Configuration Platforms
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(6);
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(0)
+ .Name
+ .Should()
+ .Be("Debug|Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(0)
+ .Configuration
+ .Should()
+ .Be("Debug");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(0)
+ .Platform
+ .Should()
+ .Be("Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(1)
+ .Name
+ .Should()
+ .Be("Debug|x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(1)
+ .Configuration
+ .Should()
+ .Be("Debug");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(1)
+ .Platform
+ .Should()
+ .Be("x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(2)
+ .Name
+ .Should()
+ .Be("Debug|x86");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(2)
+ .Configuration
+ .Should()
+ .Be("Debug");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(2)
+ .Platform
+ .Should()
+ .Be("x86");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(3)
+ .Name
+ .Should()
+ .Be("Release|Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(3)
+ .Configuration
+ .Should()
+ .Be("Release");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(3)
+ .Platform
+ .Should()
+ .Be("Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(4)
+ .Name
+ .Should()
+ .Be("Release|x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(4)
+ .Configuration
+ .Should()
+ .Be("Release");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(4)
+ .Platform
+ .Should()
+ .Be("x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(5)
+ .Name
+ .Should()
+ .Be("Release|x86");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(5)
+ .Configuration
+ .Should()
+ .Be("Release");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(5)
+ .Platform
+ .Should()
+ .Be("x86");
+
+ // -- Projects
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(3);
+
+ // 1. Project - ClassLib
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Name
+ .Should()
+ .Be("SlnParser");
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .As()
+ .File
+ .FullName
+ .Should()
+ .Contain(@"SlnParser\SlnParser.csproj");
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Type
+ .Should()
+ .Be(ProjectType.CSharp);
+
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .As()
+ .ConfigurationPlatforms
+ .Should()
+ .Contain(config => config.Name.Equals("Debug|Any CPU.ActiveCfg"));
+
+ // 2. Project - Solution Folder
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Name
+ .Should()
+ .Be("Solution Items");
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .As()
+ .Projects
+ .Should()
+ .BeEmpty();
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Type
+ .Should()
+ .Be(ProjectType.SolutionFolder);
+
+ // 3. Project - Test Project
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Name
+ .Should()
+ .Be("SlnParser.Tests");
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .As()
+ .File
+ .FullName
+ .Should()
+ .Contain(@"SlnParser.Tests\SlnParser.Tests.csproj");
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Type
+ .Should()
+ .Be(ProjectType.CSharp);
+
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .As()
+ .ConfigurationPlatforms
+ .Should()
+ .Contain(config => config.Name.Equals("Debug|x86.Build.0"));
+ }
+
+ [Fact]
+ [Category("ParseSolution:TestSln")]
+ public void Should_Be_Able_To_Parse_TestSln_Solution_Correctly()
+ {
+ var solutionFile = LoadSolution("TestSln");
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(8);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(4);
+
+ var firstSolutionFolder = solution
+ .AllProjects
+ .OfType()
+ .FirstOrDefault(folder => folder.Name == "SolutionFolder1");
+
+ Assert.NotNull(firstSolutionFolder);
+
+ firstSolutionFolder
+ .Files
+ .Should()
+ .Contain(file => file.Name == "something.txt" ||
+ file.Name == "test123.txt" ||
+ file.Name == "test456.txt");
+
+ var nestedSolutionFolder = solution
+ .AllProjects
+ .OfType()
+ .FirstOrDefault(folder => folder.Name == "NestedSolutionFolder");
+
+ Assert.NotNull(nestedSolutionFolder);
+
+ nestedSolutionFolder
+ .Files
+ .Should()
+ .Contain(file => file.Name == "testNested1.txt");
+ }
+
+ [Fact]
+ [Category("ParseSolution:ProjectWithoutPlatform")]
+ public void Parse_WithProjectWithoutPlatform_IsParsedCorrectly()
+ {
+ var solutionFile = LoadSolution("ProjectWithoutPlatform");
+
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(1);
+
+ var configurationPlatform = solution
+ .ConfigurationPlatforms
+ .Single();
+
+ configurationPlatform
+ .Configuration
+ .Should()
+ .Be("SolutionConfigurationName");
+
+ configurationPlatform
+ .Platform
+ .Should()
+ .Be("SolutionPlatformName");
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(1);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(1);
+
+ var project = solution.Projects.Single();
+ project.Id.Should().Be("D5BDBC46-CEAF-4C92-8335-31450B76914F");
+ project.Name.Should().Be("Test");
+ project.TypeGuid.Should().Be("D183A3D8-5FD8-494B-B014-37F57B35E655");
+ project.Type.Should().Be(ProjectType.Unknown);
+ }
- [Fact]
- public void Parse_WithSolutionGuid_IsParsedCorrectly()
- {
- var solutionFile = LoadSolution("SolutionGuid");
+ [Fact]
+ [Category("ParseSolution:SolutionGuid")]
+ public void Parse_WithSolutionGuid_IsParsedCorrectly()
+ {
+ var solutionFile = LoadSolution("SolutionGuid");
- var sut = new SolutionParser();
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .Guid
+ .Should()
+ .Be("7F92F20E-4C3D-4316-BF60-105559EFEAFF");
+ }
+
+ [Fact]
+ [Category("ParseSlnxSolution:Empty")]
+ public void ParseSlnx_WithEmptySolutionFile_IsParsedCorrectly()
+ {
+ var solutionFile = LoadXmlSolution("Empty");
+
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
- var solution = sut.Parse(solutionFile);
+ solution
+ .FileFormatVersion
+ .Should()
+ .Be(string.Empty);
- solution
- .Guid
- .Should()
- .Be("7F92F20E-4C3D-4316-BF60-105559EFEAFF");
- }
+ var visualStudioVersion = solution.VisualStudioVersion;
+
+ visualStudioVersion
+ .MinimumVersion
+ .Should()
+ .Be(string.Empty);
+
+ visualStudioVersion
+ .Version
+ .Should()
+ .Be(string.Empty);
+
+ solution
+ .Guid
+ .Should()
+ .Be(null);
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(0);
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(0);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(0);
+ }
+
+ [Fact]
+ [Category("ParseSlnxSolution:SlnParser")]
+ public void Should_Be_Able_To_Parse_SlnParser_SlnxSolution_Correctly()
+ {
+ var solutionFile = LoadXmlSolution("SlnParser");
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .Name
+ .Should()
+ .Be("SlnParser");
+ solution
+ .File
+ .FullName
+ .Should()
+ .Contain(@"Solutions\SlnParser.sln");
+
+ // -- Solution Configuration Platforms
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(3);
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(0)
+ .Name
+ .Should()
+ .Be("Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(0)
+ .Platform
+ .Should()
+ .Be("Any CPU");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(1)
+ .Name
+ .Should()
+ .Be("x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(1)
+ .Platform
+ .Should()
+ .Be("x64");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(2)
+ .Name
+ .Should()
+ .Be("x86");
+
+ solution
+ .ConfigurationPlatforms
+ .ElementAt(2)
+ .Platform
+ .Should()
+ .Be("x86");
+
+ // -- Projects
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(3);
+
+ // 1. Project - Solution Folder
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Name
+ .Should()
+ .Be("Solution Items");
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .As()
+ .Projects
+ .Should()
+ .BeEmpty();
+ solution
+ .AllProjects
+ .ElementAt(0)
+ .Type
+ .Should()
+ .Be(ProjectType.SolutionFolder);
+
+ // 2. Project - Test Project
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Name
+ .Should()
+ .Be("SlnParser.Tests");
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .As()
+ .File
+ .FullName
+ .Should()
+ .Contain(@"SlnParser.Tests\SlnParser.Tests.csproj");
+ solution
+ .AllProjects
+ .ElementAt(1)
+ .Type
+ .Should()
+ .Be(ProjectType.CSharp);
+
+ // 3. Project - ClassLib
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Should()
+ .BeOfType();
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Name
+ .Should()
+ .Be("SlnParser");
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .As()
+ .File
+ .FullName
+ .Should()
+ .Contain(@"SlnParser\SlnParser.csproj");
+ solution
+ .AllProjects
+ .ElementAt(2)
+ .Type
+ .Should()
+ .Be(ProjectType.CSharp);
+ }
+
+ [Fact]
+ [Category("ParseSlnxSolution:TestSln")]
+ public void Should_Be_Able_To_Parse_TestSln_SlnxSolution_Correctly()
+ {
+ var solutionFile = LoadXmlSolution("TestSln");
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(8);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(8);
+
+ var firstSolutionFolder = solution
+ .AllProjects
+ .OfType()
+ .FirstOrDefault(folder => folder.Name == "SolutionFolder1");
+
+ Assert.NotNull(firstSolutionFolder);
+
+ firstSolutionFolder
+ .Files
+ .Should()
+ .Contain(file => file.Name == "something.txt" ||
+ file.Name == "test123.txt" ||
+ file.Name == "test456.txt");
+
+ var nestedSolutionFolder = solution
+ .AllProjects
+ .OfType()
+ .FirstOrDefault(folder => folder.Name == "NestedSolutionFolder");
+
+ Assert.NotNull(nestedSolutionFolder);
+
+ nestedSolutionFolder
+ .Files
+ .Should()
+ .Contain(file => file.Name == "testNested1.txt");
+ }
+
+ [Fact]
+ [Category("ParseSlnxSolution:ProjectWithoutPlatform")]
+ public void ParseSlnx_WithProjectWithoutPlatform_IsParsedCorrectly()
+ {
+ var solutionFile = LoadXmlSolution("ProjectWithoutPlatform");
+
+ var sut = new SolutionParser();
+
+ var solution = sut.Parse(solutionFile);
+
+ solution
+ .ConfigurationPlatforms
+ .Should()
+ .HaveCount(1);
+
+ var configurationPlatform = solution
+ .ConfigurationPlatforms
+ .Single();
+
+ configurationPlatform
+ .Platform
+ .Should()
+ .Be("SolutionPlatformName");
+
+ solution
+ .AllProjects
+ .Should()
+ .HaveCount(1);
+
+ solution
+ .Projects
+ .Should()
+ .HaveCount(1);
+
+ var project = solution.Projects.Single();
+ project.Name.Should().Be("Test");
+ project.TypeGuid.Should().Be("D183A3D8-5FD8-494B-B014-37F57B35E655");
+ project.Type.Should().Be(ProjectType.Unknown);
+ }
- private static FileInfo LoadSolution(string solutionName)
- {
- var solutionFileName = $"./Solutions/{solutionName}.sln";
- var solutionFile = new FileInfo(solutionFileName);
+ private static FileInfo LoadSolution(string solutionName)
+ {
+ var solutionFileName = $"./Solutions/{solutionName}.sln";
+ var solutionFile = new FileInfo(solutionFileName);
- if (!solutionFile.Exists)
- throw new FileNotFoundException();
+ return !solutionFile.Exists ? throw new FileNotFoundException() : solutionFile;
+ }
+
+ private static FileInfo LoadXmlSolution(string solutionName)
+ {
+ var solutionFileName = $"./Solutions/{solutionName}.slnx";
+ var solutionFile = new FileInfo(solutionFileName);
- return solutionFile;
- }
+ return !solutionFile.Exists ? throw new FileNotFoundException() : solutionFile;
}
}
diff --git a/src/SlnParser.Tests/SlnParser.Tests.csproj b/src/SlnParser.Tests/SlnParser.Tests.csproj
index 3e51af1..c8d8bf3 100644
--- a/src/SlnParser.Tests/SlnParser.Tests.csproj
+++ b/src/SlnParser.Tests/SlnParser.Tests.csproj
@@ -1,16 +1,19 @@
- net6.0
+ net10.0
-
-
-
-
-
-
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -21,7 +24,7 @@
-
+
PreserveNewest
diff --git a/src/SlnParser.Tests/Solutions/Empty.slnx b/src/SlnParser.Tests/Solutions/Empty.slnx
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/src/SlnParser.Tests/Solutions/Empty.slnx
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/SlnParser.Tests/Solutions/ProjectWithoutPlatform.slnx b/src/SlnParser.Tests/Solutions/ProjectWithoutPlatform.slnx
new file mode 100644
index 0000000..e827af4
--- /dev/null
+++ b/src/SlnParser.Tests/Solutions/ProjectWithoutPlatform.slnx
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SlnParser.Tests/Solutions/SlnParser.slnx b/src/SlnParser.Tests/Solutions/SlnParser.slnx
new file mode 100644
index 0000000..8b69ed7
--- /dev/null
+++ b/src/SlnParser.Tests/Solutions/SlnParser.slnx
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SlnParser.Tests/Solutions/TestSln.sln b/src/SlnParser.Tests/Solutions/TestSln.sln
index fa98cf1..6e77f0d 100644
--- a/src/SlnParser.Tests/Solutions/TestSln.sln
+++ b/src/SlnParser.Tests/Solutions/TestSln.sln
@@ -25,7 +25,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfAppNotInASolutionFolder"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsApp1", "WinFormsApp1\WinFormsApp1.csproj", "{D4E03E9B-EE01-462A-B2F3-45AC775ADC7E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplication", "WebApplication\WebApplication.csproj", "{20AD21B6-0ABB-4DB5-8BA0-D9896E58E3E4}"
+Project("{E6FDF86B-F3D1-11D4-8576-0002A516ECE8}") = "WebApplication", "WebApplication\WebApplication.csproj", "{20AD21B6-0ABB-4DB5-8BA0-D9896E58E3E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/SlnParser.Tests/Solutions/TestSln.slnx b/src/SlnParser.Tests/Solutions/TestSln.slnx
new file mode 100644
index 0000000..8e7c916
--- /dev/null
+++ b/src/SlnParser.Tests/Solutions/TestSln.slnx
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SlnParser.sln b/src/SlnParser.sln
index ced71fb..bb2237b 100644
--- a/src/SlnParser.sln
+++ b/src/SlnParser.sln
@@ -8,6 +8,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6D0A7ECB-8812-42C3-8CB4-3DD2C8296591}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ ..\.github\workflows\build.yml = ..\.github\workflows\build.yml
+ ..\.github\workflows\release.yml = ..\.github\workflows\release.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SlnParser.Tests", "SlnParser.Tests\SlnParser.Tests.csproj", "{BB52A27D-766E-4ECD-B888-BD86405134C1}"
diff --git a/src/SlnParser/Contracts/Exceptions/ParseSolutionFailedException.cs b/src/SlnParser/Contracts/Exceptions/ParseSolutionFailedException.cs
index e0b38ee..6578b5c 100644
--- a/src/SlnParser/Contracts/Exceptions/ParseSolutionFailedException.cs
+++ b/src/SlnParser/Contracts/Exceptions/ParseSolutionFailedException.cs
@@ -1,13 +1,11 @@
using System;
using System.IO;
-using System.Runtime.Serialization;
namespace SlnParser.Contracts.Exceptions
{
///
/// Exception that is thrown when a solution could not be parsed
///
- [Serializable]
public class ParseSolutionFailedException : Exception
{
///
@@ -21,12 +19,5 @@ public ParseSolutionFailedException(FileInfo solutionFile, Exception inner)
inner)
{
}
-
- ///
- protected ParseSolutionFailedException(
- SerializationInfo info,
- StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/src/SlnParser/Contracts/Exceptions/UnexpectedSolutionStructureException.cs b/src/SlnParser/Contracts/Exceptions/UnexpectedSolutionStructureException.cs
index d330df0..7e7972d 100644
--- a/src/SlnParser/Contracts/Exceptions/UnexpectedSolutionStructureException.cs
+++ b/src/SlnParser/Contracts/Exceptions/UnexpectedSolutionStructureException.cs
@@ -1,12 +1,10 @@
using System;
-using System.Runtime.Serialization;
namespace SlnParser.Contracts.Exceptions
{
///
/// An that describes an unexpected structure of a Solution
///
- [Serializable]
public class UnexpectedSolutionStructureException : Exception
{
///
@@ -25,12 +23,5 @@ public UnexpectedSolutionStructureException(string message) : base(message)
public UnexpectedSolutionStructureException(string message, Exception inner) : base(message, inner)
{
}
-
- ///
- protected UnexpectedSolutionStructureException(
- SerializationInfo info,
- StreamingContext context) : base(info, context)
- {
- }
}
}
diff --git a/src/SlnParser/Contracts/ISolutionParser.cs b/src/SlnParser/Contracts/ISolutionParser.cs
index 020d456..631fa91 100644
--- a/src/SlnParser/Contracts/ISolutionParser.cs
+++ b/src/SlnParser/Contracts/ISolutionParser.cs
@@ -8,21 +8,21 @@ namespace SlnParser.Contracts
public interface ISolutionParser
{
///
- /// Parses the provided solution file (sln)
+ /// Parses the provided solution file (sln or slnx)
///
/// The path to the solution file that you want to parse
/// The parsed
ISolution Parse(string solutionFileName);
///
- /// Parses the provided solution file (sln)
+ /// Parses the provided solution file (sln or slnx)
///
/// The path to the solution file that you want to parse
/// The parsed
ISolution Parse(FileInfo solutionFile);
///
- /// Safely Parses the provided solution file (sln)
+ /// Safely Parses the provided solution file (sln or slnx)
///
/// The path to the solution file that you want to parse
/// The parsed
@@ -30,7 +30,7 @@ public interface ISolutionParser
bool TryParse(string solutionFileName, out ISolution? solution);
///
- /// Safely Parses the provided solution file (sln)
+ /// Safely Parses the provided solution file (sln or slnx)
///
/// The path to the solution file that you want to parse
/// The parsed
diff --git a/src/SlnParser/Helper/SlnxParser.cs b/src/SlnParser/Helper/SlnxParser.cs
new file mode 100644
index 0000000..39ad7ba
--- /dev/null
+++ b/src/SlnParser/Helper/SlnxParser.cs
@@ -0,0 +1,207 @@
+using SlnParser.Contracts;
+using SlnParser.Contracts.Exceptions;
+using SlnParser.Contracts.Helper;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+
+namespace SlnParser.Helper
+{
+ internal sealed class SlnxParser
+ {
+ private readonly IProjectTypeMapper _projectTypeMapper = new ProjectTypeMapper();
+
+ public ISolution Parse(FileInfo solutionFile)
+ {
+ // the new SLNX has no information about the file format version, VS version and minimal VS version, so it's omitted.
+ var solution = new Solution
+ {
+ Name = Path.GetFileNameWithoutExtension(solutionFile.FullName),
+ File = solutionFile,
+ };
+
+ var fileContent = File.ReadAllText(solutionFile.FullName);
+ if (string.IsNullOrEmpty(fileContent.Trim()))
+ {
+ return solution;
+ }
+
+ var xmlReaderSettings = new XmlReaderSettings
+ {
+ DtdProcessing = DtdProcessing.Prohibit, // Prevent XXE
+ XmlResolver = null, // Disable external entity resolution
+ };
+ using var xmlContentStream = solutionFile.OpenRead();
+ var xmlDocument = new XmlDocument();
+
+ using var xmlReader = XmlReader.Create(xmlContentStream, xmlReaderSettings);
+ xmlDocument.Load(xmlReader);
+
+ var root = xmlDocument.DocumentElement;
+ if (root == null) throw new UnexpectedSolutionStructureException($"Solution file '{solutionFile.FullName}' does not contain a root element");
+
+ var structuredProjects = new List();
+
+ foreach (var xmlElement in root.ChildNodes.OfType())
+ {
+ var projectsFromElement = ParseSlnxElement(xmlElement, solutionFile);
+ structuredProjects.AddRange(projectsFromElement);
+ }
+
+ solution.AllProjects = structuredProjects.AsReadOnly();
+ solution.Projects = structuredProjects.AsReadOnly();
+ solution.ConfigurationPlatforms = ParseSolutionConfigurations(root).AsReadOnly();
+
+ return solution;
+ }
+
+ private List ParseSlnxElement(XmlElement xmlElement, FileInfo solutionFile)
+ {
+ return xmlElement.Name switch
+ {
+ "Folder" => ParseSlnxFolder(xmlElement, solutionFile),
+ "Project" => ParseSlnxProject(xmlElement, solutionFile),
+ _ => new List(),
+ };
+ }
+
+ private List ParseSlnxFolder(XmlElement xmlElement, FileInfo solutionFile)
+ {
+ var folderName = xmlElement.GetAttribute("Name");
+ if (string.IsNullOrWhiteSpace(folderName))
+ {
+ throw new UnexpectedSolutionStructureException($"Could not find solution folder name attribute in solution '{solutionFile.FullName}'");
+ }
+
+ var actualFolderName = folderName.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Last();
+
+ var solutionFolderTypeId = new Guid("2150E333-8FDC-42A3-9474-1A3956D46DE8");
+ var solutionFolder = new SolutionFolder(Guid.Empty, actualFolderName, solutionFolderTypeId, ProjectType.SolutionFolder);
+ var projects = new List
+ {
+ solutionFolder,
+ };
+
+ foreach (var childElement in xmlElement.ChildNodes.OfType())
+ {
+ if (childElement.Name == "File")
+ {
+ var solutionFolderFile = ParseSolutionFolderFile(childElement, solutionFile);
+ if (solutionFolderFile == null)
+ {
+ throw new UnexpectedSolutionStructureException($"Could not parse file of solution folder '{actualFolderName}' in solution file '{solutionFile.FullName}'");
+ }
+
+ solutionFolder.AddFile(solutionFolderFile);
+ }
+
+ var childProjects = ParseSlnxElement(childElement, solutionFile);
+ foreach (var childProject in childProjects)
+ {
+ solutionFolder.AddProject(childProject);
+ projects.Add(childProject);
+ }
+ }
+
+ return projects;
+ }
+
+ private List ParseSlnxProject(XmlElement xmlElement, FileInfo solutionFile)
+ {
+ const string defaultProjectTypeId = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}";
+
+ var projectPath = xmlElement.GetAttribute("Path");
+ if (string.IsNullOrWhiteSpace(projectPath))
+ {
+ throw new UnexpectedSolutionStructureException($"Could not find solution project path attribute in solution file '{solutionFile.FullName}'.");
+ }
+
+ var projectTypeIdText = xmlElement.GetAttribute("Type");
+ projectTypeIdText = string.IsNullOrWhiteSpace(projectTypeIdText)
+ ? defaultProjectTypeId
+ // the new project type id notation does not quite fit the known format, so it is adjusted.
+ : $"{{{projectTypeIdText.ToUpper()}}}";
+ var projectTypeId = Guid.Parse(projectTypeIdText);
+ var projectType = _projectTypeMapper.Map(projectTypeId);
+
+ var projectFullPath = EnsureAbsolute(projectPath, solutionFile);
+
+ // the project name is part of its path.
+ var actualProjectName = Path.GetFileNameWithoutExtension(projectFullPath);
+
+ // elements in the SLNX file don't have any IDs anymore, so it's omitted.
+ var solutionProject = new SolutionProject(Guid.Empty, actualProjectName, projectTypeId, projectType, new FileInfo(projectFullPath));
+
+ var projectConfigurations = ParseProjectConfigurations(xmlElement);
+ foreach (var configuration in projectConfigurations) solutionProject.AddConfigurationPlatform(configuration);
+
+ return new List { solutionProject };
+ }
+
+ private static List ParseSolutionConfigurations(XmlElement rootElement)
+ {
+ var configurations = new List();
+ var configurationPlatforms = rootElement.SelectNodes("Configurations/Platform");
+ if (configurationPlatforms == null)
+ {
+ return configurations;
+ }
+
+ foreach (XmlNode configurationPlatform in configurationPlatforms)
+ {
+ if (configurationPlatform.Attributes == null) continue;
+
+ var name = configurationPlatform.Attributes["Name"].Value;
+ // there is not much info anymore
+ var platform = new ConfigurationPlatform(name, string.Empty, name);
+ configurations.Add(platform);
+ }
+
+ return configurations;
+ }
+
+ private static List ParseProjectConfigurations(XmlElement projectElement)
+ {
+ var configurations = new List();
+ var configurationPlatforms = projectElement.SelectNodes("Platform");
+ if (configurationPlatforms == null)
+ {
+ return configurations;
+ }
+
+ foreach (XmlNode configurationPlatform in configurationPlatforms)
+ {
+ if (configurationPlatform.Attributes == null) continue;
+
+ var projectName = configurationPlatform.Attributes["Project"].Value;
+ // there is not much info anymore
+ var platform = new ConfigurationPlatform(projectName, string.Empty, projectName);
+ configurations.Add(platform);
+ }
+
+ return configurations;
+ }
+
+ private static FileInfo? ParseSolutionFolderFile(XmlElement xmlElement, FileInfo solutionFile)
+ {
+ var path = xmlElement.GetAttribute("Path");
+ if (string.IsNullOrWhiteSpace(path)) return null;
+
+ var fullPath = EnsureAbsolute(path, solutionFile);
+ var fullPathInfo = new FileInfo(fullPath);
+ return fullPathInfo;
+ }
+
+ private static string EnsureAbsolute(string path, FileInfo solutionFile)
+ {
+ var filePath = new FileInfo(path);
+ var isRelative = Path.IsPathRooted(filePath.FullName);
+ var fileFullPath = isRelative
+ ? Path.Combine(solutionFile.Directory?.FullName ?? string.Empty, filePath.FullName)
+ : filePath.FullName;
+ return fileFullPath;
+ }
+ }
+}
diff --git a/src/SlnParser/SlnParser.csproj b/src/SlnParser/SlnParser.csproj
index f5ca58e..fb5026e 100644
--- a/src/SlnParser/SlnParser.csproj
+++ b/src/SlnParser/SlnParser.csproj
@@ -34,7 +34,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/SlnParser/SolutionParser.cs b/src/SlnParser/SolutionParser.cs
index 60bc5a1..9e8138a 100644
--- a/src/SlnParser/SolutionParser.cs
+++ b/src/SlnParser/SolutionParser.cs
@@ -13,6 +13,7 @@ namespace SlnParser
public sealed class SolutionParser : ISolutionParser
{
private readonly IEnumerable _solutionEnrichers;
+ private readonly SlnxParser _slnxParser = new SlnxParser();
///
/// Creates a new instance of
@@ -51,12 +52,17 @@ public ISolution Parse(FileInfo solutionFile)
throw new ArgumentNullException(nameof(solutionFile));
if (!solutionFile.Exists)
throw new FileNotFoundException("Provided Solution-File does not exist", solutionFile.FullName);
- if (!solutionFile.Extension.Equals(".sln"))
- throw new InvalidDataException("The provided file is not a solution file!");
+
+ var fileExtension = solutionFile.Extension;
try
{
- var solution = ParseInternal(solutionFile);
+ var solution = fileExtension switch
+ {
+ ".sln" => ParseSlnInternal(solutionFile),
+ ".slnx" => _slnxParser.Parse(solutionFile),
+ _ => throw new InvalidDataException($"The provided file '{solutionFile.FullName}' is not a solution file!"),
+ };
return solution;
}
catch (Exception exception)
@@ -94,11 +100,12 @@ public bool TryParse(FileInfo solutionFile, out ISolution? solution)
}
}
- private ISolution ParseInternal(FileInfo solutionFile)
+ private ISolution ParseSlnInternal(FileInfo solutionFile)
{
var solution = new Solution
{
- Name = Path.GetFileNameWithoutExtension(solutionFile.FullName), File = solutionFile
+ Name = Path.GetFileNameWithoutExtension(solutionFile.FullName),
+ File = solutionFile,
};
var allLines = File.ReadAllLines(solutionFile.FullName);
var allLinesTrimmed = allLines