diff --git a/Sources/Directory.Packages.props b/Sources/Directory.Packages.props
index 0814660..20cebdb 100644
--- a/Sources/Directory.Packages.props
+++ b/Sources/Directory.Packages.props
@@ -4,11 +4,12 @@
-
-
+
+
-
-
+
+
+
@@ -28,15 +29,15 @@
-
+
-
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem.Tests/Kysect.DotnetProjectSystem.Tests.csproj b/Sources/Kysect.DotnetProjectSystem.Tests/Kysect.DotnetProjectSystem.Tests.csproj
index f5024e8..8c89745 100644
--- a/Sources/Kysect.DotnetProjectSystem.Tests/Kysect.DotnetProjectSystem.Tests.csproj
+++ b/Sources/Kysect.DotnetProjectSystem.Tests/Kysect.DotnetProjectSystem.Tests.csproj
@@ -15,6 +15,7 @@
+
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Sources/Kysect.DotnetProjectSystem.Tests/Projects/DirectoryBuildTargetFileTests.cs b/Sources/Kysect.DotnetProjectSystem.Tests/Projects/DirectoryBuildTargetFileTests.cs
new file mode 100644
index 0000000..1d50f18
--- /dev/null
+++ b/Sources/Kysect.DotnetProjectSystem.Tests/Projects/DirectoryBuildTargetFileTests.cs
@@ -0,0 +1,27 @@
+using Kysect.DotnetProjectSystem.Projects;
+using Microsoft.Language.Xml;
+
+namespace Kysect.DotnetProjectSystem.Tests.Projects;
+
+public class DirectoryBuildTargetFileTests
+{
+ [Fact]
+ public void Create_FileWithTarget_ReturnFileWithTarget()
+ {
+ var content = """
+
+
+
+ false
+
+
+
+ """;
+
+ var dotnetBuildTargetFile = DirectoryBuildTargetFile.Create(content);
+
+ IReadOnlyCollection targets = dotnetBuildTargetFile.GetTargets();
+
+ targets.Should().HaveCount(1);
+ }
+}
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierFactoryTests.cs b/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierFactoryTests.cs
index 808c6da..75301f8 100644
--- a/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierFactoryTests.cs
+++ b/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierFactoryTests.cs
@@ -109,4 +109,48 @@ public void Create_ForSolutionWithoutDirectoryFiles_DirectoryFileMustBeCreatedOn
.ToXmlString(_syntaxFormatter)
.Should().Be(directoryPackagesPropsContent);
}
+
+ [Fact]
+ public void Create_SolutionWithDirectoryBuildTargets_ReturnTargetFileContent()
+ {
+ string directoryBuildTargetContent = """
+
+
+
+ false
+
+
+
+ """;
+
+ _solutionFileStructureBuilderFactory.Create("Solution")
+ .AddDirectoryBuildTargets(directoryBuildTargetContent)
+ .Save(_currentPath);
+
+ DotnetSolutionModifier solutionModifier = _solutionModifierFactory.Create("Solution.sln");
+
+ solutionModifier
+ .GetOrCreateDirectoryBuildTargetFile()
+ .ToXmlString(_syntaxFormatter)
+ .Should().Be(directoryBuildTargetContent);
+ }
+
+ [Fact]
+ public void Create_SolutionWithoutDirectoryBuildTargets_ReturnEmptyTargetFileContent()
+ {
+ string directoryBuildTargetContent = """
+
+
+ """;
+
+ _solutionFileStructureBuilderFactory.Create("Solution")
+ .Save(_currentPath);
+
+ DotnetSolutionModifier solutionModifier = _solutionModifierFactory.Create("Solution.sln");
+
+ solutionModifier
+ .GetOrCreateDirectoryBuildTargetFile()
+ .ToXmlString(_syntaxFormatter)
+ .Should().Be(directoryBuildTargetContent);
+ }
}
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierTests.cs b/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierTests.cs
index b2ecef7..bb8277e 100644
--- a/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierTests.cs
+++ b/Sources/Kysect.DotnetProjectSystem.Tests/SolutionModification/DotnetSolutionModifierTests.cs
@@ -1,9 +1,11 @@
using Kysect.DotnetProjectSystem.FileStructureBuilding;
using Kysect.DotnetProjectSystem.Parsing;
+using Kysect.DotnetProjectSystem.Projects;
using Kysect.DotnetProjectSystem.SolutionModification;
using Kysect.DotnetProjectSystem.Tests.Asserts;
using Kysect.DotnetProjectSystem.Tools;
using Kysect.DotnetProjectSystem.Xml;
+using Microsoft.Language.Xml;
using System.IO.Abstractions.TestingHelpers;
namespace Kysect.DotnetProjectSystem.Tests.SolutionModification;
@@ -83,4 +85,31 @@ public void Save_AfterAddingValueToDirectoryBuildProps_FileSaved()
.ShouldExists()
.ShouldHaveContent(expectedContent);
}
+
+ [Fact]
+ public void Save_AfterModifyDirectoryBuildTargets_FileSaved()
+ {
+ var expectedContent = """
+
+
+
+ """;
+
+ _solutionFileStructureBuilderFactory.Create("Solution")
+ .AddDirectoryBuildTargets(DirectoryBuildTargetFile.CreateEmpty())
+ .Save(_currentPath);
+
+ DotnetSolutionModifier solutionModifier = _solutionModifierFactory.Create("Solution.sln");
+ solutionModifier
+ .GetOrCreateDirectoryBuildTargetFile()
+ .UpdateDocument(d => d.ReplaceNode(
+ d.Root.AsSyntaxElement.AsNode,
+ d.Root.AsSyntaxElement.AddChild(ExtendedSyntaxFactory.XmlElement("NewNode")).AsNode));
+ solutionModifier.Save();
+
+ _fileSystemAsserts
+ .File(SolutionItemNameConstants.DirectoryBuildTargets)
+ .ShouldExists()
+ .ShouldHaveContent(expectedContent);
+ }
}
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem/FileStructureBuilding/SolutionFileStructureBuilder.cs b/Sources/Kysect.DotnetProjectSystem/FileStructureBuilding/SolutionFileStructureBuilder.cs
index 5a04a91..36ba653 100644
--- a/Sources/Kysect.DotnetProjectSystem/FileStructureBuilding/SolutionFileStructureBuilder.cs
+++ b/Sources/Kysect.DotnetProjectSystem/FileStructureBuilding/SolutionFileStructureBuilder.cs
@@ -16,6 +16,7 @@ public class SolutionFileStructureBuilder
private readonly List _files;
private DirectoryBuildPropsFile? _directoryBuildPropsFile;
private DirectoryPackagesPropsFile? _directoryPackagesPropsFile;
+ private DirectoryBuildTargetFile? _directoryBuildTargetFile;
public SolutionFileStructureBuilder(IFileSystem fileSystem, XmlDocumentSyntaxFormatter syntaxFormatter, string solutionName)
{
@@ -66,11 +67,22 @@ public SolutionFileStructureBuilder AddDirectoryPackagesProps(DirectoryPackagesP
return this;
}
+ public SolutionFileStructureBuilder AddDirectoryBuildTargets(string content)
+ {
+ return AddDirectoryBuildTargets(DirectoryBuildTargetFile.Create(content));
+ }
+
+ public SolutionFileStructureBuilder AddDirectoryBuildTargets(DirectoryBuildTargetFile directoryBuildTargetFile)
+ {
+ _directoryBuildTargetFile = directoryBuildTargetFile;
+ return this;
+ }
+
public void Save(string solutionDirectory)
{
string solutionFileContent = CreateSolutionFile(_fileSystem);
- DirectoryExtensions.EnsureDirectoryExists(_fileSystem, solutionDirectory);
+ _fileSystem.EnsureDirectoryExists(solutionDirectory);
_fileSystem.File.WriteAllText(_fileSystem.Path.Combine(solutionDirectory, $"{_solutionName}.sln"), solutionFileContent);
if (_directoryBuildPropsFile is not null)
@@ -79,6 +91,9 @@ public void Save(string solutionDirectory)
if (_directoryPackagesPropsFile is not null)
AddFile([SolutionItemNameConstants.DirectoryPackagesProps], _directoryPackagesPropsFile.File.ToXmlString(_syntaxFormatter));
+ if (_directoryBuildTargetFile is not null)
+ AddFile([SolutionItemNameConstants.DirectoryBuildTargets], _directoryBuildTargetFile.ToXmlString(_syntaxFormatter));
+
foreach (SolutionStructureElement? solutionFileInfo in _files)
{
string partialFilePath = _fileSystem.Path.Combine(solutionFileInfo.Path.ToArray());
diff --git a/Sources/Kysect.DotnetProjectSystem/Projects/DirectoryBuildTargetFile.cs b/Sources/Kysect.DotnetProjectSystem/Projects/DirectoryBuildTargetFile.cs
new file mode 100644
index 0000000..2d5ab8c
--- /dev/null
+++ b/Sources/Kysect.DotnetProjectSystem/Projects/DirectoryBuildTargetFile.cs
@@ -0,0 +1,58 @@
+using Kysect.CommonLib.BaseTypes.Extensions;
+using Kysect.DotnetProjectSystem.Xml;
+using Microsoft.Language.Xml;
+
+namespace Kysect.DotnetProjectSystem.Projects;
+
+public class DirectoryBuildTargetFile
+{
+ private XmlDocumentSyntax _content;
+
+ public static DirectoryBuildTargetFile CreateEmpty()
+ {
+ string contentTemplate =
+ """
+
+
+ """;
+
+ return Create(contentTemplate);
+ }
+
+ public static DirectoryBuildTargetFile Create(string content)
+ {
+ XmlDocumentSyntax xmlDocumentSyntax = Parser.ParseText(content);
+ if (xmlDocumentSyntax.RootSyntax is null)
+ return CreateEmpty();
+
+ return new DirectoryBuildTargetFile(xmlDocumentSyntax);
+ }
+
+ public DirectoryBuildTargetFile(XmlDocumentSyntax content)
+ {
+ _content = content;
+ }
+
+ public IReadOnlyCollection GetTargets()
+ {
+ return GetNodesByName("Target");
+ }
+
+ public IReadOnlyCollection GetNodesByName(string name)
+ {
+ return _content.GetNodesByName(name);
+ }
+
+ public void UpdateDocument(Func morphism)
+ {
+ morphism.ThrowIfNull();
+ _content = morphism(_content);
+ }
+
+ public string ToXmlString(XmlDocumentSyntaxFormatter formatter)
+ {
+ formatter.ThrowIfNull();
+
+ return formatter.Format(_content).ToFullString();
+ }
+}
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifier.cs b/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifier.cs
index 42b5420..586be92 100644
--- a/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifier.cs
+++ b/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifier.cs
@@ -13,6 +13,7 @@ public class DotnetSolutionModifier
private readonly IFileSystem _fileSystem;
private DirectoryBuildPropsFile? _directoryBuildPropsModifier;
private DirectoryPackagesPropsFile? _directoryPackagePropsModifier;
+ private DirectoryBuildTargetFile? _directoryBuildTargetFile;
private readonly Dictionary _projects;
public IReadOnlyCollection> Projects => _projects;
@@ -29,10 +30,17 @@ public DirectoryPackagesPropsFile GetOrCreateDirectoryPackagePropsModifier()
return _directoryPackagePropsModifier;
}
+ public DirectoryBuildTargetFile GetOrCreateDirectoryBuildTargetFile()
+ {
+ _directoryBuildTargetFile ??= DirectoryBuildTargetFile.CreateEmpty();
+ return _directoryBuildTargetFile;
+ }
+
public DotnetSolutionModifier(
Dictionary projects,
DirectoryBuildPropsFile? directoryBuildPropsModifier,
DirectoryPackagesPropsFile? directoryPackagePropsModifier,
+ DirectoryBuildTargetFile? directoryBuildTargetsFile,
IFileSystem fileSystem,
IFileInfo solutionPath,
XmlDocumentSyntaxFormatter syntaxFormatter)
@@ -40,6 +48,7 @@ public DotnetSolutionModifier(
_projects = projects;
_directoryBuildPropsModifier = directoryBuildPropsModifier;
_directoryPackagePropsModifier = directoryPackagePropsModifier;
+ _directoryBuildTargetFile = directoryBuildTargetsFile;
_fileSystem = fileSystem;
_solutionPath = solutionPath;
_syntaxFormatter = syntaxFormatter;
@@ -61,6 +70,12 @@ public void Save()
_fileSystem.File.WriteAllText(directoryPackagesPropsPath, _directoryPackagePropsModifier.File.ToXmlString(_syntaxFormatter));
}
+ if (_directoryBuildTargetFile is not null)
+ {
+ string directoryPackagesPropsPath = _fileSystem.Path.Combine(_solutionPath.Directory.FullName, SolutionItemNameConstants.DirectoryBuildTargets);
+ _fileSystem.File.WriteAllText(directoryPackagesPropsPath, _directoryBuildTargetFile.ToXmlString(_syntaxFormatter));
+ }
+
foreach (KeyValuePair projectModifier in _projects)
{
_fileSystem.File.WriteAllText(projectModifier.Key, projectModifier.Value.File.ToXmlString(_syntaxFormatter));
diff --git a/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifierFactory.cs b/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifierFactory.cs
index 30a40a7..b5ed994 100644
--- a/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifierFactory.cs
+++ b/Sources/Kysect.DotnetProjectSystem/SolutionModification/DotnetSolutionModifierFactory.cs
@@ -28,12 +28,14 @@ public DotnetSolutionModifier Create(string solutionPath)
DirectoryBuildPropsFile? directoryBuildPropsModifier = TryCreateDirectoryBuildPropsFile(solutionFileInfo);
DirectoryPackagesPropsFile? directoryPackagesPropsFile = TryCreateDirectoryPackagesPropsFile(solutionFileInfo);
+ DirectoryBuildTargetFile? directoryBuildTargetsFile = TryCreateDirectoryBuildTargetsFile(solutionFileInfo);
Dictionary projects = CreateProjectModifiers(solutionFileInfo);
return new DotnetSolutionModifier(
projects,
directoryBuildPropsModifier,
directoryPackagesPropsFile,
+ directoryBuildTargetsFile,
_fileSystem,
solutionFileInfo,
_syntaxFormatter);
@@ -63,6 +65,22 @@ public DotnetSolutionModifier Create(string solutionPath)
return new DirectoryPackagesPropsFile(dotnetProjectFile);
}
+ private DirectoryBuildTargetFile? TryCreateDirectoryBuildTargetsFile(IFileInfo solutionFileInfo)
+ {
+ solutionFileInfo.Directory.ThrowIfNull();
+
+ string path = _fileSystem.Path.Combine(solutionFileInfo.Directory.FullName, SolutionItemNameConstants.DirectoryBuildTargets);
+ if (!_fileSystem.File.Exists(path))
+ return null;
+
+ string fileContent =
+ _fileSystem.File.Exists(path)
+ ? _fileSystem.File.ReadAllText(path)
+ : string.Empty;
+
+ return DirectoryBuildTargetFile.Create(fileContent);
+ }
+
private Dictionary CreateProjectModifiers(IFileInfo solutionFileInfo)
{
solutionFileInfo.Directory.ThrowIfNull();
diff --git a/Sources/Kysect.DotnetProjectSystem/Tools/SolutionItemNameConstants.cs b/Sources/Kysect.DotnetProjectSystem/Tools/SolutionItemNameConstants.cs
index 41caaf7..6a7b27f 100644
--- a/Sources/Kysect.DotnetProjectSystem/Tools/SolutionItemNameConstants.cs
+++ b/Sources/Kysect.DotnetProjectSystem/Tools/SolutionItemNameConstants.cs
@@ -4,4 +4,5 @@ public static class SolutionItemNameConstants
{
public const string DirectoryBuildProps = "Directory.Build.props";
public const string DirectoryPackagesProps = "Directory.Packages.props";
+ public const string DirectoryBuildTargets = "Directory.Build.targets";
}
\ No newline at end of file
diff --git a/Sources/Kysect.DotnetProjectSystem/Xml/XmlElementSyntaxExtensions.cs b/Sources/Kysect.DotnetProjectSystem/Xml/XmlElementSyntaxExtensions.cs
deleted file mode 100644
index aded487..0000000
--- a/Sources/Kysect.DotnetProjectSystem/Xml/XmlElementSyntaxExtensions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Kysect.CommonLib.BaseTypes.Extensions;
-using Microsoft.Language.Xml;
-
-namespace Kysect.DotnetProjectSystem.Xml;
-
-public static class XmlElementSyntaxExtensions
-{
- public static IXmlElementSyntax RemoveAllChild(this IXmlElementSyntax xmlElementSyntax)
- {
- xmlElementSyntax.ThrowIfNull();
-
- IXmlElementSyntax? child = xmlElementSyntax.Elements.FirstOrDefault();
-
- while (child is not null)
- {
- xmlElementSyntax = xmlElementSyntax.RemoveChild(child);
- child = xmlElementSyntax.Elements.FirstOrDefault();
- }
-
- return xmlElementSyntax;
- }
-}
\ No newline at end of file