From 69d2d87d7beca1a983f62a54c41dc4e799648d1f Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Wed, 8 Nov 2023 12:49:59 +0200 Subject: [PATCH] feat: Generate HotReload-friendly merged file when HR is enabled --- src/Directory.Build.props | 1 + src/Uno.XamlMerge.Task/BatchMergeXaml.cs | 74 +++++++++++++++++++ .../Uno.XamlMerge.Task.csproj | 1 - .../build/Uno.XamlMerge.Task.targets | 2 + .../Given_BatchMergeXaml.cs | 7 +- .../When_HR_Enabled/Input_Dictionary_1.xml | 7 ++ .../When_HR_Enabled/Input_Dictionary_2.xml | 7 ++ .../Scenarios/When_HR_Enabled/expected.xml | 9 +++ .../Uno.XamlMerge.Tests.csproj | 1 - 9 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_1.xml create mode 100644 src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_2.xml create mode 100644 src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/expected.xml diff --git a/src/Directory.Build.props b/src/Directory.Build.props index c41d3b1..d13c897 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,6 +2,7 @@ unoplatform + 11 https://github.com/unoplatform/uno.xamlmerge.task https://nv-assets.azurewebsites.net/logos/uno.png https://github.com/unoplatform/uno.xamlmerge.task diff --git a/src/Uno.XamlMerge.Task/BatchMergeXaml.cs b/src/Uno.XamlMerge.Task/BatchMergeXaml.cs index 188ee1e..c2bd0e9 100644 --- a/src/Uno.XamlMerge.Task/BatchMergeXaml.cs +++ b/src/Uno.XamlMerge.Task/BatchMergeXaml.cs @@ -11,6 +11,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Text; using System.Xml; namespace Uno.UI.Tasks.BatchMerge @@ -28,6 +29,9 @@ public class BatchMergeXaml_v0 : CustomTask [Required] public string ProjectFullPath { get; set; } + [Required] + public bool IsHotReloadEnabled { get; set; } + [Output] public string[] FilesWritten => _filesWritten.ToArray(); @@ -44,6 +48,12 @@ public override bool Execute() var filteredPages = Pages.ToList(); filteredPages.RemoveAll(e => MergedXamlFiles.Any(m => FullPathComparer.Default.Equals(e, m))); + if (IsHotReloadEnabled) + { + GenerateForHotReload(filteredPages); + return !HasLoggedErrors; + } + if (MergedXamlFiles.Length > 1) { foreach (var mergedXamlFile in MergedXamlFiles) @@ -69,6 +79,70 @@ public override bool Execute() return !HasLoggedErrors; } + private string GenerateMergedDictionariesForHotReload(IEnumerable filteredPages) + { + var projectBasePath = Path.GetDirectoryName(Path.GetFullPath(ProjectFullPath)); + + var builder = new StringBuilder(); + builder.Append(""" + + + + + + """); + + foreach (var page in filteredPages) + { + var pagePath = Path.GetFullPath(page.ItemSpec).Replace(projectBasePath, "").TrimStart(Path.DirectorySeparatorChar); + builder.Append($""" + + """); + } + + builder.Append(""" + + + + """); + + return builder.ToString(); + } + + /// + /// When HotReload is enabled, we want modifications to the original XAML files to be reflected. + /// This cannot be achieved when an actual merge happens. + /// So, for HotReload, we'll generate a XAML file that only references the original XAML files and not do an actual merge. + /// This way, it can work with HotReload perfectly. + /// + private void GenerateForHotReload(List filteredPages) + { + if (MergedXamlFiles.Length > 1) + { + foreach (var mergedXamlFile in MergedXamlFiles) + { + var mergeFileName = Path.GetFileName(mergedXamlFile.ItemSpec); + string fileContents = GenerateMergedDictionariesForHotReload(filteredPages.Where(p => string.Equals(p.GetMetadata("MergeFile"), mergeFileName, StringComparison.OrdinalIgnoreCase))); + + Directory.CreateDirectory(Path.GetDirectoryName(mergedXamlFile.ItemSpec)); + Utils.RewriteFileIfNecessary(mergedXamlFile.ItemSpec, fileContents); + } + } + else if (MergedXamlFiles.Length == 1) + { + // Single target file, without "MergeFile" attribution + var mergedXamlFile = MergedXamlFiles[0]; + var mergeFileName = Path.GetFileName(mergedXamlFile.ItemSpec); + string fileContents = GenerateMergedDictionariesForHotReload(filteredPages); + + Directory.CreateDirectory(Path.GetDirectoryName(mergedXamlFile.ItemSpec)); + Utils.RewriteFileIfNecessary(mergedXamlFile.ItemSpec, fileContents); + } + } + private void ValidatePageMergeFileMetadata() { if (MergedXamlFiles.Length > 1) diff --git a/src/Uno.XamlMerge.Task/Uno.XamlMerge.Task.csproj b/src/Uno.XamlMerge.Task/Uno.XamlMerge.Task.csproj index 609dfc6..df75650 100644 --- a/src/Uno.XamlMerge.Task/Uno.XamlMerge.Task.csproj +++ b/src/Uno.XamlMerge.Task/Uno.XamlMerge.Task.csproj @@ -4,7 +4,6 @@ netstandard2.0 enable enable - 10.0 True true Uno.XamlMerge.Task.v0 diff --git a/src/Uno.XamlMerge.Task/build/Uno.XamlMerge.Task.targets b/src/Uno.XamlMerge.Task/build/Uno.XamlMerge.Task.targets index 70a394c..116f799 100644 --- a/src/Uno.XamlMerge.Task/build/Uno.XamlMerge.Task.targets +++ b/src/Uno.XamlMerge.Task/build/Uno.XamlMerge.Task.targets @@ -12,9 +12,11 @@ DependsOnTargets="_XamlMergeFillProperties" Condition="'$(BuildingProject)' == 'true' or '$(DesignTimeBuild)' != 'true'"> + diff --git a/src/Uno.XamlMerge.Tests/Given_BatchMergeXaml.cs b/src/Uno.XamlMerge.Tests/Given_BatchMergeXaml.cs index d43982f..2a37881 100644 --- a/src/Uno.XamlMerge.Tests/Given_BatchMergeXaml.cs +++ b/src/Uno.XamlMerge.Tests/Given_BatchMergeXaml.cs @@ -28,9 +28,9 @@ public void When_Empty() } [TestMethod] - public void When_Key_TargeType_Conflict() + public void When_HR_Enabled() { - var task = CreateMerger(); + var task = CreateMerger(isHotReloadEnabled: true); Assert.IsTrue(task.Execute()); @@ -324,7 +324,7 @@ private void ValidateOutput(BatchMergeXaml_v0 task, [CallerMemberName] string te } } - private BatchMergeXaml_v0 CreateMerger([CallerMemberName] string testName = "") + private BatchMergeXaml_v0 CreateMerger(bool isHotReloadEnabled = false, [CallerMemberName] string testName = "") { var basePath = GetBasePath(testName); @@ -364,6 +364,7 @@ private BatchMergeXaml_v0 CreateMerger([CallerMemberName] string testName = "") .Distinct() .Select(f => new TaskItem(Path.Combine(basePath, "Output", f))) .ToArray(); + task.IsHotReloadEnabled = isHotReloadEnabled; return task; } diff --git a/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_1.xml b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_1.xml new file mode 100644 index 0000000..2e86580 --- /dev/null +++ b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_1.xml @@ -0,0 +1,7 @@ + + + Value1 + diff --git a/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_2.xml b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_2.xml new file mode 100644 index 0000000..6600e4b --- /dev/null +++ b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/Input_Dictionary_2.xml @@ -0,0 +1,7 @@ + + + Value2 + diff --git a/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/expected.xml b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/expected.xml new file mode 100644 index 0000000..966dfd6 --- /dev/null +++ b/src/Uno.XamlMerge.Tests/Scenarios/When_HR_Enabled/expected.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/Uno.XamlMerge.Tests/Uno.XamlMerge.Tests.csproj b/src/Uno.XamlMerge.Tests/Uno.XamlMerge.Tests.csproj index 8767271..e30c8c6 100644 --- a/src/Uno.XamlMerge.Tests/Uno.XamlMerge.Tests.csproj +++ b/src/Uno.XamlMerge.Tests/Uno.XamlMerge.Tests.csproj @@ -2,7 +2,6 @@ net6.0;net461 - 10 enable false