Skip to content

Commit

Permalink
fix(source-generators): Added support nested folders in solution gene…
Browse files Browse the repository at this point in the history
…ration
  • Loading branch information
david-driscoll committed Sep 14, 2024
1 parent 558a89c commit 6dab2a5
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 18 deletions.
17 changes: 17 additions & 0 deletions nuke-common.sln
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nuke.Utilities.Text.Yaml",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nuke.Utilities.IO.Compression", "source\Nuke.Utilities.IO.Compression\Nuke.Utilities.IO.Compression.csproj", "{3E330C45-DB19-4EAD-9C5D-B9D24F0254E8}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nested", "nested", "{C7BB2283-613C-4AC1-8CE1-F369EAA96E39}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "folder", "folder", "{79B5D985-8AEB-49E4-A159-6B63A996A8AF}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{4F3551E8-EA01-40BD-900C-279E63019A89}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{15C2101B-5848-4722-B92D-19E5BFE9E630}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "something", "something", "{691EE1CF-B539-4D23-A4C3-26E362C0077B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{83FD462A-E9B3-417E-9F44-4CFB5B6DF858}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -178,6 +190,11 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{79B5D985-8AEB-49E4-A159-6B63A996A8AF} = {C7BB2283-613C-4AC1-8CE1-F369EAA96E39}
{4F3551E8-EA01-40BD-900C-279E63019A89} = {79B5D985-8AEB-49E4-A159-6B63A996A8AF}
{15C2101B-5848-4722-B92D-19E5BFE9E630} = {C7BB2283-613C-4AC1-8CE1-F369EAA96E39}
{691EE1CF-B539-4D23-A4C3-26E362C0077B} = {C7BB2283-613C-4AC1-8CE1-F369EAA96E39}
{83FD462A-E9B3-417E-9F44-4CFB5B6DF858} = {691EE1CF-B539-4D23-A4C3-26E362C0077B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A2C37D4D-74E1-443B-999B-505B8C6694C9}
Expand Down
2 changes: 1 addition & 1 deletion source/Nuke.SolutionModel.Tests/SolutionModelTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void SolutionTest()
{
var solution = SolutionModelTasks.ParseSolution(SolutionFile);

solution.SolutionFolders.Select(x => x.Name).Should().BeEquivalentTo("misc");
solution.SolutionFolders.Select(x => x.Name).Should().BeEquivalentTo("misc", "nested");
solution.AllProjects.Where(x => x.Is(ProjectType.CSharpProject)).Should().HaveCountGreaterOrEqualTo(9);

var buildProject = solution.AllProjects.SingleOrDefault(x => x.Name == "_build");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,59 @@ internal class Solution : Nuke.Common.ProjectModel.Solution
public Project Nuke_Utilities_Text_Yaml => SolutionFolder.GetProject("Nuke.Utilities.Text.Yaml");
public Project Nuke_Utilities_IO_Compression => SolutionFolder.GetProject("Nuke.Utilities.IO.Compression");
public _misc misc => new(SolutionFolder.GetSolutionFolder("misc"));
public _nested nested => new(SolutionFolder.GetSolutionFolder("nested"));

internal class _misc
{
private SolutionFolder SolutionFolder { get; }

public _misc(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
}

internal class _nested
{
private SolutionFolder SolutionFolder { get; }

public _nested(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
public _nestedfolder folder => new(SolutionFolder.GetSolutionFolder("folder"));
public _nestedother other => new(SolutionFolder.GetSolutionFolder("other"));
public _nestedsomething something => new(SolutionFolder.GetSolutionFolder("something"));

internal class _nestedfolder
{
private SolutionFolder SolutionFolder { get; }

public _nestedfolder(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
public _nested_folderother other => new(SolutionFolder.GetSolutionFolder("other"));

internal class _nested_folderother
{
private SolutionFolder SolutionFolder { get; }

public _nested_folderother(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
}
}

internal class _nestedother
{
private SolutionFolder SolutionFolder { get; }

public _nestedother(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
}

internal class _nestedsomething
{
private SolutionFolder SolutionFolder { get; }

public _nestedsomething(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
public _nested_somethingother other => new(SolutionFolder.GetSolutionFolder("other"));

internal class _nested_somethingother
{
private SolutionFolder SolutionFolder { get; }

public _nested_somethingother(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;
}
}
}
}
34 changes: 17 additions & 17 deletions source/Nuke.SourceGenerators/StronglyTypedSolutionGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ private string GenerateSolutionSource(Compilation compilation)

var solution = SolutionSerializer.DeserializeFromFile<Solution>(solutionFile);

var classDeclaration = GetSolutionFolderDeclaration(member.Name, solution.SolutionFolders, solution.Projects, isSolution: true);
var classDeclaration = GetSolutionFolderDeclaration(member.Name, solution.SolutionFolders, solution.Projects, parent: "_", isSolution: true);
compilationUnit = compilationUnit
.AddMembers(member.ContainingType.ContainingNamespace.Equals(compilation.GlobalNamespace, SymbolEqualityComparer.Default)
? NamespaceDeclaration(IdentifierName(member.ContainingType.ContainingNamespace.GetFullName()))
Expand All @@ -92,40 +92,40 @@ private ClassDeclarationSyntax GetSolutionFolderDeclaration(
string name,
IReadOnlyCollection<SolutionFolder> solutionFolders,
IReadOnlyCollection<Project> projects,
string parent,
bool isSolution = false)
{
string GetMemberName(string name) => name
static string GetMemberName([CanBeNull] string name) => name?
.ReplaceRegex(@"(^[\W^\d]|[\W])", _ => "_")
.TrimToOne("_");

string GetSolutionFolderTypeName(string name)
=> $"_{GetMemberName(name)}";
static string GetSolutionFolderTypeName(string name, string parent)
=> $"{parent}{GetMemberName(name)}";

MemberDeclarationSyntax GetSolutionFolderPropertyDeclaration()
=> isSolution
? ParseMemberDeclaration($"private {typeof(Solution).FullName} SolutionFolder => this;")
: ParseMemberDeclaration("private SolutionFolder SolutionFolder { get; }");

MemberDeclarationSyntax GetSolutionFolderConstructorDeclaration()
=> ParseMemberDeclaration($"public {GetSolutionFolderTypeName(name)}(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;");
MemberDeclarationSyntax GetSolutionFolderConstructorDeclaration(string parent)
=> ParseMemberDeclaration($"public {GetSolutionFolderTypeName(name, parent)}(SolutionFolder solutionFolder) => SolutionFolder = solutionFolder;");

MemberDeclarationSyntax GetProjectPropertyDeclaration(string name)
static MemberDeclarationSyntax GetProjectPropertyDeclaration(string name)
=> ParseMemberDeclaration($@"public Project {GetMemberName(name)} => SolutionFolder.GetProject(""{name}"");");

MemberDeclarationSyntax GetSolutionFolderProperty(string name)
=> ParseMemberDeclaration(
$@"public {GetSolutionFolderTypeName(name)} {GetMemberName(name)} => new(SolutionFolder.GetSolutionFolder(""{name}""));");
static MemberDeclarationSyntax GetSolutionFolderProperty(string name, string parent)
=> ParseMemberDeclaration($@"public {GetSolutionFolderTypeName(name, parent)} {GetMemberName(name)} => new(SolutionFolder.GetSolutionFolder(""{name}""));");

return ClassDeclaration(isSolution ? name : GetSolutionFolderTypeName(name)) // TODO: check for multiple solution fields
string GetParentName([CanBeNull] SolutionFolder solutionFolder) => $"{parent}_{GetMemberName(solutionFolder?.Name)}".TrimToOne("_");

return ClassDeclaration(isSolution ? name : GetSolutionFolderTypeName(name, parent)) // TODO: check for multiple solution fields
.AddModifiers(Token(SyntaxKind.InternalKeyword))
.When(isSolution, _ => _
.AddBaseListTypes(SimpleBaseType(ParseTypeName(typeof(Solution).FullName.NotNull()))))
.When(isSolution, syntax => syntax.AddBaseListTypes(SimpleBaseType(ParseTypeName(typeof(Solution).FullName.NotNull()))))
.AddMembers(GetSolutionFolderPropertyDeclaration())
.When(!isSolution, _ => _
.AddMembers(GetSolutionFolderConstructorDeclaration()))
.When(!isSolution, syntax => syntax.AddMembers(GetSolutionFolderConstructorDeclaration(parent)))
.AddMembers(projects.Select(project => GetProjectPropertyDeclaration(project.Name)).ToArray())
.AddMembers(solutionFolders.Select(x => GetSolutionFolderProperty(x.Name)).ToArray())
.AddMembers(solutionFolders.Select(x => GetSolutionFolderDeclaration(x.Name, x.SolutionFolders, x.Projects))
.AddMembers(solutionFolders.Select(x => GetSolutionFolderProperty(x.Name, GetParentName(x.SolutionFolder))).ToArray())
.AddMembers(solutionFolders.Select(x => GetSolutionFolderDeclaration(x.Name, x.SolutionFolders, x.Projects, GetParentName(x.SolutionFolder)))
.ToArray<MemberDeclarationSyntax>());
}

Expand Down

0 comments on commit 6dab2a5

Please sign in to comment.