Skip to content
Open
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
4 changes: 2 additions & 2 deletions Source/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<PackageVersion Include="PolySharp" Version="1.15.0" />
<PackageVersion Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556" />
<PackageVersion Include="Sundew.Base" Version="15.0.0-u20251116-020129-ci" />
<PackageVersion Include="Sundew.Packaging.Publish" Version="10.0.10-u20251005-144150-ci" />
<PackageVersion Include="Sundew.Xaml.Optimization" Version="3.0.0-u20251116-021731-ci" />
<PackageVersion Include="Sundew.Packaging.Publish" Version="10.0.10-u20251109-011824-ci" />
<PackageVersion Include="Sundew.Xaml.Optimization" Version="3.0.0-u20251116-224913-ci" />
<PackageVersion Include="Sundew.Xaml.Theming.Wpf" Version="0.1.0-u20251101-221236-ci" />
<PackageVersion Include="System.IO.Abstractions" Version="22.0.16" />
<PackageVersion Include="xunit" Version="2.9.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,4 +422,55 @@ public async Task Optimize_When_ThereIsOneMergedResourceDictionaryMarkedWithRemo

result.XamlFileChanges.Single().File.Document.ToString().Should().Be(XDocument.Parse(expectedResult).ToString());
}

[Theory]
[InlineData("Application")]
[InlineData("UserControl")]
[InlineData("Page")]
[InlineData("Window")]
public async Task Optimize_When_ThereIsOneMergedResourceDictionaryMarkedWithRemoveCategoryWithSxInDesignNamespace_Then_ResultShouldBeExpectedResult2(string rootType)
{
var input = $@"<{rootType} x:Class=""Sonova.Pegasi.Fsw.App.Wpf.App""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006""
xmlns:sxd=""http://sundew.dev/xaml/design""
Startup=""App_Startup""
mc:Ignorable=""sxd"">

<{rootType}.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--<ResourceDictionary Source=""pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml"" />-->
<ResourceDictionary Source=""/Sonova.Pegasi.Fsw.App.Wpf.Phonak;component/Themes/Designer.xaml"" sxd:ResourceDictionary.Category=""🎨"" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</{rootType}.Resources>
</{rootType}>
";

var expectedResult = $@"<{rootType} x:Class=""Sonova.Pegasi.Fsw.App.Wpf.App""
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:mc=""http://schemas.openxmlformats.org/markup-compatibility/2006""
xmlns:sxd=""http://sundew.dev/xaml/design""
Startup=""App_Startup""
mc:Ignorable=""sxd"">

<{rootType}.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--<ResourceDictionary Source=""pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml"" />-->
<ResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</{rootType}.Resources>
</{rootType}>";

var testee = new ResourceDictionaryOptimizer(new ResourceDictionarySettings([new OptimizationMapping("🎨", OptimizationAction.Remove)], true));

var result = await testee.OptimizeAsync(new XamlFiles([new XamlFile(XDocument.Parse(input), Substitute.For<IFileReference>(), Environment.NewLine), new XamlFile(XDocument.Parse(input), Substitute.For<IFileReference>(), Environment.NewLine)]), this.xamlPlatformInfo, this.projectInfo);

result.XamlFileChanges.Single().File.Document.ToString().Should().Be(XDocument.Parse(expectedResult).ToString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ namespace Sundew.Xaml.Optimizers.Wpf.Freezing;
using System.Collections.Generic;
using System.ComponentModel;
using Newtonsoft.Json;
using Sundew.Xaml.Optimization;

/// <summary>Settings for <see cref="FreezeResourceOptimizer"/>.</summary>
public class FreezeResourceSettings
public class FreezeResourceSettings : OptimizerSettings
{
/// <summary>Initializes a new instance of the <see cref="FreezeResourceSettings"/> class.</summary>
/// <param name="includeFrameworkTypes">if set to <c>true</c> [include framework types].</param>
/// <param name="includedTypes">The included types.</param>
/// <param name="excludedTypes">The excluded types.</param>
/// <param name="unfreezeMarker">The unfreeze marker.</param>
public FreezeResourceSettings(bool includeFrameworkTypes = true, IReadOnlyList<string>? includedTypes = null, IReadOnlyList<string>? excludedTypes = null, string? unfreezeMarker = null)
/// <param name="debug">A value indicating whether the optimizer should be debugged.</param>
public FreezeResourceSettings(bool includeFrameworkTypes = true, IReadOnlyList<string>? includedTypes = null, IReadOnlyList<string>? excludedTypes = null, string? unfreezeMarker = null, bool debug = false)
: base(debug)
{
this.IncludeFrameworkTypes = includeFrameworkTypes;
this.UnfreezeMarker = unfreezeMarker;
Expand Down
3 changes: 2 additions & 1 deletion Source/Sundew.Xaml.Optimizers.Wpf/ILRepack.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ILRepacker" BeforeTargets="PostBuildEvent" AfterTargets="Build">
<Target Name="ILRepacker" BeforeTargets="PostBuildEvent" AfterTargets="Build" Condition="$(Configuration.Contains('Release')) AND $(TargetFramework) != ''">

<ItemGroup>
<InputAssemblies Include="$(OutputPath)**\*.dll" />
Expand All @@ -12,6 +12,7 @@
</ItemGroup>

<ILRepack
DebugInfo="true"
Parallel="true"
Internalize="true"
InputAssemblies="$(OutputPath)\$(AssemblyName).dll;@(InputAssemblies)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@

namespace Sundew.Xaml.Optimizers.Wpf.ResourceDictionary.Internal;

using Sundew.Xaml.Optimization;

/// <summary>
/// Info about how a resource dictionary should be optimized.
/// </summary>
internal sealed class OptimizationInfo
internal sealed record OptimizationInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="OptimizationInfo"/> class.
/// </summary>
/// <param name="optimizationAction">The optimization action.</param>
/// <param name="replacementType">The replacement type.</param>
/// <param name="source">The binding.</param>
public OptimizationInfo(OptimizationAction optimizationAction, XamlType replacementType, string source)
/// <param name="xamlDiagnostic">The xaml diagnostic.</param>
public OptimizationInfo(OptimizationAction optimizationAction, XamlType replacementType, string source, XamlDiagnostic? xamlDiagnostic = null)
{
this.OptimizationAction = optimizationAction;
this.ReplacementType = replacementType;
this.Source = source;
this.XamlDiagnostic = xamlDiagnostic;
}

/// <summary>
Expand All @@ -45,4 +49,9 @@ public OptimizationInfo(OptimizationAction optimizationAction, XamlType replacem
/// The binding.
/// </value>
public string Source { get; }

/// <summary>
/// Gets diagnostic information related to XAML processing, if available.
/// </summary>
public XamlDiagnostic? XamlDiagnostic { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ namespace Sundew.Xaml.Optimizers.Wpf.ResourceDictionary.Internal;

using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Sundew.Base;
using Sundew.Xaml.Optimization;

/// <summary>
/// Provides an optimization info based on an <see cref="XElement"/>.
Expand Down Expand Up @@ -66,7 +69,20 @@ public static OptimizationInfo GetOptimizationInfo(
};
}

return new OptimizationInfo(OptimizationAction.None, defaultReplacementType, sourceAttribute.Value);
var (line, column) = categoryAttribute is IXmlLineInfo lineInfo ? (lineInfo.LineNumber, lineInfo.LinePosition) : (-1, -1);
return new OptimizationInfo(
OptimizationAction.None,
defaultReplacementType,
sourceAttribute.Value,
XamlDiagnostic.Warning(
ResourceDictionaryOptimizer.CategoryNotMapped,
"The element: {0} specified a category {1}, but the category was not mapping in settings.",
[resourceDictionaryElement.Name, categoryAttribute.Value],
resourceDictionaryElement.Document?.BaseUri ?? string.Empty,
line,
column,
line,
column));
}

return new OptimizationInfo(OptimizationAction.None, defaultReplacementType, string.Empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Sundew.Xaml.Optimizers.Wpf.ResourceDictionary;
/// </summary>
public class ResourceDictionaryOptimizer : IXamlOptimizer
{
internal const string CategoryNotMapped = "RDO0001";
private const string Source = "Source";
private static readonly XamlType FallbackReplacementType = new XamlType(Constants.SxPrefix, Constants.SundewXamlOptimizationNamespace, Constants.ResourceDictionaryName);
private readonly ResourceDictionarySettings resourceDictionarySettings;
Expand All @@ -50,19 +51,21 @@ public async ValueTask<OptimizationResult> OptimizeAsync(XamlFiles xamlFiles, Xa
var defaultReplaceUncategorized = this.resourceDictionarySettings.ReplaceUncategorized ?? xamlPlatformInfo.XamlPlatform == XamlPlatform.WPF;

var xamlFilesChanges = new ConcurrentBag<XamlFileChange>();
var xamlDiagnostics = new ConcurrentBag<XamlDiagnostic>();
await xamlFiles.ForEachAsync(
(xamlFile, token) =>
{
var mergedResourceDictionaries = xamlFile.Document.XPathSelectElements(
Constants.DefaultResourceDictionaryMergedDictionariesDefaultResourceDictionaryXPath,
xamlPlatformInfo.XmlNamespaceResolver);
var hasBeenOptimized = false;
var hasSxoNamespace = false;
if (!xamlFile.Document.Root.HasValue)
{
return Task.CompletedTask;
}

var mergedResourceDictionaries = xamlFile.Document.XPathSelectElements(
Constants.DefaultResourceDictionaryMergedDictionariesDefaultResourceDictionaryXPath,
xamlPlatformInfo.XmlNamespaceResolver);

var hasBeenOptimized = false;
var hasSxoNamespace = false;
foreach (var xElement in mergedResourceDictionaries.ToList())
{
var optimization = OptimizationProvider.GetOptimizationInfo(
Expand Down Expand Up @@ -95,6 +98,11 @@ await xamlFiles.ForEachAsync(
new XAttribute(Constants.SourceText, optimization.Source)));
break;
}

if (optimization.XamlDiagnostic.HasValue)
{
xamlDiagnostics.Add(optimization.XamlDiagnostic);
}
}

if (hasBeenOptimized)
Expand All @@ -105,6 +113,6 @@ await xamlFiles.ForEachAsync(
return Task.CompletedTask;
});

return OptimizationResult.From(xamlFilesChanges);
return OptimizationResult.From(xamlFilesChanges, xamlDiagnostics: xamlDiagnostics);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@
namespace Sundew.Xaml.Optimizers.Wpf.ResourceDictionary;

using System.Collections.Generic;
using Sundew.Xaml.Optimization;

/// <summary>
/// Used to deserialize settings for the <see cref="ResourceDictionaryOptimizer"/>.
/// </summary>
public class ResourceDictionarySettings
public class ResourceDictionarySettings : OptimizerSettings
{
/// <summary>
/// Initializes a new instance of the <see cref="ResourceDictionarySettings"/> class.
/// </summary>
/// <param name="optimizationMappings">The optimization mappings.</param>
/// <param name="replaceUncategorized">The replace uncategorized.</param>
/// <param name="replaceUncategorized">A value indicating whether uncategorized should be replaced.</param>
/// <param name="defaultReplacementType">The default replacement type.</param>
public ResourceDictionarySettings(IReadOnlyList<OptimizationMapping> optimizationMappings, bool? replaceUncategorized = null, string? defaultReplacementType = null)
/// <param name="debug">A value indicating whether the optimizer should be debugged.</param>
public ResourceDictionarySettings(IReadOnlyList<OptimizationMapping> optimizationMappings, bool? replaceUncategorized = null, string? defaultReplacementType = null, bool debug = false)
: base(debug)
{
this.OptimizationMappings = optimizationMappings;
this.ReplaceUncategorized = replaceUncategorized;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@

namespace Sundew.Xaml.Optimizers.Wpf.StaticToDynamicResource;

using Sundew.Xaml.Optimization;

/// <summary>
/// Settings for the <see cref="StaticToDynamicResourceOptimizer"/>.
/// </summary>
public class StaticToDynamicResourceSettings
public class StaticToDynamicResourceSettings : OptimizerSettings
{
/// <summary>
/// Initializes a new instance of the <see cref="StaticToDynamicResourceSettings"/> class with the specified dynamic marker.
/// </summary>
/// <param name="dynamicMarker">The dynamic marker.</param>
public StaticToDynamicResourceSettings(string? dynamicMarker = null)
/// <param name="debug">A value indicating whether the optimizer should be debugged.</param>
public StaticToDynamicResourceSettings(string? dynamicMarker = null, bool debug = false)
: base(debug)
{
this.DynamicMarker = dynamicMarker ?? "🔄️";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<SuppressDependenciesWhenPacking>false</SuppressDependenciesWhenPacking>
<NuspecFile>Sundew.Xaml.Optimizers.Wpf.nuspec</NuspecFile>
<NoWarn>$(NoWarn);NU5128;NU1701</NoWarn>
<SxowPath>$(AssemblyName).dll</SxowPath>
</PropertyGroup>

<PropertyGroup Condition="$(Configuration.Contains('Release')) AND $(TargetFramework) != ''">
<SxowPath>$(AssemblyName).m.dll</SxowPath>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -56,7 +61,7 @@

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<ItemGroup>
<OutputFiles Include="$(OutputPath)\$(AssemblyName).m.dll;$(OutputPath)**\System*.dll;$(OutputPath)Sundew.Xaml.Optimization.dll" />
<OutputFiles Include="$(OutputPath)\$(SxowPath);$(OutputPath)**\System*.dll;$(OutputPath)Sundew.Xaml.Optimization.dll" />
<BuildFiles Include="$(MSBuildProjectDirectory)\build\**\*.*" />
<ContentFiles Include="$(MSBuildProjectDirectory)\content\**\*.*" />
</ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions Source/Sundew.Xaml.Optimizers.Wpf/Theme/ThemeOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Sundew.Xaml.Optimizers.Wpf.Theme;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@

namespace Sundew.Xaml.Optimizers.Wpf.Theme;

using Sundew.Xaml.Optimization;

/// <summary>
/// Settings for the <see cref="ThemeOptimizer"/>.
/// </summary>
public class ThemeOptimizerSettings
public class ThemeOptimizerSettings : OptimizerSettings
{
/// <summary>
/// Initializes a new instance of the <see cref="ThemeOptimizerSettings"/> class.
/// </summary>
/// <param name="themesPath">The themes path.</param>
/// <param name="themeModesPath">The theme mode path.</param>
public ThemeOptimizerSettings(string themesPath, string themeModesPath)
/// <param name="debug">A value indicating whether the optimizer should be debugged.</param>
public ThemeOptimizerSettings(string themesPath, string themeModesPath, bool debug = false)
: base(debug)
{
this.ThemesPath = themesPath;
this.ThemeModesPath = themeModesPath;
Expand Down
Loading