diff --git a/nuke-common.sln b/nuke-common.sln index 68d05e870..fa1b6ead3 100644 --- a/nuke-common.sln +++ b/nuke-common.sln @@ -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 @@ -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} diff --git a/source/Nuke.SolutionModel.Tests/SolutionModelTest.cs b/source/Nuke.SolutionModel.Tests/SolutionModelTest.cs index ef2bee640..88d377e98 100644 --- a/source/Nuke.SolutionModel.Tests/SolutionModelTest.cs +++ b/source/Nuke.SolutionModel.Tests/SolutionModelTest.cs @@ -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"); diff --git a/source/Nuke.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#StronglyTypedSolutionGenerator.verified.cs b/source/Nuke.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#StronglyTypedSolutionGenerator.verified.cs index a72c5367f..725102df1 100644 --- a/source/Nuke.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#StronglyTypedSolutionGenerator.verified.cs +++ b/source/Nuke.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#StronglyTypedSolutionGenerator.verified.cs @@ -32,6 +32,7 @@ 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 { @@ -39,4 +40,51 @@ internal class _misc 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; + } + } + } } \ No newline at end of file diff --git a/source/Nuke.SourceGenerators/StronglyTypedSolutionGenerator.cs b/source/Nuke.SourceGenerators/StronglyTypedSolutionGenerator.cs index 25a8fba70..f55155854 100644 --- a/source/Nuke.SourceGenerators/StronglyTypedSolutionGenerator.cs +++ b/source/Nuke.SourceGenerators/StronglyTypedSolutionGenerator.cs @@ -73,7 +73,7 @@ private string GenerateSolutionSource(Compilation compilation) var solution = SolutionSerializer.DeserializeFromFile(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())) @@ -92,40 +92,40 @@ private ClassDeclarationSyntax GetSolutionFolderDeclaration( string name, IReadOnlyCollection solutionFolders, IReadOnlyCollection 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()); }