Browse Source

Merge pull request #9480 from AvaloniaUI/enable-trimming

Enable trimming and fix errors in multiple projects
Max Katz 2 years ago
parent
commit
567a38ec72
100 changed files with 446 additions and 109 deletions
  1. 4 1
      .editorconfig
  2. 4 2
      Avalonia.sln
  3. 1 1
      build/SharedVersion.props
  4. 16 0
      build/TrimmingEnable.props
  5. 0 1
      nukebuild/Build.cs
  6. 1 1
      nukebuild/_build.csproj
  7. 1 0
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  8. 0 2
      src/Avalonia.Base/Animation/Animation.cs
  9. 3 1
      src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
  10. 5 5
      src/Avalonia.Base/Avalonia.Base.csproj
  11. 2 0
      src/Avalonia.Base/AvaloniaProperty.cs
  12. 2 0
      src/Avalonia.Base/AvaloniaPropertyRegistry.cs
  13. 2 0
      src/Avalonia.Base/AvaloniaProperty`1.cs
  14. 3 1
      src/Avalonia.Base/Collections/AvaloniaListConverter.cs
  15. 121 0
      src/Avalonia.Base/Compatibility/TrimmingAttributes.cs
  16. 3 0
      src/Avalonia.Base/Data/BindingValue.cs
  17. 2 0
      src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
  18. 2 0
      src/Avalonia.Base/Data/Converters/MethodToCommandConverter.cs
  19. 2 0
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  20. 5 0
      src/Avalonia.Base/Data/Core/ExpressionObserver.cs
  21. 3 1
      src/Avalonia.Base/Data/Core/Parsers/ExpressionTreeParser.cs
  22. 2 0
      src/Avalonia.Base/Data/Core/Parsers/ExpressionVisitorNodeBuilder.cs
  23. 3 0
      src/Avalonia.Base/Data/Core/Plugins/AvaloniaPropertyAccessorPlugin.cs
  24. 4 0
      src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
  25. 3 0
      src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs
  26. 3 0
      src/Avalonia.Base/Data/Core/Plugins/IDataValidationPlugin.cs
  27. 3 0
      src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessorPlugin.cs
  28. 3 0
      src/Avalonia.Base/Data/Core/Plugins/IStreamPlugin.cs
  29. 3 0
      src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs
  30. 7 3
      src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs
  31. 7 2
      src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs
  32. 5 0
      src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs
  33. 6 1
      src/Avalonia.Base/Data/Core/Plugins/TaskStreamPlugin.cs
  34. 2 1
      src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs
  35. 2 0
      src/Avalonia.Base/Data/Core/StreamNode.cs
  36. 30 0
      src/Avalonia.Base/Diagnostics/TrimmingMessages.cs
  37. 2 0
      src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs
  38. 2 0
      src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs
  39. 2 0
      src/Avalonia.Base/StyledPropertyBase.cs
  40. 3 2
      src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
  41. 2 0
      src/Avalonia.Base/Styling/Setter.cs
  42. 3 0
      src/Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs
  43. 11 2
      src/Avalonia.Base/Utilities/TypeUtilities.cs
  44. 6 2
      src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs
  45. 2 1
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  46. 1 0
      src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj
  47. 1 49
      src/Avalonia.Controls/AppBuilderBase.cs
  48. 1 0
      src/Avalonia.Controls/Avalonia.Controls.csproj
  49. 11 1
      src/Avalonia.Controls/NativeMenuBar.cs
  50. 1 1
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  51. 12 1
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  52. 3 1
      src/Avalonia.Desktop/Avalonia.Desktop.csproj
  53. 1 0
      src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
  54. 1 0
      src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj
  55. 5 1
      src/Avalonia.Headless/Avalonia.Headless.csproj
  56. 2 0
      src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
  57. 1 1
      src/Avalonia.MicroCom/CallbackBase.cs
  58. 1 0
      src/Avalonia.Native/Avalonia.Native.csproj
  59. 1 0
      src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
  60. 1 0
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  61. 2 0
      src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
  62. 2 0
      src/Avalonia.Remote.Protocol/BsonStreamTransport.cs
  63. 3 1
      src/Avalonia.Remote.Protocol/BsonTcpTransport.cs
  64. 4 0
      src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs
  65. 9 2
      src/Avalonia.Remote.Protocol/MetsysBson.cs
  66. 3 0
      src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
  67. 3 0
      src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj
  68. 1 0
      src/Avalonia.X11/Avalonia.X11.csproj
  69. 3 1
      src/Avalonia.X11/X11Structs.cs
  70. 1 0
      src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj
  71. 1 0
      src/Browser/Avalonia.Browser/Avalonia.Browser.csproj
  72. 2 1
      src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj
  73. 2 1
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  74. 2 6
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  75. 4 1
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  76. 3 0
      src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
  77. 2 0
      src/Markup/Avalonia.Markup.Xaml/Extensions.cs
  78. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/ArrayElementPlugin.cs
  79. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs
  80. 2 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
  81. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/MethodAccessorPlugin.cs
  82. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/ObservableStreamPlugin.cs
  83. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorPlugin.cs
  84. 3 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/TaskStreamPlugin.cs
  85. 5 6
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs
  86. 3 1
      src/Markup/Avalonia.Markup.Xaml/Styling/ResourceInclude.cs
  87. 3 1
      src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs
  88. 2 0
      src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs
  89. 2 0
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  90. 2 0
      src/Markup/Avalonia.Markup.Xaml/XamlTypes.cs
  91. 1 0
      src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
  92. 2 0
      src/Markup/Avalonia.Markup/Data/Binding.cs
  93. 2 1
      src/Markup/Avalonia.Markup/Data/BindingBase.cs
  94. 5 1
      src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionObserverBuilder.cs
  95. 2 0
      src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs
  96. 2 0
      src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs
  97. 3 0
      src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs
  98. 1 0
      src/Skia/Avalonia.Skia/Avalonia.Skia.csproj
  99. 1 1
      src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
  100. 2 0
      src/Windows/Avalonia.Win32/Automation/AutomationNode.cs

+ 4 - 1
.editorconfig

@@ -64,7 +64,7 @@ dotnet_naming_symbols.static_fields.applicable_kinds   = field
 dotnet_naming_symbols.static_fields.required_modifiers = static
 
 dotnet_naming_style.static_prefix_style.required_prefix = s_
-dotnet_naming_style.static_prefix_style.capitalization = camel_case 
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
 
 # internal and private fields should be _camelCase
 dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
@@ -137,6 +137,9 @@ space_within_single_line_array_initializer_braces = true
 #Net Analyzer
 dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
 
+# CS1591: Missing XML comment for publicly visible type or member
+dotnet_diagnostic.CS1591.severity = suggestion
+
 # CA1304: Specify CultureInfo
 dotnet_diagnostic.CA1304.severity = warning
 # CA1802: Use literals where appropriate

+ 4 - 2
Avalonia.sln

@@ -40,6 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
 		.editorconfig = .editorconfig
 		src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
 		src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
+		src\Shared\NullableAttributes.cs = src\Shared\NullableAttributes.cs
 		src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
 		src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs = src\Avalonia.Base\Compatibility\StringCompatibilityExtensions.cs
 	EndProjectSection
@@ -119,6 +120,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 		build\SourceLink.props = build\SourceLink.props
 		build\System.Drawing.Common.props = build\System.Drawing.Common.props
 		build\System.Memory.props = build\System.Memory.props
+		build\TrimmingEnable.props = build\TrimmingEnable.props
 		build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
 		build\XUnit.props = build\XUnit.props
 	EndProjectSection
@@ -222,9 +224,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.iOS", "sample
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
 EndProject

+ 1 - 1
build/SharedVersion.props

@@ -7,7 +7,7 @@
     <PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>
     <RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
-    <NoWarn>CS1591</NoWarn>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
     <LangVersion>preview</LangVersion>
     <PackageLicenseExpression>MIT</PackageLicenseExpression>
     <PackageIcon>Icon.png</PackageIcon>

+ 16 - 0
build/TrimmingEnable.props

@@ -0,0 +1,16 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
+    <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
+    <TrimmerSingleWarn>false</TrimmerSingleWarn>
+    <IsTrimmable>true</IsTrimmable>
+  </PropertyGroup>
+  <!-- Remove check for the AOT when we get rid of dependencies with reflection -->
+  <PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0' and '$(PublishAot)' != 'true'">
+    <ILLinkTreatWarningsAsErrors>true</ILLinkTreatWarningsAsErrors>
+    <!-- Trim warnings -->
+    <WarningsAsErrors>$(WarningsAsErrors);IL2000;IL2001;IL2002;IL2003;IL2004;IL2005;IL2006;IL2007;IL2008;IL2009;IL2010;IL2011;IL2012;IL2013;IL2014;IL2015;IL2016;IL2017;IL2018;IL2019;IL2020;IL2021;IL2022;IL2023;IL2024;IL2025;IL2026;IL2027;IL2028;IL2029;IL2030;IL2031;IL2032;IL2033;IL2034;IL2035;IL2036;IL2037;IL2038;IL2039;IL2040;IL2041;IL2042;IL2043;IL2044;IL2045;IL2046;IL2047;IL2048;IL2049;IL2050;IL2051;IL2052;IL2053;IL2054;IL2055;IL2056;IL2057;IL2058;IL2059;IL2060;IL2061;IL2062;IL2063;IL2064;IL2065;IL2066;IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091;IL2092;IL2093;IL2094;IL2095;IL2096;IL2097;IL2098;IL2099;IL2100;IL2101;IL2102;IL2103;IL2104;IL2105;IL2106;IL2107;IL2108;IL2109;IL2110;IL2111;IL2112;IL2113;IL2114;IL2115;IL2116;IL2117;IL2118;IL2119;IL2120;IL2121;IL2122;IL2123;IL2124;IL2125;IL2126;IL2127;IL2128;IL2129;IL2130;IL2131;IL2132;IL2133;IL2134;IL2135;IL2136;IL2137;IL2138;IL2139;IL2140;IL2141;IL2142;IL2143;IL2144;IL2145;IL2146;IL2147;IL2148;IL2149;IL2150;IL2151;IL2152;IL2153;IL2154;IL2155;IL2156;IL2157</WarningsAsErrors>
+    <!-- NativeAOT warnings -->
+    <WarningsAsErrors>$(WarningsAsErrors);IL3050;IL3051;IL3052;IL3053;IL3054;IL3055;IL3056</WarningsAsErrors>
+  </PropertyGroup>
+</Project>

+ 0 - 1
nukebuild/Build.cs

@@ -80,7 +80,6 @@ partial class Build : NukeBuild
         if (Parameters.IsRunningOnAzure)
             c.AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_11_X64"));
         c.AddProperty("PackageVersion", Parameters.Version)
-            .AddProperty("iOSRoslynPathHackRequired", true)
             .SetConfiguration(Parameters.Configuration)
             .SetVerbosity(DotNetVerbosity.Minimal);
         return c;

+ 1 - 1
nukebuild/_build.csproj

@@ -4,7 +4,7 @@
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <RootNamespace></RootNamespace>
     <IsPackable>False</IsPackable>
-    <NoWarn>CS0649;CS0169;SYSLIB0011</NoWarn>
+    <NoWarn>$(NoWarn);CS0649;CS0169;SYSLIB0011</NoWarn>
     <NukeTelemetryVersion>1</NukeTelemetryVersion>
     <TargetFramework>net7.0</TargetFramework>
   </PropertyGroup>

+ 1 - 0
src/Android/Avalonia.Android/Avalonia.Android.csproj

@@ -16,4 +16,5 @@
     <ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
   </ItemGroup>
   <Import Project="..\..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 </Project>

+ 0 - 2
src/Avalonia.Base/Animation/Animation.cs

@@ -202,9 +202,7 @@ namespace Avalonia.Animation
         /// <param name="setter">The animation setter.</param>
         /// <param name="value">The property animator value.</param>
         public static void SetAnimator(IAnimationSetter setter, 
-#if NET6_0_OR_GREATER
             [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)]
-#endif
             Type value)
         {
             s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!);

+ 3 - 1
src/Avalonia.Base/Animation/AnimatorKeyFrame.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Animation.Animators;
 using Avalonia.Data;
 using Avalonia.Reactive;
@@ -66,7 +67,8 @@ namespace Avalonia.Animation
             }
         }
 
-        public T GetTypedValue<T>()
+        [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
+        public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
         {
             var typeConv = TypeDescriptor.GetConverter(typeof(T));
 

+ 5 - 5
src/Avalonia.Base/Avalonia.Base.csproj

@@ -19,6 +19,7 @@
   <Import Project="..\..\build\System.Memory.props" />
   <Import Project="..\..\build\ApiDiff.props" />
   <Import Project="..\..\build\NullableEnable.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
   <Import Project="..\..\build\DevAnalyzers.props" />
   <Import Project="..\..\build\SourceGenerators.props" />
   <ItemGroup>
@@ -30,6 +31,8 @@
     <InternalsVisibleTo Include="Avalonia.Base.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Benchmarks, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Controls, PublicKey=$(AvaloniaPublicKey)" />
+    <InternalsVisibleTo Include="Avalonia.Markup, PublicKey=$(AvaloniaPublicKey)" />
+    <InternalsVisibleTo Include="Avalonia.Markup.Xaml, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Controls.ColorPicker, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Controls.DataGrid, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Controls.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
@@ -41,6 +44,7 @@
     <InternalsVisibleTo Include="Avalonia.Skia.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Benchmarks, PublicKey=$(AvaloniaPublicKey)" />
+    <InternalsVisibleTo Include="Avalonia.X11, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Win32, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Dialogs, PublicKey=$(AvaloniaPublicKey)" />
     <InternalsVisibleTo Include="Avalonia.Diagnostics, PublicKey=$(AvaloniaPublicKey)" />
@@ -48,14 +52,10 @@
   </ItemGroup>
   
   <ItemGroup Label="Build dependency">
-    <ProjectReference Include="$(MSBuildThisFileDirectory)\..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj" 
-                      SetTargetFramework="TargetFramework=netstandard2.0"
-                      ReferenceOutputAssembly="false"
-                      SkipGetTargetFrameworkProperties="true" />
+    <ProjectReference Include="$(MSBuildThisFileDirectory)\..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj" SetTargetFramework="TargetFramework=netstandard2.0" ReferenceOutputAssembly="false" SkipGetTargetFrameworkProperties="true" />
   </ItemGroup>
 
   <ItemGroup>
-    <Folder Include="Compatibility\" />
     <Folder Include="Rendering\Composition\Utils" />
   </ItemGroup>
 </Project>

+ 2 - 0
src/Avalonia.Base/AvaloniaProperty.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Data;
 using Avalonia.Data.Core;
 using Avalonia.PropertyStore;
@@ -442,6 +443,7 @@ namespace Avalonia
         /// </summary>
         /// <param name="value">The value.</param>
         /// <returns>True if the value is valid, otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public bool IsValidValue(object? value)
         {
             return TypeUtilities.TryConvertImplicit(PropertyType, value, out _);

+ 2 - 0
src/Avalonia.Base/AvaloniaPropertyRegistry.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 
 namespace Avalonia
@@ -42,6 +43,7 @@ namespace Avalonia
         /// </summary>
         /// <param name="type">The type.</param>
         /// <returns>A collection of <see cref="AvaloniaProperty"/> definitions.</returns>
+        [UnconditionalSuppressMessage("Trimming", "IL2059", Justification = "If type was trimmed out, no properties were referenced")]
         public IReadOnlyList<AvaloniaProperty> GetRegistered(Type type)
         {
             _ = type ?? throw new ArgumentNullException(nameof(type));

+ 2 - 0
src/Avalonia.Base/AvaloniaProperty`1.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive.Subjects;
 using Avalonia.Data;
 using Avalonia.Utilities;
@@ -67,6 +68,7 @@ namespace Avalonia
 
         protected override IObservable<AvaloniaPropertyChangedEventArgs> GetChanged() => Changed;
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
         protected BindingValue<object?> TryConvert(object? value)
         {
             if (value == UnsetValue)

+ 3 - 1
src/Avalonia.Base/Collections/AvaloniaListConverter.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using Avalonia.Utilities;
 
@@ -8,7 +9,8 @@ namespace Avalonia.Collections
     /// <summary>
     /// Creates an <see cref="AvaloniaList{T}"/> from a string representation.
     /// </summary>
-    public class AvaloniaListConverter<T> : TypeConverter
+    [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
+    public class AvaloniaListConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : TypeConverter
     {
         public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
         {

+ 121 - 0
src/Avalonia.Base/Compatibility/TrimmingAttributes.cs

@@ -0,0 +1,121 @@
+#pragma warning disable MA0048 // File name must match type name
+// https://github.com/dotnet/runtime/tree/main/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis
+
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics.CodeAnalysis
+{
+#nullable enable
+#if !NET6_0_OR_GREATER
+    [AttributeUsage(
+        AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter |
+        AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method |
+        AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct,
+        Inherited = false)]
+    internal sealed class DynamicallyAccessedMembersAttribute : Attribute
+    {
+        public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes)
+        {
+            MemberTypes = memberTypes;
+        }
+
+        public DynamicallyAccessedMemberTypes MemberTypes { get; }
+    }
+    
+    [Flags]
+    internal enum DynamicallyAccessedMemberTypes
+    {
+        None = 0,
+        PublicParameterlessConstructor = 0x0001,
+        PublicConstructors = 0x0002 | PublicParameterlessConstructor,
+        NonPublicConstructors = 0x0004,
+        PublicMethods = 0x0008,
+        NonPublicMethods = 0x0010,
+        PublicFields = 0x0020,
+        NonPublicFields = 0x0040,
+        PublicNestedTypes = 0x0080,
+        NonPublicNestedTypes = 0x0100,
+        PublicProperties = 0x0200,
+        NonPublicProperties = 0x0400,
+        PublicEvents = 0x0800,
+        NonPublicEvents = 0x1000,
+        Interfaces = 0x2000,
+        All = ~None
+    }
+    
+    [AttributeUsage(
+        AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method,
+        AllowMultiple = true, Inherited = false)]
+    internal sealed class DynamicDependencyAttribute : Attribute
+    {
+        public DynamicDependencyAttribute(string memberSignature)
+        {
+            MemberSignature = memberSignature;
+        }
+
+        public DynamicDependencyAttribute(string memberSignature, Type type)
+        {
+            MemberSignature = memberSignature;
+            Type = type;
+        }
+
+        public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName)
+        {
+            MemberSignature = memberSignature;
+            TypeName = typeName;
+            AssemblyName = assemblyName;
+        }
+
+        public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type)
+        {
+            MemberTypes = memberTypes;
+            Type = type;
+        }
+
+        public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName)
+        {
+            MemberTypes = memberTypes;
+            TypeName = typeName;
+            AssemblyName = assemblyName;
+        }
+
+        public string? MemberSignature { get; }
+        public DynamicallyAccessedMemberTypes MemberTypes { get; }
+        public Type? Type { get; }
+        public string? TypeName { get; }
+        public string? AssemblyName { get; }
+        public string? Condition { get; set; }
+    }
+    
+    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)]
+    internal sealed class RequiresUnreferencedCodeAttribute : Attribute
+    {
+        public RequiresUnreferencedCodeAttribute(string message)
+        {
+            Message = message;
+        }
+
+        public string Message { get; }
+        public string? Url { get; set; }
+    }
+
+    [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
+    internal sealed class UnconditionalSuppressMessageAttribute : Attribute
+    {
+        public UnconditionalSuppressMessageAttribute(string category, string checkId)
+        {
+            Category = category;
+            CheckId = checkId;
+        }
+        public string Category { get; }
+        public string CheckId { get; }
+        public string? Scope { get; set; }
+        public string? Target { get; set; }
+        public string? MessageId { get; set; }
+        public string? Justification { get; set; }
+    }
+#endif
+}
+

+ 3 - 0
src/Avalonia.Base/Data/BindingValue.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Utilities;
 
 namespace Avalonia.Data
@@ -236,6 +237,7 @@ namespace Avalonia.Data
         /// </summary>
         /// <param name="value">The untyped value.</param>
         /// <returns>The typed binding value.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public static BindingValue<T> FromUntyped(object? value)
         {
             return FromUntyped(value, typeof(T));
@@ -249,6 +251,7 @@ namespace Avalonia.Data
         /// <param name="value">The untyped value.</param>
         /// <param name="targetType">The runtime target type.</param>
         /// <returns>The typed binding value.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public static BindingValue<T> FromUntyped(object? value, Type targetType)
         {
             if (value == AvaloniaProperty.UnsetValue)

+ 2 - 0
src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Windows.Input;
 using Avalonia.Utilities;
@@ -9,6 +10,7 @@ namespace Avalonia.Data.Converters
     /// Provides a default set of value conversions for bindings that do not specify a value
     /// converter.
     /// </summary>
+    [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
     public class DefaultValueConverter : IValueConverter
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Data/Converters/MethodToCommandConverter.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Linq.Expressions;
@@ -9,6 +10,7 @@ using Avalonia.Utilities;
 
 namespace Avalonia.Data.Converters
 {
+    [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
     class MethodToCommandConverter : ICommand
     {
         readonly static Func<object?, bool> AlwaysEnabled = (_) => true;

+ 2 - 0
src/Avalonia.Base/Data/Core/BindingExpression.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Reactive.Linq;
 using System.Reactive.Subjects;
@@ -13,6 +14,7 @@ namespace Avalonia.Data.Core
     /// Binds to an expression on an object using a type value converter to convert the values
     /// that are sent and received.
     /// </summary>
+    [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
     public class BindingExpression : LightweightObservableBase<object?>, ISubject<object?>, IDescription
     {
         private readonly ExpressionObserver _inner;

+ 5 - 0
src/Avalonia.Base/Data/Core/ExpressionObserver.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq.Expressions;
 using System.Reactive;
 using System.Reactive.Linq;
@@ -126,6 +127,7 @@ namespace Avalonia.Data.Core
         /// <param name="description">
         /// A description of the expression. If null, <paramref name="expression"/>'s string representation will be used.
         /// </param>
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ExpressionSafeSupressWarningMessage)]
         public static ExpressionObserver Create<T, U>(
             T? root,
             Expression<Func<T, U>> expression,
@@ -144,6 +146,7 @@ namespace Avalonia.Data.Core
         /// <param name="description">
         /// A description of the expression. If null, <paramref name="expression"/>'s string representation will be used.
         /// </param>
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ExpressionSafeSupressWarningMessage)]
         public static ExpressionObserver Create<T, U>(
             IObservable<T> rootObservable,
             Expression<Func<T, U>> expression,
@@ -168,6 +171,7 @@ namespace Avalonia.Data.Core
         /// <param name="description">
         /// A description of the expression. If null, <paramref name="expression"/>'s string representation will be used.
         /// </param>
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ExpressionSafeSupressWarningMessage)]
         public static ExpressionObserver Create<T, U>(
             Func<T> rootGetter,
             Expression<Func<T, U>> expression,
@@ -283,6 +287,7 @@ namespace Avalonia.Data.Core
             }
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
         private static ExpressionNode Parse(LambdaExpression expression, bool enableDataValidation)
         {
             return ExpressionTreeParser.Parse(expression, enableDataValidation);

+ 3 - 1
src/Avalonia.Base/Data/Core/Parsers/ExpressionTreeParser.cs

@@ -1,10 +1,12 @@
-using System.Linq;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
 using System.Linq.Expressions;
 
 namespace Avalonia.Data.Core.Parsers
 {
     static class ExpressionTreeParser
     {
+        [RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
         public static ExpressionNode Parse(Expression expr, bool enableDataValidation)
         {
             var visitor = new ExpressionVisitorNodeBuilder(enableDataValidation);

+ 2 - 0
src/Avalonia.Base/Data/Core/Parsers/ExpressionVisitorNodeBuilder.cs

@@ -1,11 +1,13 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Linq.Expressions;
 using System.Reflection;
 
 namespace Avalonia.Data.Core.Parsers
 {
+    [RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
     class ExpressionVisitorNodeBuilder : ExpressionVisitor
     {
         private const string MultiDimensionalArrayGetterMethodName = "Get";

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/AvaloniaPropertyAccessorPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Runtime.ExceptionServices;
 using Avalonia.Utilities;
 
@@ -10,6 +11,7 @@ namespace Avalonia.Data.Core.Plugins
     public class AvaloniaPropertyAccessorPlugin : IPropertyAccessorPlugin
     {
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName)
         {
             if (obj is AvaloniaObject o)
@@ -29,6 +31,7 @@ namespace Avalonia.Data.Core.Plugins
         /// An <see cref="IPropertyAccessor"/> interface through which future interactions with the 
         /// property will be made.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor? Start(WeakReference<object?> reference, string propertyName)
         {
             _ = reference ?? throw new ArgumentNullException(nameof(reference));

+ 4 - 0
src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 
@@ -12,6 +13,7 @@ namespace Avalonia.Data.Core.Plugins
     public class DataAnnotationsValidationPlugin : IDataValidationPlugin
     {
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public bool Match(WeakReference<object?> reference, string memberName)
         {
             reference.TryGetTarget(out var target);
@@ -24,11 +26,13 @@ namespace Avalonia.Data.Core.Plugins
         }
 
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object?> reference, string name, IPropertyAccessor inner)
         {
             return new Accessor(reference, name, inner);
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         private sealed class Accessor : DataValidationBase
         {
             private readonly ValidationContext? _context;

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/ExceptionValidationPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 
 namespace Avalonia.Data.Core.Plugins
@@ -9,9 +10,11 @@ namespace Avalonia.Data.Core.Plugins
     public class ExceptionValidationPlugin : IDataValidationPlugin
     {
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public bool Match(WeakReference<object?> reference, string memberName) => true;
 
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object?> reference, string name, IPropertyAccessor inner)
         {
             return new Validator(reference, name, inner);

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/IDataValidationPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Data.Core.Plugins
 {
@@ -13,6 +14,7 @@ namespace Avalonia.Data.Core.Plugins
         /// <param name="reference">A weak reference to the object.</param>
         /// <param name="memberName">The name of the member to validate.</param>
         /// <returns>True if the plugin can handle the object; otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         bool Match(WeakReference<object?> reference, string memberName);
 
         /// <summary>
@@ -25,6 +27,7 @@ namespace Avalonia.Data.Core.Plugins
         /// An <see cref="IPropertyAccessor"/> interface through which future interactions with the 
         /// property will be made.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         IPropertyAccessor Start(WeakReference<object?> reference,
             string propertyName,
             IPropertyAccessor inner);

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/IPropertyAccessorPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Data.Core.Plugins
 {
@@ -14,6 +15,7 @@ namespace Avalonia.Data.Core.Plugins
         /// <param name="obj">The object.</param>
         /// <param name="propertyName">The property name.</param>
         /// <returns>True if the plugin can handle the property on the object; otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         bool Match(object obj, string propertyName);
 
         /// <summary>
@@ -25,6 +27,7 @@ namespace Avalonia.Data.Core.Plugins
         /// An <see cref="IPropertyAccessor"/> interface through which future interactions with the 
         /// property will be made.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         IPropertyAccessor? Start(WeakReference<object?> reference,
             string propertyName);
     }

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/IStreamPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Data.Core.Plugins
 {
@@ -12,6 +13,7 @@ namespace Avalonia.Data.Core.Plugins
         /// </summary>
         /// <param name="reference">A weak reference to the value.</param>
         /// <returns>True if the plugin can handle the value; otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         bool Match(WeakReference<object?> reference);
 
         /// <summary>
@@ -21,6 +23,7 @@ namespace Avalonia.Data.Core.Plugins
         /// <returns>
         /// An observable that produces the output for the value.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         IObservable<object?> Start(WeakReference<object?> reference);
     }
 }

+ 3 - 0
src/Avalonia.Base/Data/Core/Plugins/IndeiValidationPlugin.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Avalonia.Utilities;
 
@@ -18,6 +19,7 @@ namespace Avalonia.Data.Core.Plugins
             );
 
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public bool Match(WeakReference<object?> reference, string memberName)
         {
             reference.TryGetTarget(out var target);
@@ -26,6 +28,7 @@ namespace Avalonia.Data.Core.Plugins
         }
 
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.DataValidationPluginRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object?> reference, string name, IPropertyAccessor accessor)
         {
             return new Validator(reference, name, accessor);

+ 7 - 3
src/Avalonia.Base/Data/Core/Plugins/InpcPropertyAccessorPlugin.cs

@@ -1,7 +1,7 @@
 using System;
 using System.Collections.Generic;
-using System.Collections.Specialized;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using Avalonia.Utilities;
 
@@ -17,6 +17,7 @@ namespace Avalonia.Data.Core.Plugins
             new Dictionary<(Type, string), PropertyInfo?>();
 
         /// <inheritdoc/>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName) => GetFirstPropertyWithName(obj, propertyName) != null;
 
         /// <summary>
@@ -28,6 +29,7 @@ namespace Avalonia.Data.Core.Plugins
         /// An <see cref="IPropertyAccessor"/> interface through which future interactions with the 
         /// property will be made.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor? Start(WeakReference<object?> reference, string propertyName)
         {
             _ = reference ?? throw new ArgumentNullException(nameof(reference));
@@ -52,7 +54,8 @@ namespace Avalonia.Data.Core.Plugins
 
         private const BindingFlags PropertyBindingFlags =
             BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
-        
+
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         private PropertyInfo? GetFirstPropertyWithName(object instance, string propertyName)
         {
             if (instance is IReflectableType reflectableType && instance is not Type)
@@ -70,7 +73,8 @@ namespace Avalonia.Data.Core.Plugins
             return propertyInfo;
         }
 
-        private PropertyInfo? TryFindAndCacheProperty(Type type, string propertyName)
+        private PropertyInfo? TryFindAndCacheProperty(
+            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type, string propertyName)
         {
             PropertyInfo? found = null;
 

+ 7 - 2
src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq.Expressions;
 using System.Reflection;
 
@@ -10,8 +11,10 @@ namespace Avalonia.Data.Core.Plugins
         private readonly Dictionary<(Type, string), MethodInfo?> _methodLookup =
             new Dictionary<(Type, string), MethodInfo?>();
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string methodName) => GetFirstMethodWithName(obj.GetType(), methodName) != null;
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor? Start(WeakReference<object?> reference, string methodName)
         {
             _ = reference ?? throw new ArgumentNullException(nameof(reference));
@@ -34,7 +37,8 @@ namespace Avalonia.Data.Core.Plugins
             }
         }
 
-        private MethodInfo? GetFirstMethodWithName(Type type, string methodName)
+        private MethodInfo? GetFirstMethodWithName(
+            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type, string methodName)
         {
             var key = (type, methodName);
 
@@ -46,7 +50,8 @@ namespace Avalonia.Data.Core.Plugins
             return methodInfo;
         }
 
-        private MethodInfo? TryFindAndCacheMethod(Type type, string methodName)
+        private MethodInfo? TryFindAndCacheMethod(
+            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type, string methodName)
         {
             MethodInfo? found = null;
 

+ 5 - 0
src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reactive.Linq;
 using System.Reflection;
@@ -8,6 +9,7 @@ namespace Avalonia.Data.Core.Plugins
     /// <summary>
     /// Handles binding to <see cref="IObservable{T}"/>s for the '^' stream binding operator.
     /// </summary>
+    [UnconditionalSuppressMessage("Trimming", "IL3050", Justification = TrimmingMessages.IgnoreNativeAotSupressWarningMessage)]
     public class ObservableStreamPlugin : IStreamPlugin
     {
         static MethodInfo? observableSelect;
@@ -17,6 +19,7 @@ namespace Avalonia.Data.Core.Plugins
         /// </summary>
         /// <param name="reference">A weak reference to the value.</param>
         /// <returns>True if the plugin can handle the value; otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public virtual bool Match(WeakReference<object?> reference)
         {
             reference.TryGetTarget(out var target);
@@ -33,6 +36,7 @@ namespace Avalonia.Data.Core.Plugins
         /// <returns>
         /// An observable that produces the output for the value.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public virtual IObservable<object?> Start(WeakReference<object?> reference)
         {
             if (!reference.TryGetTarget(out var target) || target is null)
@@ -65,6 +69,7 @@ namespace Avalonia.Data.Core.Plugins
                 new object[] { target, box })!;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         private static MethodInfo GetObservableSelect(Type source)
         {
             return GetObservableSelect().MakeGenericMethod(source, typeof(object));

+ 6 - 1
src/Avalonia.Base/Data/Core/Plugins/TaskStreamPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive.Linq;
 using System.Reactive.Subjects;
 using System.Reflection;
@@ -9,6 +10,7 @@ namespace Avalonia.Data.Core.Plugins
     /// <summary>
     /// Handles binding to <see cref="Task"/>s for the '^' stream binding operator.
     /// </summary>
+    [UnconditionalSuppressMessage("Trimming", "IL3050", Justification = TrimmingMessages.IgnoreNativeAotSupressWarningMessage)]
     public class TaskStreamPlugin : IStreamPlugin
     {
         /// <summary>
@@ -16,12 +18,13 @@ namespace Avalonia.Data.Core.Plugins
         /// </summary>
         /// <param name="reference">A weak reference to the value.</param>
         /// <returns>True if the plugin can handle the value; otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public virtual bool Match(WeakReference<object?> reference)
         {
             reference.TryGetTarget(out var target);
 
             return target is Task;
-        } 
+        }
 
         /// <summary>
         /// Starts producing output based on the specified value.
@@ -30,6 +33,7 @@ namespace Avalonia.Data.Core.Plugins
         /// <returns>
         /// An observable that produces the output for the value.
         /// </returns>
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public virtual IObservable<object?> Start(WeakReference<object?> reference)
         {
             reference.TryGetTarget(out var target);
@@ -59,6 +63,7 @@ namespace Avalonia.Data.Core.Plugins
             return Observable.Empty<object?>();
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         private static IObservable<object?> HandleCompleted(Task task)
         {
             var resultProperty = task.GetType().GetRuntimeProperty("Result");

+ 2 - 1
src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs

@@ -1,9 +1,10 @@
 using System;
-using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Data.Core.Plugins;
 
 namespace Avalonia.Data.Core
 {
+    [RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
     public class PropertyAccessorNode : SettableNode
     {
         private readonly bool _enableValidation;

+ 2 - 0
src/Avalonia.Base/Data/Core/StreamNode.cs

@@ -1,9 +1,11 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive.Linq;
 using Avalonia.Data.Core.Plugins;
 
 namespace Avalonia.Data.Core
 {
+    [RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
     public class StreamNode : ExpressionNode
     {
         private IStreamPlugin? _customPlugin = null;

+ 30 - 0
src/Avalonia.Base/Diagnostics/TrimmingMessages.cs

@@ -0,0 +1,30 @@
+namespace Avalonia;
+
+internal static class TrimmingMessages
+{
+    public const string ImplicitTypeConvertionSupressWarningMessage = "Implicit convertion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible.";
+    public const string ImplicitTypeConvertionRequiresUnreferencedCodeMessage = "Implicit convertion methods are required for type conversion.";
+
+    public const string TypeConvertionSupressWarningMessage = "Convertion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible.";
+    public const string TypeConvertionRequiresUnreferencedCodeMessage = "Convertion methods are required for type conversion, including op_Implicit, op_Explicit, Parse and TypeConverter.";
+
+    public const string ReflectionBindingRequiresUnreferencedCodeMessage = "BindingExpression and ReflectionBinding heavily use reflection. Consider using CompiledBindings instead.";
+    public const string ReflectionBindingSupressWarningMessage = "BindingExpression and ReflectionBinding internal heavily use reflection.";
+
+    public const string CompiledBindingSafeSupressWarningMessage = "CompiledBinding preserves members used in the expression tree.";
+
+    public const string ExpressionNodeRequiresUnreferencedCodeMessage = "ExpressionNode might require unreferenced code.";
+    public const string ExpressionSafeSupressWarningMessage = "Typed Expressions preserves members used in the expression tree.";
+
+    public const string SelectorsParseRequiresUnreferencedCodeMessage = "Selectors runtime parser might require unreferenced code. Consider using stronly typed selectors factory with 'new Style(s => s.OfType<Button>())' syntax.";
+
+    public const string PropertyAccessorsRequiresUnreferencedCodeMessage = "PropertyAccessors might require unreferenced code.";
+    public const string DataValidationPluginRequiresUnreferencedCodeMessage = "DataValidationPlugin might require unreferenced code.";
+    public const string StreamPluginRequiresUnreferencedCodeMessage = "StreamPlugin might require unreferenced code.";
+
+    public const string StyleResourceIncludeRequiresUnreferenceCodeMessage = "StyleInclude and ResourceInclude use AvaloniaXamlLoader.Load which dynamically loads referenced assembly with Avalonia resources. Note, StyleInclude and ResourceInclude defined in XAML are resolved compile time and are safe with trimming and AOT.";
+    public const string AvaloniaXamlLoaderRequiresUnreferenceCodeMessage = "AvaloniaXamlLoader.Load(uri, baseUri) dynamically loads referenced assembly with Avalonia resources.";
+    public const string XamlTypeResolvedRequiresUnreferenceCodeMessage = "XamlTypeResolver might require unreferenced code.";
+
+    public const string IgnoreNativeAotSupressWarningMessage = "This method is not supported by NativeAOT.";
+}

+ 2 - 0
src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs

@@ -1,9 +1,11 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Data;
 using Avalonia.Threading;
 
 namespace Avalonia.PropertyStore
 {
+    [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
     internal class DirectUntypedBindingObserver<T> : IObserver<object?>,
         IDisposable
     {

+ 2 - 0
src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs

@@ -7,6 +7,7 @@ namespace Avalonia.PropertyStore
 {
     internal static class UntypedValueUtils
     {
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
         public static BindingValue<T> ConvertAndValidate<T>(
             object? value,
             Type targetType,
@@ -23,6 +24,7 @@ namespace Avalonia.PropertyStore
             return v;
         }
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
         public static bool TryConvertAndValidate<T>(
             StyledPropertyBase<T> property,
             object? value, 

+ 2 - 0
src/Avalonia.Base/StyledPropertyBase.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using Avalonia.Data;
 using Avalonia.PropertyStore;
@@ -206,6 +207,7 @@ namespace Avalonia
         }
 
         /// <inheritdoc/>
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
         internal override IDisposable? RouteSetValue(
             AvaloniaObject target,
             object? value,

+ 3 - 2
src/Avalonia.Base/Styling/PropertyEqualsSelector.cs

@@ -1,11 +1,10 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using Avalonia.Styling.Activators;
 using Avalonia.Utilities;
 
-#nullable enable
-
 namespace Avalonia.Styling
 {
     /// <summary>
@@ -92,6 +91,8 @@ namespace Avalonia.Styling
         protected override Selector? MovePrevious() => _previous;
         protected override Selector? MovePreviousOrParent() => _previous;
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)]
+        [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)]
         internal static bool Compare(Type propertyType, object? propertyValue, object? value)
         {
             if (propertyType == typeof(object) &&

+ 2 - 0
src/Avalonia.Base/Styling/Setter.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Animation;
 using Avalonia.Data;
 using Avalonia.Metadata;
@@ -64,6 +65,7 @@ namespace Avalonia.Styling
 
         void IValueEntry.Unsubscribe() { }
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)]
         ISetterInstance ISetter.Instance(IStyleInstance instance, StyledElement target)
         {
             if (target is not AvaloniaObject ao)

+ 3 - 0
src/Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Runtime.Serialization;
 using System.Xml.Linq;
 using System.Linq;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Utilities
 {
@@ -33,6 +34,7 @@ namespace Avalonia.Utilities
             return entries;
         }
 
+        [RequiresUnreferencedCode("AvaloniaResources uses Data Contract Serialization, which might require unreferenced code")]
         public static void Write(Stream stream, List<AvaloniaResourcesIndexEntry> entries)
         {
             new BinaryWriter(stream).Write(LastKnownVersion);
@@ -43,6 +45,7 @@ namespace Avalonia.Utilities
                 });
         }
 
+        [RequiresUnreferencedCode("AvaloniaResources uses Data Contract Serialization, which might require unreferenced code")]
         public static byte[] Create(Dictionary<string, byte[]> data)
         {
             var sources = data.ToList();

+ 11 - 2
src/Avalonia.Base/Utilities/TypeUtilities.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
@@ -125,6 +126,7 @@ namespace Avalonia.Utilities
         /// <param name="culture">The culture to use.</param>
         /// <param name="result">If successful, contains the convert value.</param>
         /// <returns>True if the cast was successful, otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
         public static bool TryConvert(Type to, object? value, CultureInfo? culture, out object? result)
         {
             if (value == null)
@@ -150,7 +152,7 @@ namespace Avalonia.Utilities
 
             if (toUnderl == typeof(string))
             {
-                result = Convert.ToString(value, culture);
+                result = Convert.ToString(value, culture)!;
                 return true;
             }
 
@@ -244,6 +246,7 @@ namespace Avalonia.Utilities
         /// <param name="value">The value to convert.</param>
         /// <param name="result">If successful, contains the converted value.</param>
         /// <returns>True if the convert was successful, otherwise false.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public static bool TryConvertImplicit(Type to, object? value, out object? result)
         {
             if (value == null)
@@ -306,6 +309,7 @@ namespace Avalonia.Utilities
         /// <param name="type">The type to convert to..</param>
         /// <param name="culture">The culture to use.</param>
         /// <returns>A value of <paramref name="type"/>.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)]
         public static object? ConvertOrDefault(object? value, Type type, CultureInfo culture)
         {
             return TryConvert(type, value, culture, out var result) ? result : Default(type);
@@ -318,11 +322,13 @@ namespace Avalonia.Utilities
         /// <param name="value">The value to convert.</param>
         /// <param name="type">The type to convert to.</param>
         /// <returns>A value of <paramref name="type"/>.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public static object? ConvertImplicitOrDefault(object? value, Type type)
         {
             return TryConvertImplicit(type, value, out var result) ? result : Default(type);
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)]
         public static T ConvertImplicit<T>(object value)
         {
             if (TryConvertImplicit(typeof(T), value, out var result))
@@ -339,6 +345,7 @@ namespace Avalonia.Utilities
         /// </summary>
         /// <param name="type">The type.</param>
         /// <returns>The default value.</returns>
+        [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "We don't care about public ctors for the value types, and always return null for the ref types.")]
         public static object? Default(Type type)
         {
             if (type.IsValueType)
@@ -391,7 +398,9 @@ namespace Avalonia.Utilities
             return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
         }
 
-        private static MethodInfo? FindTypeConversionOperatorMethod(Type fromType, Type toType, OperatorType operatorType)
+        private static MethodInfo? FindTypeConversionOperatorMethod(
+            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type fromType,
+            Type toType, OperatorType operatorType)
         {
             const string implicitName = "op_Implicit";
             const string explicitName = "op_Explicit";

+ 6 - 2
src/Avalonia.Base/Utilities/WeakEventHandlerManager.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using System.Runtime.CompilerServices;
@@ -20,7 +21,8 @@ namespace Avalonia.Utilities
         /// <param name="target">The event source.</param>
         /// <param name="eventName">The name of the event.</param>
         /// <param name="subscriber">The subscriber.</param>
-        public static void Subscribe<TTarget, TEventArgs, TSubscriber>(TTarget target, string eventName, EventHandler<TEventArgs> subscriber)
+        public static void Subscribe<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] TTarget, TEventArgs, TSubscriber>(
+            TTarget target, string eventName, EventHandler<TEventArgs> subscriber)
             where TEventArgs : EventArgs where TSubscriber : class
         {
             _ = target ?? throw new ArgumentNullException(nameof(target));
@@ -92,7 +94,9 @@ namespace Avalonia.Utilities
             private static Dictionary<MethodInfo, CallerDelegate> s_Callers =
                 new Dictionary<MethodInfo, CallerDelegate>();
             
-            public Subscription(SubscriptionDic<T, TSubscriber> sdic, Type targetType, object target, string eventName)
+            public Subscription(SubscriptionDic<T, TSubscriber> sdic,
+                [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] Type targetType,
+                object target, string eventName)
             {
                 _sdic = sdic;
                 _target = target;

+ 2 - 1
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@@ -6,7 +6,7 @@
         <BuildOutputTargetFolder>tools</BuildOutputTargetFolder>
         <DefineConstants>$(DefineConstants);BUILDTASK;XAMLX_CECIL_INTERNAL;XAMLX_INTERNAL</DefineConstants>
         <CopyLocalLockFileAssemblies Condition="$(TargetFramework) == 'netstandard2.0'">true</CopyLocalLockFileAssemblies>
-        <NoWarn>NU1605;CS8632</NoWarn>
+        <NoWarn>$(NoWarn);NU1605;CS8632</NoWarn>
     </PropertyGroup>
 
     <!--Disable Net Perf. analyzer for submodule to avoid commit issue -->
@@ -111,6 +111,7 @@
         <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
       </Compile>
       <Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />
+      <Compile Include="..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
       <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" />
       <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
       <PackageReference Include="Mono.Cecil" Version="0.11.4" />

+ 1 - 0
src/Avalonia.Controls.ColorPicker/Avalonia.Controls.ColorPicker.csproj

@@ -21,6 +21,7 @@
   <Import Project="..\..\build\BuildTargets.targets" />
   <!--<Import Project="..\..\build\ApiDiff.props" />-->
   <Import Project="..\..\build\NullableEnable.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
   <Import Project="..\..\build\DevAnalyzers.props" />
 
   <ItemGroup Label="InternalsVisibleTo">

+ 1 - 49
src/Avalonia.Controls/AppBuilderBase.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Linq;
 using Avalonia.Controls.ApplicationLifetimes;
@@ -162,13 +163,6 @@ namespace Avalonia.Controls
             return Self;
         }
 
-        /// <summary>
-        /// Specifies a windowing subsystem to use.
-        /// </summary>
-        /// <param name="dll">The dll in which to look for subsystem.</param>
-        /// <returns>An <typeparamref name="TAppBuilder"/> instance.</returns>
-        public TAppBuilder UseWindowingSubsystem(string dll) => UseWindowingSubsystem(GetInitializer(dll), dll.Replace("Avalonia.", string.Empty));
-
         /// <summary>
         /// Specifies a rendering subsystem to use.
         /// </summary>
@@ -182,50 +176,8 @@ namespace Avalonia.Controls
             return Self;
         }
 
-        /// <summary>
-        /// Specifies a rendering subsystem to use.
-        /// </summary>
-        /// <param name="dll">The dll in which to look for subsystem.</param>
-        /// <returns>An <typeparamref name="TAppBuilder"/> instance.</returns>
-        public TAppBuilder UseRenderingSubsystem(string dll) => UseRenderingSubsystem(GetInitializer(dll));
-
-        static Action GetInitializer(string assemblyName) => () =>
-        {
-            var assembly = Assembly.Load(new AssemblyName(assemblyName));
-            var platformClassName = assemblyName.Replace("Avalonia.", string.Empty) + "Platform";
-            var platformClassFullName = assemblyName + "." + platformClassName;
-            var platformClass = assembly.GetType(platformClassFullName);
-            var init = platformClass!.GetRuntimeMethod("Initialize", Type.EmptyTypes);
-            init!.Invoke(null, null);
-        };
-
-        public TAppBuilder UseAvaloniaModules() => AfterSetup(builder => SetupAvaloniaModules());
-
         protected virtual bool CheckSetup => true;
 
-        /// <summary>
-        /// Searches and initiates modules included with <see cref="ExportAvaloniaModuleAttribute"/> attribute.
-        /// </summary>
-        private void SetupAvaloniaModules()
-        {
-            var moduleInitializers = from assembly in AppDomain.CurrentDomain.GetAssemblies()
-                                     from attribute in assembly.GetCustomAttributes<ExportAvaloniaModuleAttribute>()
-                                     where string.IsNullOrEmpty(attribute.ForWindowingSubsystem)
-                                      || attribute.ForWindowingSubsystem == WindowingSubsystemName
-                                     where string.IsNullOrEmpty(attribute.ForRenderingSubsystem)
-                                      || attribute.ForRenderingSubsystem == RenderingSubsystemName
-                                     group attribute by attribute.Name into exports
-                                     select (from export in exports
-                                             orderby export.ForWindowingSubsystem.Length descending
-                                             orderby export.ForRenderingSubsystem.Length descending
-                                             select export).First().ModuleType into moduleType
-                                     select (from constructor in moduleType.GetTypeInfo().DeclaredConstructors
-                                             where constructor.GetParameters().Length == 0 && !constructor.IsStatic
-                                             select constructor).Single() into constructor
-                                     select (Action)(() => constructor.Invoke(Array.Empty<object>()));
-            Delegate.Combine(moduleInitializers.ToArray())!.DynamicInvoke();
-        }
-
         /// <summary>
         /// Configures platform-specific options
         /// </summary>

+ 1 - 0
src/Avalonia.Controls/Avalonia.Controls.csproj

@@ -10,6 +10,7 @@
   <Import Project="..\..\build\JetBrains.Annotations.props" />
   <Import Project="..\..\build\ApiDiff.props" />
   <Import Project="..\..\build\NullableEnable.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
   <Import Project="..\..\build\DevAnalyzers.props" />
 
   <ItemGroup Label="InternalsVisibleTo">

+ 11 - 1
src/Avalonia.Controls/NativeMenuBar.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Controls.Primitives;
 using Avalonia.Interactivity;
 
@@ -21,7 +22,16 @@ namespace Avalonia.Controls
                     item.Click -= OnMenuItemClick;
             });
         }
-        
+
+        [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenu))]
+        [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItem))]
+        [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItemBase))]
+        [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NativeMenuItemSeparator))]
+        public NativeMenuBar()
+        {
+
+        }
+
         public static void SetEnableMenuItemClickForwarding(MenuItem menuItem, bool enable)
         {
             menuItem.SetValue(EnableMenuItemClickForwardingProperty, enable);

+ 1 - 1
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@@ -7,7 +7,7 @@
          need change when there are breaking changes to designer support api.
     -->
     <Version>0.7.0</Version>
-    <NoWarn>CS1591</NoWarn>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <NugetPackageName>Avalonia</NugetPackageName>
   </PropertyGroup>

+ 12 - 1
src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Net;
 using System.Reflection;
 using System.Threading;
@@ -150,10 +151,20 @@ namespace Avalonia.DesignerSupport.Remote
                 }
 
                 if (args.Method == Methods.Win32)
-                    builder.UseWindowingSubsystem("Avalonia.Win32");
+                    builder.UseWindowingSubsystem(GetInitializer("Avalonia.Win32"), "Win32");
                 builder.SetupWithoutStarting();
                 return transport;
             }
+
+            private static Action GetInitializer(string assemblyName) => () =>
+            {
+                var assembly = Assembly.Load(new AssemblyName(assemblyName));
+                var platformClassName = assemblyName.Replace("Avalonia.", string.Empty) + "Platform";
+                var platformClassFullName = assemblyName + "." + platformClassName;
+                var platformClass = assembly.GetType(platformClassFullName);
+                var init = platformClass!.GetRuntimeMethod("Initialize", Type.EmptyTypes);
+                init!.Invoke(null, null);
+            };
         }
 
         private const string BuilderMethodName = "BuildAvaloniaApp";

+ 3 - 1
src/Avalonia.Desktop/Avalonia.Desktop.csproj

@@ -12,5 +12,7 @@
       <ProjectReference Include="../Avalonia.X11/Avalonia.X11.csproj" />
   </ItemGroup>
   
-  <Import Project="..\..\build\ApiDiff.props" />  
+  <Import Project="..\..\build\ApiDiff.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
+  <Import Project="..\..\build\NullableEnable.props" />
 </Project>

+ 1 - 0
src/Avalonia.Dialogs/Avalonia.Dialogs.csproj

@@ -16,4 +16,5 @@
 
   <Import Project="..\..\build\ApiDiff.props" />
   <Import Project="..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 1 - 0
src/Avalonia.Headless.Vnc/Avalonia.Headless.Vnc.csproj

@@ -9,4 +9,5 @@
       <PackageReference Include="Quamotion.RemoteViewing" Version="1.1.21" />
     </ItemGroup>
 
+    <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 5 - 1
src/Avalonia.Headless/Avalonia.Headless.csproj

@@ -5,5 +5,9 @@
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
-  </ItemGroup>  
+  </ItemGroup>
+
+  <Import Project="..\..\build\ApiDiff.props" />
+  <Import Project="..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 2 - 0
src/Avalonia.MicroCom/Avalonia.MicroCom.csproj

@@ -13,4 +13,6 @@
     </ProjectReference>
   </ItemGroup>
   <Import Project="..\..\build\BuildTargets.targets" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
+  <Import Project="..\..\build\NullableEnable.props" />
 </Project>

+ 1 - 1
src/Avalonia.MicroCom/CallbackBase.cs

@@ -38,7 +38,7 @@ namespace Avalonia.MicroCom
             }
         }
 
-        public MicroComShadow Shadow { get; set; }
+        public MicroComShadow? Shadow { get; set; }
         public void OnReferencedFromNative()
         {
             lock (_lock) 

+ 1 - 0
src/Avalonia.Native/Avalonia.Native.csproj

@@ -29,4 +29,5 @@
   </ItemGroup>
 
   <Import Project="..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 1 - 0
src/Avalonia.OpenGL/Avalonia.OpenGL.csproj

@@ -12,4 +12,5 @@
 
     <Import Project="..\..\build\DevAnalyzers.props" />
     <Import Project="..\..\build\SourceGenerators.props" />
+    <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 1 - 0
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@@ -11,4 +11,5 @@
   <Import Project="..\..\build\ReactiveUI.props" />
   <Import Project="..\..\build\ApiDiff.props" />
   <Import Project="..\..\build\NullableEnable.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 2 - 0
src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj

@@ -8,6 +8,8 @@
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="..\Avalonia.Base\Input\Key.cs" />
+    <Compile Include="..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Visible="False" />
   </ItemGroup>
   <Import Project="..\..\build\ApiDiff.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 2 - 0
src/Avalonia.Remote.Protocol/BsonStreamTransport.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
@@ -6,6 +7,7 @@ using Metsys.Bson;
 
 namespace Avalonia.Remote.Protocol
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     class BsonStreamTransportConnection : IAvaloniaRemoteTransportConnection
     {
         private readonly IMessageTypeResolver _resolver;

+ 3 - 1
src/Avalonia.Remote.Protocol/BsonTcpTransport.cs

@@ -1,9 +1,11 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Reflection;
 
 namespace Avalonia.Remote.Protocol
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     public class BsonTcpTransport : TcpTransportBase
     {
         public BsonTcpTransport(IMessageTypeResolver resolver) : base(resolver)
@@ -24,4 +26,4 @@ namespace Avalonia.Remote.Protocol
             return wrap;
         }
     }
-}
+}

+ 4 - 0
src/Avalonia.Remote.Protocol/DefaultMessageTypeResolver.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 
@@ -9,6 +10,9 @@ namespace Avalonia.Remote.Protocol
     {
         private readonly Dictionary<Guid, Type> _guidsToTypes = new Dictionary<Guid, Type>();
         private readonly Dictionary<Type, Guid> _typesToGuids = new Dictionary<Type, Guid>();
+
+        [UnconditionalSuppressMessage("Trimming", "IL2026",
+            Justification = "If type was trimmed, we don't need to resolve it in the remove protocol")]
         public DefaultMessageTypeResolver(params Assembly[] assemblies)
         {
             foreach (var asm in

+ 9 - 2
src/Avalonia.Remote.Protocol/MetsysBson.cs

@@ -32,6 +32,7 @@ using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
 using System.Linq.Expressions;
@@ -71,7 +72,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
-
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class Serializer
     {
         private static readonly IDictionary<Type, Types> _typeMap = new Dictionary<Type, Types>
@@ -687,6 +688,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class TypeHelper
     {
         private static readonly IDictionary<Type, TypeHelper> _cachedTypeLookup = new Dictionary<Type, TypeHelper>();
@@ -787,6 +789,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class ListWrapper : BaseWrapper
     {
         private IList _list;
@@ -821,6 +824,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal static class ListHelper
     {
         public static Type GetListItemType(Type enumerableType)
@@ -865,6 +869,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class CollectionWrapper<T> : BaseWrapper
     {
         private ICollection<T> _list;
@@ -892,6 +897,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal abstract class BaseWrapper
     {
         public static BaseWrapper Create(Type type, Type itemType, object existingContainer)
@@ -948,7 +954,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
-
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class ArrayWrapper<T> : BaseWrapper
     {
         private readonly List<T> _list = new List<T>();
@@ -1000,6 +1006,7 @@ namespace Metsys.Bson
 
 namespace Metsys.Bson
 {
+    [RequiresUnreferencedCode("Bson uses reflection")]
     internal class Deserializer
     {
         internal class Options

+ 3 - 0
src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj

@@ -1,6 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
+    <!-- NativeMenuBar uses ReflectionBinding -->
+    <NoWarn>$(NoWarn);IL2026</NoWarn>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
@@ -14,4 +16,5 @@
   <Import Project="..\..\build\BuildTargets.targets" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ApiDiff.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 3 - 0
src/Avalonia.Themes.Simple/Avalonia.Themes.Simple.csproj

@@ -1,6 +1,8 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
+    <!-- NativeMenuBar uses ReflectionBinding -->
+    <NoWarn>$(NoWarn);IL2026</NoWarn>
   </PropertyGroup>
   <ItemGroup>
     <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
@@ -13,4 +15,5 @@
   <Import Project="..\..\build\BuildTargets.targets" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ApiDiff.props" />
+  <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 1 - 0
src/Avalonia.X11/Avalonia.X11.csproj

@@ -12,4 +12,5 @@
         <Compile Include="..\Shared\RawEventGrouping.cs" />
     </ItemGroup>
     <Import Project="..\..\build\SourceGenerators.props" />
+    <Import Project="..\..\build\TrimmingEnable.props" />
 </Project>

+ 3 - 1
src/Avalonia.X11/X11Structs.cs

@@ -34,6 +34,7 @@ using System.Diagnostics;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+using System.Diagnostics.CodeAnalysis;
 // ReSharper disable FieldCanBeMadeReadOnly.Global
 // ReSharper disable IdentifierTypo
 // ReSharper disable MemberCanBePrivate.Global
@@ -654,7 +655,8 @@ namespace Avalonia.X11 {
 					return type.ToString ();
 			}
 		}
-		
+
+        [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = TrimmingMessages.IgnoreNativeAotSupressWarningMessage)]
 		public static string ToString (object ev)
 		{
 			string result = string.Empty;

+ 1 - 0
src/Browser/Avalonia.Browser.Blazor/Avalonia.Browser.Blazor.csproj

@@ -11,6 +11,7 @@
   </ItemGroup>
 
   <Import Project="..\..\..\build\NullableEnable.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="7.0.0-*" />

+ 1 - 0
src/Browser/Avalonia.Browser/Avalonia.Browser.csproj

@@ -15,6 +15,7 @@
   <Import Project="..\..\..\build\SkiaSharp.props" />
   <Import Project="..\..\..\build\HarfBuzzSharp.props" />
   <Import Project="..\..\..\build\NullableEnable.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup>
     <ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />

+ 2 - 1
src/Linux/Avalonia.LinuxFramebuffer/Avalonia.LinuxFramebuffer.csproj

@@ -8,5 +8,6 @@
     <ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
     <ProjectReference Include="..\..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
     <Compile Include="..\..\Shared\RawEventGrouping.cs" />
-  </ItemGroup>  
+  </ItemGroup>
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 </Project>

+ 2 - 1
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
@@ -13,6 +13,7 @@
   <Import Project="IncludeXamlIlSre.props" />
   <ItemGroup>
     <Compile Include="..\..\Avalonia.Base\Utilities\StringBuilderCache.cs" Link="Utilities\StringBuilderCache.cs" />
+    <Compile Include="..\..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="System.Reflection.Emit" Version="4.3.0" />

+ 2 - 6
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@@ -6,10 +6,9 @@
     <DefineConstants Condition="$(UseCecil) == true">$(DefineConstants);RUNTIME_XAML_CECIL</DefineConstants>
     <EnableDefaultCompileItems>False</EnableDefaultCompileItems>
     <EnableDefaultItems>false</EnableDefaultItems>
-    <NoWarn>CS1591</NoWarn>
+    <NoWarn>$(NoWarn);CS1591</NoWarn>
   </PropertyGroup>
     <ItemGroup>
-        <Compile Include="..\..\Shared\StringCompatibilityExtensions.cs" Link="Compatibility\StringCompatibilityExtensions.cs" />
         <Compile Include="AvaloniaXamlLoader.cs" />
         <Compile Include="Converters\AvaloniaUriTypeConverter.cs" />
         <Compile Include="Converters\ColorToBrushConverter.cs" />
@@ -69,12 +68,9 @@
   <Import Project="..\..\..\build\Rx.props" />
   <Import Project="..\..\..\build\ApiDiff.props" />
   <Import Project="..\..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup Label="InternalsVisibleTo">
     <InternalsVisibleTo Include="Avalonia.Markup.Xaml.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
   </ItemGroup>
-
-  <ItemGroup>
-    <Folder Include="Compatibility\" />
-  </ItemGroup>
 </Project>

+ 4 - 1
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using Avalonia.Platform;
 #nullable enable
@@ -43,11 +44,12 @@ namespace Avalonia.Markup.Xaml
         /// A base URI to use if <paramref name="uri"/> is relative.
         /// </param>
         /// <returns>The loaded object.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.AvaloniaXamlLoaderRequiresUnreferenceCodeMessage)]
         public static object Load(Uri uri, Uri? baseUri = null)
         {
             return Load(null, uri, baseUri);
         }
-        
+
         /// <summary>
         /// Loads XAML from a URI.
         /// </summary>
@@ -57,6 +59,7 @@ namespace Avalonia.Markup.Xaml
         /// A base URI to use if <paramref name="uri"/> is relative.
         /// </param>
         /// <returns>The loaded object.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.AvaloniaXamlLoaderRequiresUnreferenceCodeMessage)]
         public static object Load(IServiceProvider? sp, Uri uri, Uri? baseUri = null)
         {
             if (uri is null)

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using Avalonia.Controls;
 using Avalonia.Logging;
@@ -10,6 +11,7 @@ using Avalonia.Utilities;
 
 namespace Avalonia.Markup.Xaml.Converters
 {
+    [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
     public class AvaloniaPropertyTypeConverter : TypeConverter
     {
         public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
@@ -48,6 +50,7 @@ namespace Avalonia.Markup.Xaml.Converters
             return property;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
         private static Type TryResolveOwnerByName(ITypeDescriptorContext context, string ns, string owner)
         {
             if (owner != null)

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/Extensions.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml.XamlIl.Runtime;
@@ -28,6 +29,7 @@ namespace Avalonia.Markup.Xaml
 
         public static bool IsInControlTemplate(this IServiceProvider sp) => sp.GetService<IAvaloniaXamlIlControlTemplateProvider>() != null;
 
+        [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
         public static Type ResolveType(this IServiceProvider ctx, string namespacePrefix, string type)
         {
             var tr = ctx.GetService<IXamlTypeResolver>();

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/ArrayElementPlugin.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Text;
 using Avalonia.Data;
 using Avalonia.Data.Core.Plugins;
@@ -17,11 +18,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             _elementType = elementType;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName)
         {
             throw new InvalidOperationException("The ArrayElementPlugin does not support dynamic matching");
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object> reference, string propertyName)
         {
             if (reference.TryGetTarget(out var target) && target is Array arr)

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CommandAccessorPlugin.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Text;
 using System.Windows.Input;
@@ -23,11 +24,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             _dependsOnProperties = dependsOnProperties;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName)
         {
             throw new InvalidOperationException("The CommandAccessorPlugin does not support dynamic matching");
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object> reference, string propertyName)
         {
             return new CommandAccessor(reference, _execute, _canExecute, _dependsOnProperties);

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using Avalonia.Controls;
@@ -22,6 +23,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             RawSource = rawSource;
         }
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.CompiledBindingSafeSupressWarningMessage)]
         public ExpressionNode BuildExpression(bool enableValidation)
         {
             ExpressionNode pathRoot = null;

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/MethodAccessorPlugin.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Text;
 using Avalonia.Data;
@@ -21,11 +22,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             _delegateType = delegateType;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName)
         {
             throw new InvalidOperationException("The MethodAccessorPlugin does not support dynamic matching");
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object?> reference, string propertyName)
         {
             Debug.Assert(_method.Name == propertyName);

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/ObservableStreamPlugin.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive.Linq;
 using System.Text;
 using Avalonia.Data.Core.Plugins;
@@ -8,11 +9,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
 {
     class ObservableStreamPlugin<T> : IStreamPlugin
     {
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public bool Match(WeakReference<object> reference)
         {
             return reference.TryGetTarget(out var target) && target is IObservable<T>;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public IObservable<object> Start(WeakReference<object> reference)
         {
             if (!(reference.TryGetTarget(out var target) && target is IObservable<T> obs))

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/PropertyInfoAccessorPlugin.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Text;
 using Avalonia.Data;
 using Avalonia.Data.Core;
@@ -19,11 +20,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             _accessorFactory = accessorFactory;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public bool Match(object obj, string propertyName)
         {
             throw new InvalidOperationException("The PropertyInfoAccessorPlugin does not support dynamic matching");
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
         public IPropertyAccessor Start(WeakReference<object> reference, string propertyName)
         {
             Debug.Assert(_propertyInfo.Name == propertyName);

+ 3 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/TaskStreamPlugin.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive.Linq;
 using System.Reactive.Subjects;
 using System.Threading.Tasks;
@@ -9,11 +10,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
 {
     class TaskStreamPlugin<T> : IStreamPlugin
     {
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public bool Match(WeakReference<object> reference)
         {
             return reference.TryGetTarget(out var target) && target is Task<T>;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.StreamPluginRequiresUnreferencedCodeMessage)]
         public IObservable<object> Start(WeakReference<object> reference)
         {
             if(!(reference.TryGetTarget(out var target) && target is Task<T> task))

+ 5 - 6
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs

@@ -1,14 +1,13 @@
 using Avalonia.Data;
 using System;
+using Avalonia.Controls;
+using Avalonia.Data.Converters;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Markup.Xaml.MarkupExtensions
 {
-    using Avalonia.Controls;
-    using Avalonia.Data.Converters;
-    using Avalonia.Markup.Data;
-    using Avalonia.Styling;
-    using System.ComponentModel;
-
+    [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
     public class ReflectionBindingExtension
     {
         public ReflectionBindingExtension()

+ 3 - 1
src/Markup/Avalonia.Markup.Xaml/Styling/ResourceInclude.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Controls;
 
 #nullable enable
@@ -8,9 +9,10 @@ namespace Avalonia.Markup.Xaml.Styling
     /// <summary>
     /// Loads a resource dictionary from a specified URL.
     /// </summary>
+    [RequiresUnreferencedCode(TrimmingMessages.StyleResourceIncludeRequiresUnreferenceCodeMessage)]
     public class ResourceInclude : IResourceProvider
     {
-        private readonly IServiceProvider _serviceProvider;
+        private readonly IServiceProvider? _serviceProvider;
         private readonly Uri? _baseUri;
         private IResourceDictionary? _loaded;
         private bool _isLoading;

+ 3 - 1
src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs

@@ -2,6 +2,7 @@ using Avalonia.Styling;
 using System;
 using Avalonia.Controls;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 
 #nullable enable
 
@@ -10,9 +11,10 @@ namespace Avalonia.Markup.Xaml.Styling
     /// <summary>
     /// Includes a style from a URL.
     /// </summary>
+    [RequiresUnreferencedCode(TrimmingMessages.StyleResourceIncludeRequiresUnreferenceCodeMessage)]
     public class StyleInclude : IStyle, IResourceProvider
     {
-        private readonly IServiceProvider _serviceProvider;
+        private readonly IServiceProvider? _serviceProvider;
         private readonly Uri? _baseUri;
         private IStyle[]? _loaded;
         private bool _isLoading;

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using Avalonia.Controls;
 using Avalonia.Controls.Templates;
 using Avalonia.Data;
@@ -33,6 +34,7 @@ namespace Avalonia.Markup.Xaml.Templates
             }
         }
 
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "If ItemsSource is a CompiledBinding, then path members will be preserver")]
         public InstancedBinding ItemsSelector(object item)
         {
             if (ItemsSource != null)

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using Avalonia.Controls;
@@ -141,6 +142,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
                 _nsInfo = nsInfo;
             }
 
+            [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
             public Type Resolve(string qualifiedTypeName)
             {
                 var sp = qualifiedTypeName.Split(new[] {':'}, 2);

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/XamlTypes.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Markup.Xaml
 {
@@ -28,6 +29,7 @@ namespace Avalonia.Markup.Xaml
     
     public interface IXamlTypeResolver
     {
+        [RequiresUnreferencedCode(TrimmingMessages.XamlTypeResolvedRequiresUnreferenceCodeMessage)]
         Type Resolve (string qualifiedTypeName);
     }
 

+ 1 - 0
src/Markup/Avalonia.Markup/Avalonia.Markup.csproj

@@ -17,6 +17,7 @@
   <Import Project="..\..\..\build\ApiDiff.props" />
   <Import Project="..\..\..\build\NullableEnable.props" />
   <Import Project="..\..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup Label="InternalsVisibleTo">
     <InternalsVisibleTo Include="Avalonia.Markup.UnitTests, PublicKey=$(AvaloniaPublicKey)" />

+ 2 - 0
src/Markup/Avalonia.Markup/Data/Binding.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reactive;
 using System.Reactive.Linq;
@@ -15,6 +16,7 @@ namespace Avalonia.Data
     /// <summary>
     /// A XAML binding.
     /// </summary>
+    [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
     public class Binding : BindingBase
     {
         /// <summary>

+ 2 - 1
src/Markup/Avalonia.Markup/Data/BindingBase.cs

@@ -1,5 +1,6 @@
 
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reactive;
 using System.Reactive.Linq;
@@ -7,7 +8,6 @@ using Avalonia.Controls;
 using Avalonia.Data.Converters;
 using Avalonia.Data.Core;
 using Avalonia.LogicalTree;
-using Avalonia.Markup.Parsers;
 using Avalonia.Reactive;
 using Avalonia.VisualTree;
 
@@ -81,6 +81,7 @@ namespace Avalonia.Data
             bool enableDataValidation);
 
         /// <inheritdoc/>
+        [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)]
         public InstancedBinding? Initiate(
             AvaloniaObject target,
             AvaloniaProperty? targetProperty,

+ 5 - 1
src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionObserverBuilder.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics.CodeAnalysis;
 using System.Reactive;
 using Avalonia.Controls;
 using Avalonia.Data.Core;
@@ -8,6 +9,7 @@ namespace Avalonia.Markup.Parsers
 {
     public static class ExpressionObserverBuilder
     {
+        [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
         internal static (ExpressionNode Node, SourceMode Mode) Parse(string expression, bool enableValidation = false, Func<string, string, Type>? typeResolver = null,
             INameScope? nameScope = null)
         {
@@ -28,6 +30,7 @@ namespace Avalonia.Markup.Parsers
             return node;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
         public static ExpressionObserver Build(
             object root,
             string expression,
@@ -41,6 +44,7 @@ namespace Avalonia.Markup.Parsers
                 description ?? expression);
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
         public static ExpressionObserver Build(
             IObservable<object> rootObservable,
             string expression,
@@ -56,7 +60,7 @@ namespace Avalonia.Markup.Parsers
                 description ?? expression);
         }
 
-
+        [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
         public static ExpressionObserver Build(
             Func<object> rootGetter,
             string expression,

+ 2 - 0
src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs

@@ -5,6 +5,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using Avalonia.Controls;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Markup.Parsers
 {
@@ -24,6 +25,7 @@ namespace Avalonia.Markup.Parsers
             _enableValidation = enableValidation;
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
         public (ExpressionNode Node, SourceMode Mode) Parse(ref CharacterReader r)
         {
             ExpressionNode? rootNode = null;

+ 2 - 0
src/Markup/Avalonia.Markup/Markup/Parsers/Nodes/StringIndexerNode.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Reactive.Linq;
@@ -12,6 +13,7 @@ using Avalonia.Utilities;
 
 namespace Avalonia.Markup.Parsers.Nodes
 {
+    [RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
     internal class StringIndexerNode : IndexerNodeBase
     {
         public StringIndexerNode(IList<string> arguments)

+ 3 - 0
src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs

@@ -4,6 +4,7 @@ using System.Globalization;
 using Avalonia.Styling;
 using Avalonia.Utilities;
 using System.Linq;
+using System.Diagnostics.CodeAnalysis;
 
 namespace Avalonia.Markup.Parsers
 {
@@ -32,12 +33,14 @@ namespace Avalonia.Markup.Parsers
         /// </summary>
         /// <param name="s">The string.</param>
         /// <returns>The parsed selector.</returns>
+        [RequiresUnreferencedCode(TrimmingMessages.SelectorsParseRequiresUnreferencedCodeMessage)]
         public Selector? Parse(string s)
         {
             var syntax = SelectorGrammar.Parse(s);
             return Create(syntax);
         }
 
+        [RequiresUnreferencedCode(TrimmingMessages.SelectorsParseRequiresUnreferencedCodeMessage)]
         private Selector? Create(IEnumerable<SelectorGrammar.ISyntax> syntax)
         {
             var result = default(Selector);

+ 1 - 0
src/Skia/Avalonia.Skia/Avalonia.Skia.csproj

@@ -18,6 +18,7 @@
   <Import Project="..\..\..\build\SkiaSharp.props" />
   <Import Project="..\..\..\build\HarfBuzzSharp.props" />
   <Import Project="..\..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup Label="InternalsVisibleTo">
     <InternalsVisibleTo Include="Avalonia.Skia.RenderTests, PublicKey=$(AvaloniaPublicKey)" />

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@@ -19,6 +19,7 @@
   <Import Project="..\..\..\build\HarfBuzzSharp.props" />
   <Import Project="..\..\..\build\JetBrains.Annotations.props" />
   <Import Project="..\..\..\build\DevAnalyzers.props" />
+  <Import Project="..\..\..\build\TrimmingEnable.props" />
 
   <ItemGroup Label="InternalsVisibleTo">
     <InternalsVisibleTo Include="Avalonia.Direct2D1.RenderTests, PublicKey=$(AvaloniaPublicKey)" />
@@ -28,5 +29,4 @@
   <ItemGroup>
     <Folder Include="Properties\" />
   </ItemGroup>
-  
 </Project>

+ 2 - 0
src/Windows/Avalonia.Win32/Automation/AutomationNode.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Runtime.CompilerServices;
@@ -16,6 +17,7 @@ using AAP = Avalonia.Automation.Provider;
 namespace Avalonia.Win32.Automation
 {
     [ComVisible(true)]
+    [RequiresUnreferencedCode("Requires .NET COM interop")]
     internal partial class AutomationNode : MarshalByRefObject,
         IRawElementProviderSimple,
         IRawElementProviderSimple2,

Some files were not shown because too many files changed in this diff