Browse Source

Trimmable runtime xaml loader (#12937)

* Add trimming attributes to the Runtime XAML Loader project

* Create CompilerDynamicDependenciesAttribute with all known dynamic types

* Use master XamlX

* Implement CompilerDynamicDependenciesGenerator to simplify CompilerDynamicDependencies attribute

* Better formatting of generated code

* Be safe about type converters as well

* Remove unnecessary warning

* Also include FindType just in case
pull/13087/head
Max Katz 2 years ago
committed by GitHub
parent
commit
dcd1b59783
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  2. 12
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs
  3. 38
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
  4. 18
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerDynamicDependencies.cs
  5. 9
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  6. 20
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  7. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  8. 2
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  9. 1
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
  10. 3
      src/tools/Avalonia.Generators/Avalonia.Generators.csproj
  11. 77
      src/tools/DevGenerators/CompilerDynamicDependenciesGenerator.cs
  12. 3
      src/tools/DevGenerators/DevGenerators.csproj
  13. 8
      src/tools/DevGenerators/Properties/launchSettings.json

4
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<IsPackable>true</IsPackable>
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants>
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL;XAML_RUNTIME_LOADER</DefineConstants>
</PropertyGroup>
<!--Disable Net Perf. analyzer for submodule to avoid commit issue -->
<PropertyGroup>
@ -21,4 +21,6 @@
<ProjectReference Include="..\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
</ItemGroup>
<Import Project="..\..\..\build\DevAnalyzers.props" />
<Import Project="..\..\..\build\TrimmingEnable.props" />
<Import Project="..\..\..\build\SourceGenerators.props" />
</Project>

12
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaRuntimeXamlLoader.cs

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Text;
using Avalonia.Markup.Xaml.XamlIl;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
#nullable enable
namespace Avalonia.Markup.Xaml
{
@ -18,6 +21,7 @@ namespace Avalonia.Markup.Xaml
/// <param name="uri">The URI of the XAML being loaded.</param>
/// <param name="designMode">Indicates whether the XAML is being loaded in design mode.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static object Load(string xaml, Assembly? localAssembly = null, object? rootInstance = null, Uri? uri = null, bool designMode = false)
{
xaml = xaml ?? throw new ArgumentNullException(nameof(xaml));
@ -37,6 +41,7 @@ namespace Avalonia.Markup.Xaml
/// <param name="uri">The URI of the XAML being loaded.</param>
/// <param name="designMode">Indicates whether the XAML is being loaded in design mode.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static object Load(Stream stream, Assembly? localAssembly = null, object? rootInstance = null, Uri? uri = null,
bool designMode = false)
=> AvaloniaXamlIlRuntimeCompiler.Load(new RuntimeXamlLoaderDocument(uri, rootInstance, stream),
@ -48,6 +53,7 @@ namespace Avalonia.Markup.Xaml
/// <param name="document">The stream containing the XAML.</param>
/// <param name="configuration">Xaml loader configuration.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration? configuration = null)
=> AvaloniaXamlIlRuntimeCompiler.Load(document, configuration ?? new RuntimeXamlLoaderConfiguration());
@ -57,6 +63,7 @@ namespace Avalonia.Markup.Xaml
/// <param name="documents">Collection of documents.</param>
/// <param name="configuration">Xaml loader configuration.</param>
/// <returns>The loaded objects per each input document. If document was removed, the element by index is null.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static IReadOnlyList<object?> LoadGroup(IReadOnlyCollection<RuntimeXamlLoaderDocument> documents, RuntimeXamlLoaderConfiguration? configuration = null)
=> AvaloniaXamlIlRuntimeCompiler.LoadGroup(documents, configuration ?? new RuntimeXamlLoaderConfiguration());
@ -66,6 +73,7 @@ namespace Avalonia.Markup.Xaml
/// <param name="xaml">The string containing the XAML.</param>
/// <param name="localAssembly">Default assembly for clr-namespace:.</param>
/// <returns>The loaded object.</returns>
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static object Parse(string xaml, Assembly? localAssembly = null)
=> Load(xaml, localAssembly);
@ -76,8 +84,8 @@ namespace Avalonia.Markup.Xaml
/// <param name="xaml">>The string containing the XAML.</param>
/// <param name="localAssembly">>Default assembly for clr-namespace:.</param>
/// <returns>The loaded object.</returns>
public static T Parse<T>(string xaml, Assembly? localAssembly = null)
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
public static T Parse<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>(string xaml, Assembly? localAssembly = null)
=> (T)Parse(xaml, localAssembly);
}
}

38
src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
@ -11,6 +12,7 @@ using System.Runtime.InteropServices;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
using Avalonia.Markup.Xaml.XamlIl.Runtime;
using Avalonia.Platform;
using XamlX;
using XamlX.Ast;
using XamlX.Transform;
using XamlX.TypeSystem;
@ -22,9 +24,13 @@ using Mono.Cecil;
using XamlX.Ast;
using XamlX.IL.Cecil;
#endif
namespace Avalonia.Markup.Xaml.XamlIl
{
static class AvaloniaXamlIlRuntimeCompiler
#if !RUNTIME_XAML_CECIL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
#endif
internal static class AvaloniaXamlIlRuntimeCompiler
{
#if !RUNTIME_XAML_CECIL
private static SreTypeSystem _sreTypeSystem;
@ -37,6 +43,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
private static AssemblyBuilder _sreAsm;
private static bool _sreCanSave;
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
public static void DumpRuntimeCompilationResults()
{
if (_sreBuilder == null)
@ -55,7 +62,9 @@ namespace Avalonia.Markup.Xaml.XamlIl
//Ignore
}
}
[CompilerDynamicDependencies]
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
static void InitializeSre()
{
if (_sreTypeSystem == null)
@ -66,10 +75,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
var name = new AssemblyName(Guid.NewGuid().ToString("N"));
if (_sreCanSave)
{
var define = AppDomain.CurrentDomain.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "DefineDynamicAssembly"
&& m.GetParameters().Length == 3 &&
m.GetParameters()[2].ParameterType == typeof(string));
var define = GetDefineDynamicAssembly();
if (define != null)
_sreAsm = (AssemblyBuilder)define.Invoke(AppDomain.CurrentDomain, new object[]
{
@ -101,6 +107,12 @@ namespace Avalonia.Markup.Xaml.XamlIl
_ignoresAccessChecksFromAttribute = EmitIgnoresAccessCheckAttributeDefinition(_sreBuilder);
}
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = XamlX.TrimmingMessages.CanBeSafelyTrimmed)]
static MethodInfo GetDefineDynamicAssembly() => AppDomain.CurrentDomain.GetType().GetMethods()
.FirstOrDefault(m => m.Name == "DefineDynamicAssembly"
&& m.GetParameters().Length == 3 &&
m.GetParameters()[2].ParameterType == typeof(string));
static Type EmitIgnoresAccessCheckAttributeDefinition(ModuleBuilder builder)
{
var tb = builder.DefineType("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute",
@ -138,6 +150,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
return tb.CreateTypeInfo();
}
[UnconditionalSuppressMessage("Trimming", "IL2080", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
static void EmitIgnoresAccessCheckToAttribute(AssemblyName assemblyName)
{
var name = assemblyName.Name;
@ -150,7 +163,6 @@ namespace Avalonia.Markup.Xaml.XamlIl
_ignoresAccessChecksFromAttribute.GetConstructors()[0],
new object[] { name }));
}
static object LoadSre(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
{
@ -184,7 +196,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
DumpRuntimeCompilationResults();
}
}
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
static IReadOnlyList<object> LoadGroupSreCore(IReadOnlyCollection<RuntimeXamlLoaderDocument> documents, RuntimeXamlLoaderConfiguration configuration)
{
InitializeSre();
@ -264,14 +277,16 @@ namespace Avalonia.Markup.Xaml.XamlIl
.Select(t => LoadOrPopulate(t.Item1, t.Item2.RootInstance, t.Item2.ServiceProvider))
.ToArray();
}
static object LoadSreCore(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
{
return LoadGroupSreCore(new[] { document }, configuration).Single();
}
#endif
static object LoadOrPopulate(Type created, object rootInstance, IServiceProvider parentServiceProvider)
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = XamlX.TrimmingMessages.GeneratedTypes)]
static object LoadOrPopulate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type created, object rootInstance, IServiceProvider parentServiceProvider)
{
var isp = Expression.Parameter(typeof(IServiceProvider));
@ -317,7 +332,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
return rootInstance;
}
}
public static object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration)
{
#if RUNTIME_XAML_CECIL
@ -364,6 +379,7 @@ namespace Avalonia.Markup.Xaml.XamlIl
private static XamlIlXmlnsMappings _cecilXmlns;
private static bool _cecilInitialized;
[CompilerDynamicDependencies]
static void InitializeCecil()
{
if(_cecilInitialized)

18
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerDynamicDependencies.cs

@ -0,0 +1,18 @@
using System;
using System.Diagnostics.CodeAnalysis;
// WARNING: this is a partial class, second part of which is generated by CompilerDynamicDependenciesGenerator.
namespace Avalonia.Markup.Xaml.XamlIl;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
internal sealed partial class CompilerDynamicDependenciesAttribute : Attribute
{
public const DynamicallyAccessedMemberTypes XamlDynamicallyAccessedMemberTypes = DynamicallyAccessedMemberTypes.All ^
(DynamicallyAccessedMemberTypes.NonPublicConstructors
| DynamicallyAccessedMemberTypes.NonPublicEvents
| DynamicallyAccessedMemberTypes.NonPublicFields
| DynamicallyAccessedMemberTypes.NonPublicMethods
| DynamicallyAccessedMemberTypes.NonPublicProperties
| DynamicallyAccessedMemberTypes.NonPublicNestedTypes);
}

9
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.GroupTransformers;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
@ -143,6 +144,9 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
}
}
#if !XAMLX_CECIL_INTERNAL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
#endif
public XamlDocument Parse(string xaml, IXamlType overrideRootType)
{
var parsed = XDocumentXamlParser.Parse(xaml, new Dictionary<string, string>
@ -191,7 +195,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
(s, returnType, parameters) => tb.DefineDelegateSubType(s, false, returnType, parameters), baseUri,
fileSource);
}
#if !XAMLX_CECIL_INTERNAL
[RequiresUnreferencedCode(XamlX.TrimmingMessages.DynamicXamlReference)]
#endif
public void ParseAndCompile(string xaml, string baseUri, IFileSource fileSource, IXamlTypeBuilder<IXamlILEmitter> tb, IXamlType overrideRootType)
{
var parsed = Parse(xaml, overrideRootType);

20
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using Avalonia.Controls;
@ -120,21 +121,18 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
void AddType(IXamlType type, IXamlType conv)
=> _converters.Add(new KeyValuePair<IXamlType, IXamlType>(type, conv));
void Add(string type, string conv)
=> AddType(typeSystem.GetType(type), typeSystem.GetType(conv));
Add("Avalonia.Media.IImage","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter");
Add("Avalonia.Media.Imaging.Bitmap","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter");
Add("Avalonia.Media.IImageBrushSource","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter");
AddType(typeSystem.GetType("Avalonia.Media.IImage"), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.BitmapTypeConverter"));
AddType(typeSystem.GetType("Avalonia.Media.Imaging.Bitmap"), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.BitmapTypeConverter"));
AddType(typeSystem.GetType("Avalonia.Media.IImageBrushSource"), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.BitmapTypeConverter"));
var ilist = typeSystem.GetType("System.Collections.Generic.IList`1");
AddType(ilist.MakeGenericType(typeSystem.GetType("Avalonia.Point")),
typeSystem.GetType("Avalonia.Markup.Xaml.Converters.PointsListTypeConverter"));
Add("Avalonia.Controls.WindowIcon","Avalonia.Markup.Xaml.Converters.IconTypeConverter");
Add("System.Globalization.CultureInfo", "System.ComponentModel.CultureInfoConverter");
Add("System.Uri", "Avalonia.Markup.Xaml.Converters.AvaloniaUriTypeConverter");
Add("System.TimeSpan", "Avalonia.Markup.Xaml.Converters.TimeSpanTypeConverter");
Add("Avalonia.Media.FontFamily","Avalonia.Markup.Xaml.Converters.FontFamilyTypeConverter");
AddType(typeSystem.GetType("Avalonia.Controls.WindowIcon"), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.IconTypeConverter"));
AddType(typeSystem.GetType("System.Globalization.CultureInfo"), typeSystem.GetType( "System.ComponentModel.CultureInfoConverter"));
AddType(typeSystem.GetType("System.Uri"), typeSystem.GetType( "Avalonia.Markup.Xaml.Converters.AvaloniaUriTypeConverter"));
AddType(typeSystem.GetType("System.TimeSpan"), typeSystem.GetType( "Avalonia.Markup.Xaml.Converters.TimeSpanTypeConverter"));
AddType(typeSystem.GetType("Avalonia.Media.FontFamily"), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.FontFamilyTypeConverter"));
_avaloniaList = typeSystem.GetType("Avalonia.Collections.AvaloniaList`1");
_avaloniaListConverter = typeSystem.GetType("Avalonia.Collections.AvaloniaListConverter`1");
}

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.GroupTransformers;
using XamlX.Emit;
@ -203,7 +204,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
ThemeVariant = cfg.TypeSystem.GetType("Avalonia.Styling.ThemeVariant");
WindowTransparencyLevel = cfg.TypeSystem.GetType("Avalonia.Controls.WindowTransparencyLevel");
(IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
(IXamlType, IXamlConstructor) GetNumericTypeInfo([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string name, IXamlType componentType, int componentCount)
{
var type = cfg.TypeSystem.GetType(name);
var ctor = type.GetConstructor(Enumerable.Range(0, componentCount).Select(_ => componentType).ToList());

2
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@ -1 +1 @@
Subproject commit 3d57397eed3f111e1fa20446de4ef5f9310ebe71
Subproject commit c23ae3ed669532e2af8d86be18369584a803170a

1
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -18,6 +18,7 @@
<ItemGroup>
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerExtensions\**\*.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerDynamicDependencies.cs" />
<Compile Include="..\..\Avalonia.Base\Utilities\StringBuilderCache.cs" Link="Utilities\StringBuilderCache.cs" />
</ItemGroup>
<ItemGroup>

3
src/tools/Avalonia.Generators/Avalonia.Generators.csproj

@ -19,7 +19,8 @@
<Compile Link="Compiler\XamlX\filename" Include="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/**/*.cs" />
<Compile Remove="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/obj/**/*.cs" />
<Compile Remove="../../Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/src/XamlX/**/SreTypeSystem.cs" />
<Compile Include="..\..\Shared\IsExternalInit.cs" Link="IsExternalInit.cs" />
<Compile Include="..\..\Shared\IsExternalInit.cs" Link="IsExternalInit.cs" Visible="False" />
<Compile Include="..\..\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="TrimmingAttributes.cs" Visible="False" />
</ItemGroup>
<ItemGroup>

77
src/tools/DevGenerators/CompilerDynamicDependenciesGenerator.cs

@ -0,0 +1,77 @@
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace DevGenerators;
[Generator(LanguageNames.CSharp)]
public class CompilerDynamicDependenciesGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var invocationSyntaxes = context.SyntaxProvider
.CreateSyntaxProvider(
static (s, _) => s is InvocationExpressionSyntax inv && inv.Expression is MemberAccessExpressionSyntax
{
Name: { Identifier: { Text: "GetType" or "FindType" } }
} && inv.ArgumentList.Arguments.Count == 1 && inv.ArgumentList.Arguments[0].Expression is LiteralExpressionSyntax,
static (context, _) => (InvocationExpressionSyntax)context.Node!);
context.RegisterSourceOutput(invocationSyntaxes.Collect(), static (context, invocations) =>
{
var types = invocations
.Select(t => t.ArgumentList.Arguments[0].GetText().ToString())
.Distinct()
.Select(t => t
.Replace("\"", "")
.Replace("`1", "<>")
.Replace("`2", "<,>")
.Replace("`3", "<,,>")
.Replace("`4", "<,,,>"))
.OrderBy(t => t)
.ToArray();
if (types.Length == 0)
{
return;
}
var attributesBuilder = new StringBuilder();
attributesBuilder.AppendLine("""
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by CompilerDynamicDependenciesGenerator source generator.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics.CodeAnalysis;
#if XAML_RUNTIME_LOADER
namespace Avalonia.Markup.Xaml.XamlIl
{
internal sealed partial class CompilerDynamicDependenciesAttribute
{
""");
foreach (var type in types)
{
if (type is "System.Void" or "XamlX.XamlDebugHatch"
|| type.StartsWith("CompiledAvaloniaXaml"))
{
continue;
}
attributesBuilder.AppendFormat(
" [DynamicDependency(XamlDynamicallyAccessedMemberTypes, typeof({0}))]", type);
attributesBuilder.AppendLine();
}
attributesBuilder.AppendLine("""
public CompilerDynamicDependenciesAttribute() {}
}
}
#endif
""");
var str = attributesBuilder.ToString();
context.AddSource("CompilerDynamicDependenciesAttribute.generated.cs", attributesBuilder.ToString());
});
}
}

3
src/tools/DevGenerators/DevGenerators.csproj

@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<EnforceExtendedAnalyzerRules>True</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>

8
src/tools/DevGenerators/Properties/launchSettings.json

@ -0,0 +1,8 @@
{
"profiles": {
"Profile 1": {
"commandName": "DebugRoslynComponent",
"targetProject": "..\\..\\Markup\\Avalonia.Markup.Xaml.Loader\\Avalonia.Markup.Xaml.Loader.csproj"
}
}
}
Loading…
Cancel
Save