Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support parsing and retrieving SolutionGuid #26

Merged
merged 3 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/SlnParser.Tests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,53 @@ namespace SlnParser.Tests
{
public class IntegrationTests
{
[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()
Expand Down Expand Up @@ -371,7 +418,22 @@ public void Parse_WithProjectWithoutPlatform_IsParsedCorrectly()
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");

var sut = new SolutionParser();

var solution = sut.Parse(solutionFile);

solution
.Guid
.Should()
.Be("7F92F20E-4C3D-4316-BF60-105559EFEAFF");
}

private static FileInfo LoadSolution(string solutionName)
{
var solutionFileName = $"./Solutions/{solutionName}.sln";
Expand Down
1 change: 1 addition & 0 deletions src/SlnParser.Tests/Solutions/Empty.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ο»Ώ
5 changes: 5 additions & 0 deletions src/SlnParser.Tests/Solutions/SolutionGuid.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ο»ΏGlobal
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7F92F20E-4C3D-4316-BF60-105559EFEAFF}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ internal interface IParseSolutionConfigurationPlatform
{
IEnumerable<ProjectConfigurationPlatform> Parse(
IEnumerable<string> fileContents,
string startSection);
string sectionName);
}
}
11 changes: 11 additions & 0 deletions src/SlnParser/Contracts/Helper/ISectionParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ο»Ώusing System.Collections.Generic;

namespace SlnParser.Contracts.Helper
{
internal interface ISectionParser
{
IEnumerable<string> GetFileContentsInGlobalSection(
IEnumerable<string> fileContents,
string sectionName);
}
}
8 changes: 7 additions & 1 deletion src/SlnParser/Contracts/ISolution.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ο»Ώusing System.Collections.Generic;
ο»Ώusing System;
using System.Collections.Generic;
using System.IO;

namespace SlnParser.Contracts
Expand Down Expand Up @@ -42,5 +43,10 @@ public interface ISolution
/// The <see cref="ConfigurationPlatform" />s configured for this solution
/// </summary>
IReadOnlyCollection<ConfigurationPlatform> ConfigurationPlatforms { get; }

/// <summary>
/// The <see cref="Guid"/> of the solution.
/// </summary>
Guid? Guid { get; }
}
}
6 changes: 5 additions & 1 deletion src/SlnParser/Contracts/Solution.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ο»Ώusing System.Collections.Generic;
ο»Ώusing System;
using System.Collections.Generic;
using System.IO;

namespace SlnParser.Contracts
Expand Down Expand Up @@ -36,5 +37,8 @@ public Solution()

/// <inheritdoc />
public IReadOnlyCollection<ConfigurationPlatform> ConfigurationPlatforms { get; internal set; }

/// <inheritdoc/>
public Guid? Guid { get; internal set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void Enrich(Solution solution, IEnumerable<string> fileContents)
{
var projectConfigurations = _parseSolutionConfigurationPlatform.Parse(
fileContents,
"GlobalSection(ProjectConfiguration");
"ProjectConfiguration");
MapConfigurationPlatformsToProjects(solution, projectConfigurations);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void Enrich(Solution solution, IEnumerable<string> fileContents)
{
var projectConfigurations = _parseSolutionConfigurationPlatform.Parse(
fileContents,
"GlobalSection(SolutionConfiguration");
"SolutionConfiguration");
solution.ConfigurationPlatforms = projectConfigurations
.Select(projectConfiguration => projectConfiguration.ConfigurationPlatform)
.ToList()
Expand Down
38 changes: 38 additions & 0 deletions src/SlnParser/Helper/EnrichSolutionWithSolutionGuid.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
ο»Ώusing SlnParser.Contracts;
using SlnParser.Contracts.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace SlnParser.Helper
{
internal sealed class EnrichSolutionWithSolutionGuid : IEnrichSolution
{
private readonly ISectionParser _sectionParser = new SectionParser();

public void Enrich(Solution solution, IEnumerable<string> fileContents)
{
var extensibilityGlobals = _sectionParser.GetFileContentsInGlobalSection(
fileContents,
"ExtensibilityGlobals");

solution.Guid = extensibilityGlobals
.Select(ExtractSolutionGuid)
.FirstOrDefault(x => x.HasValue);
}

private Guid? ExtractSolutionGuid(string line)
{
const string pattern = @"\s*SolutionGuid\s*=\s*{([A-Fa-f0-9\-]+)}";
var match = Regex.Match(line, pattern);
if (!match.Success)
{
return null;
}

var guidString = match.Groups[1].Value;
return new Guid(guidString);
}
}
}
34 changes: 34 additions & 0 deletions src/SlnParser/Helper/SectionParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
ο»Ώusing SlnParser.Contracts.Helper;
using System.Collections.Generic;
using System.Linq;

namespace SlnParser.Helper
{
internal class SectionParser : ISectionParser
{
public IEnumerable<string> GetFileContentsInGlobalSection(
IEnumerable<string> fileContents,
string sectionName)
{
var startSection = $"GlobalSection({sectionName}";
const string endSection = "EndGlobalSection";

return GetFileContentsInSection(fileContents, startSection, endSection);
}

private static IEnumerable<string> GetFileContentsInSection(
IEnumerable<string> fileContents,
string startSection,
string endSection)
{
var section = fileContents
.SkipWhile(line => !line.StartsWith(startSection))
.TakeWhile(line => !line.StartsWith(endSection))
.Where(line => !line.StartsWith(startSection))
.Where(line => !line.StartsWith(endSection))
.Where(line => !string.IsNullOrWhiteSpace(line));

return section.ToList();
}
}
}
26 changes: 6 additions & 20 deletions src/SlnParser/Helper/SolutionConfigurationPlatformParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,21 @@ namespace SlnParser.Helper
{
internal sealed class SolutionConfigurationPlatformParser : IParseSolutionConfigurationPlatform
{
private readonly ISectionParser _sectionParser = new SectionParser();

public IEnumerable<ProjectConfigurationPlatform> Parse(
IEnumerable<string> fileContents,
string startSection)
string sectionName)
{
if (fileContents == null) throw new ArgumentNullException(nameof(fileContents));
if (string.IsNullOrWhiteSpace(startSection))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(startSection));
if (string.IsNullOrWhiteSpace(sectionName))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(sectionName));

var sectionContents = GetFileContentsInSection(fileContents, startSection);
var sectionContents = _sectionParser.GetFileContentsInGlobalSection(fileContents, sectionName);
var projectConfigurationPlatforms = ParseConfigurationPlatforms(sectionContents);
return projectConfigurationPlatforms;
}

private static IEnumerable<string> GetFileContentsInSection(
IEnumerable<string> fileContents,
string startSection)
{
const string endSection = "EndGlobalSection";

var section = fileContents
.SkipWhile(line => !line.StartsWith(startSection))
.TakeWhile(line => !line.StartsWith(endSection))
.Where(line => !line.StartsWith(startSection))
.Where(line => !line.StartsWith(endSection))
.Where(line => !string.IsNullOrWhiteSpace(line));

return section.ToList();
}

private static IEnumerable<ProjectConfigurationPlatform> ParseConfigurationPlatforms(
IEnumerable<string> sectionFileContents)
{
Expand Down
3 changes: 2 additions & 1 deletion src/SlnParser/SolutionParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public SolutionParser()
* because we need the parsed projects before we can map the configurations to them
*/
new EnrichSolutionWithProjectConfigurationPlatforms(),
new EnrichSolutionWithSolutionFolderFiles()
new EnrichSolutionWithSolutionFolderFiles(),
new EnrichSolutionWithSolutionGuid(),
};
}

Expand Down
Loading