Browse Source

Drop original internal XAML resources after merge

pull/12074/head
Julien Lebosquain 3 years ago
parent
commit
4405d7970c
No known key found for this signature in database GPG Key ID: 1833CAD10ACC46FD
  1. 39
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  2. 23
      src/Markup/Avalonia.Markup.Xaml.Loader/AvaloniaXamlIlRuntimeCompiler.cs
  3. 6
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  4. 20
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlMergeResourceGroupTransformer.cs
  5. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/IXamlDocumentResource.cs
  6. 34
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs
  7. 23
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentTypeBuilderProvider.cs
  8. 8
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentUsage.cs

39
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -304,7 +304,7 @@ namespace Avalonia.Build.Tasks
|| "Internal".Equals(classModifierText, StringComparison.OrdinalIgnoreCase))
classModifierPublic = false;
else
throw new XamlParseException("Invalid value for x:ClassModifier. Expected value are: Public, NotPublic (internal).", precompileDirective);
throw new XamlParseException("Invalid value for x:ClassModifier. Expected value are: Public, NotPublic (internal).", classModifierDirective);
}
var classDirective = initialRoot.Children.OfType<XamlAstXmlDirective>()
@ -353,10 +353,16 @@ namespace Avalonia.Build.Tasks
((List<XamlDocumentResource>)parsedXamlDocuments).Add(new XamlDocumentResource(
parsed, res.Uri, res, classType,
classModifierPublic.Value,
populateBuilder,
compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
classTypeDefinition == null && classModifierPublic.Value),
buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, classModifierPublic.Value)));
() => new XamlDocumentTypeBuilderProvider(
populateBuilder,
compiler.DefinePopulateMethod(
populateBuilder,
parsed,
populateName,
classTypeDefinition == null && classModifierPublic.Value),
buildName == null ?
null :
compiler.DefineBuildMethod(builder, parsed, buildName, classModifierPublic.Value))));
}
catch (Exception e)
{
@ -387,10 +393,17 @@ namespace Avalonia.Build.Tasks
foreach (var document in parsedXamlDocuments)
{
var res = (IResource)document.FileSource!;
if (document.Usage == XamlDocumentUsage.Merged && !document.IsPublic)
{
res.Remove();
continue;
}
var parsed = document.XamlDocument;
var res = (IResource)document.FileSource;
var classType = document.ClassType;
var populateBuilder = document.TypeBuilder;
var populateBuilder = document.TypeBuilderProvider.TypeBuilder;
try
{
@ -399,8 +412,8 @@ namespace Avalonia.Build.Tasks
compiler.Compile(parsed,
contextClass,
document.PopulateMethod,
document.BuildMethod,
document.TypeBuilderProvider.PopulateMethod,
document.TypeBuilderProvider.BuildMethod,
builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name, true),
(closureName, closureBaseType) =>
populateBuilder.DefineSubType(closureBaseType, closureName, false),
@ -412,7 +425,7 @@ namespace Avalonia.Build.Tasks
if (classTypeDefinition != null)
{
var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve()
.Methods.First(m => m.Name == document.PopulateMethod.Name);
.Methods.First(m => m.Name == document.TypeBuilderProvider.PopulateMethod.Name);
var designLoaderFieldType = typeSystem
.GetType("System.Action`1")
@ -536,12 +549,12 @@ namespace Avalonia.Build.Tasks
}
if (document.IsPublic
&& (document.BuildMethod != null || classTypeDefinition != null))
&& (document.TypeBuilderProvider.BuildMethod != null || classTypeDefinition != null))
{
var compiledBuildMethod = document.BuildMethod == null ?
var compiledBuildMethod = document.TypeBuilderProvider.BuildMethod is not { } buildMethod ?
null :
typeSystem.GetTypeReference(builder).Resolve()
.Methods.First(m => m.Name == document.BuildMethod?.Name);
.Methods.First(m => m.Name == buildMethod.Name);
var parameterlessConstructor = compiledBuildMethod != null ?
null :
classTypeDefinition.GetConstructors().FirstOrDefault(c =>

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

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
@ -231,10 +232,19 @@ namespace Avalonia.Markup.Xaml.XamlIl
?? ((IXamlAstValueNode)parsed.Root).Type.GetClrType().Name;
var tb = _sreBuilder.DefineType("Builder_" + Guid.NewGuid().ToString("N") + "_" + xamlName);
var builder = _sreTypeSystem.CreateTypeBuilder(tb);
parsedDocuments.Add(new XamlDocumentResource(parsed, document.BaseUri?.ToString(),
null, null, true, builder,
compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true),
document.RootInstance is null ? compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) : null));
parsedDocuments.Add(new XamlDocumentResource(
parsed,
document.BaseUri?.ToString(),
null,
null,
true,
() => new XamlDocumentTypeBuilderProvider(
builder,
compiler.DefinePopulateMethod(builder, parsed, AvaloniaXamlIlCompiler.PopulateName, true),
document.RootInstance is null ?
compiler.DefineBuildMethod(builder, parsed, AvaloniaXamlIlCompiler.BuildName, true) :
null)));
originalDocuments.Add(document);
}
@ -242,9 +252,8 @@ namespace Avalonia.Markup.Xaml.XamlIl
var createdTypes = parsedDocuments.Select(document =>
{
compiler.Compile(document.XamlDocument, document.TypeBuilder, document.PopulateMethod,
document.BuildMethod, document.Uri, document.FileSource);
return _sreTypeSystem.GetType(document.TypeBuilder.CreateType());
compiler.Compile(document.XamlDocument, document.TypeBuilderProvider, document.Uri, document.FileSource);
return _sreTypeSystem.GetType(document.TypeBuilderProvider.TypeBuilder.CreateType());
}).ToArray();
clrPropertyBuilder.CreateTypeInfo();

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

@ -179,9 +179,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return parsed;
}
public void Compile(XamlDocument document, IXamlTypeBuilder<IXamlILEmitter> tb, IXamlMethodBuilder<IXamlILEmitter> populateMethod, IXamlMethodBuilder<IXamlILEmitter> buildMethod, string baseUri, IFileSource fileSource)
public void Compile(XamlDocument document, XamlDocumentTypeBuilderProvider typeBuilderProvider, string baseUri, IFileSource fileSource)
{
Compile(document, _contextType, populateMethod, buildMethod,
var tb = typeBuilderProvider.TypeBuilder;
Compile(document, _contextType, typeBuilderProvider.PopulateMethod, typeBuilderProvider.BuildMethod,
_configuration.TypeMappings.XmlNamespaceInfoProvider == null ?
null :
tb.DefineSubType(_configuration.WellKnownTypes.Object,

20
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlMergeResourceGroupTransformer.cs

@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
using XamlX.Ast;
using XamlX.IL.Emitters;
using XamlX.Transform.Transformers;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.GroupTransformers;
@ -24,7 +22,6 @@ internal class XamlMergeResourceGroupTransformer : IXamlAstGroupTransformer
var mergeResourceIncludeType = context.GetAvaloniaTypes().MergeResourceInclude;
var mergeSourceNodes = new List<XamlPropertyAssignmentNode>();
var mergedResourceWasAdded = false;
foreach (var manipulationNode in resourceDictionaryManipulation.Children.ToArray())
{
void ProcessXamlPropertyAssignmentNode(XamlManipulationGroupNode parent, XamlPropertyAssignmentNode assignmentNode)
@ -39,7 +36,6 @@ internal class XamlMergeResourceGroupTransformer : IXamlAstGroupTransformer
{
parent.Children.Remove(assignmentNode);
mergeSourceNodes.Add(sourceAssignmentNode);
mergedResourceWasAdded = true;
}
else
{
@ -85,25 +81,29 @@ internal class XamlMergeResourceGroupTransformer : IXamlAstGroupTransformer
return context.ParseError(
$"Node MergeResourceInclude is unable to resolve \"{originalAssetPath}\" path.", propertyNode, node);
}
var targetDocument = context.Documents.FirstOrDefault(d =>
string.Equals(d.Uri, originalAssetPath, StringComparison.InvariantCultureIgnoreCase))
?.XamlDocument.Root as XamlValueWithManipulationNode;
if (targetDocument is null)
string.Equals(d.Uri, originalAssetPath, StringComparison.InvariantCultureIgnoreCase));
if (targetDocument?.XamlDocument.Root is not XamlValueWithManipulationNode targetDocumentRoot)
{
return context.ParseError(
$"Node MergeResourceInclude is unable to resolve \"{originalAssetPath}\" path.", propertyNode, node);
}
var singleRootObject = ((XamlManipulationGroupNode)targetDocument.Manipulation)
var singleRootObject = ((XamlManipulationGroupNode)targetDocumentRoot.Manipulation)
.Children.OfType<XamlObjectInitializationNode>().Single();
if (singleRootObject.Type != resourceDictionaryType)
{
return context.ParseError(
$"MergeResourceInclude can only include another ResourceDictionary", propertyNode, node);
"MergeResourceInclude can only include another ResourceDictionary", propertyNode, node);
}
manipulationGroup.Add(singleRootObject.Manipulation);
if (targetDocument.Usage == XamlDocumentUsage.Unknown)
{
targetDocument.Usage = XamlDocumentUsage.Merged;
}
}
// Order of resources is defined by ResourceDictionary.TryGetResource.

4
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/IXamlDocumentResource.cs

@ -1,5 +1,4 @@
using System;
using XamlX.Ast;
using XamlX.Ast;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
@ -14,4 +13,5 @@ internal interface IXamlDocumentResource
IXamlMethod PopulateMethod { get; }
IFileSource? FileSource { get; }
XamlDocument XamlDocument { get; }
XamlDocumentUsage Usage { get; set; }
}

34
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentResource.cs

@ -1,6 +1,5 @@
using System;
using XamlX.Ast;
using XamlX.IL;
using XamlX.TypeSystem;
#nullable enable
@ -8,24 +7,23 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
internal class XamlDocumentResource : IXamlDocumentResource
{
private readonly Func<XamlDocumentTypeBuilderProvider> _createTypeBuilderProvider;
private XamlDocumentTypeBuilderProvider? _typeBuilderProvider;
public XamlDocumentResource(
XamlDocument xamlDocument,
string? uri,
IFileSource? fileSource,
IXamlType? classType,
bool isPublic,
IXamlTypeBuilder<IXamlILEmitter> typeBuilder,
IXamlMethodBuilder<IXamlILEmitter> populateMethod,
IXamlMethodBuilder<IXamlILEmitter>? buildMethod)
Func<XamlDocumentTypeBuilderProvider> createTypeBuilderProvider)
{
_createTypeBuilderProvider = createTypeBuilderProvider;
XamlDocument = xamlDocument;
Uri = uri;
FileSource = fileSource;
ClassType = classType;
IsPublic = isPublic;
TypeBuilder = typeBuilder;
PopulateMethod = populateMethod;
BuildMethod = buildMethod;
}
public XamlDocument XamlDocument { get; }
@ -34,10 +32,22 @@ internal class XamlDocumentResource : IXamlDocumentResource
public IXamlType? ClassType { get; }
public bool IsPublic { get; }
public IXamlTypeBuilder<IXamlILEmitter> TypeBuilder { get; }
public IXamlMethodBuilder<IXamlILEmitter> PopulateMethod { get; }
public IXamlMethodBuilder<IXamlILEmitter>? BuildMethod { get; }
public XamlDocumentUsage Usage { get; set; }
public XamlDocumentTypeBuilderProvider TypeBuilderProvider
{
get
{
if (_typeBuilderProvider is null)
{
_typeBuilderProvider = _createTypeBuilderProvider();
Usage = XamlDocumentUsage.Used;
}
return _typeBuilderProvider;
}
}
IXamlMethod? IXamlDocumentResource.BuildMethod => BuildMethod;
IXamlMethod IXamlDocumentResource.PopulateMethod => PopulateMethod;
IXamlMethod? IXamlDocumentResource.BuildMethod => TypeBuilderProvider.BuildMethod;
IXamlMethod IXamlDocumentResource.PopulateMethod => TypeBuilderProvider.PopulateMethod;
}

23
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentTypeBuilderProvider.cs

@ -0,0 +1,23 @@
#nullable enable
using XamlX.IL;
using XamlX.TypeSystem;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
internal sealed class XamlDocumentTypeBuilderProvider
{
public XamlDocumentTypeBuilderProvider(
IXamlTypeBuilder<IXamlILEmitter> typeBuilder,
IXamlMethodBuilder<IXamlILEmitter> populateMethod,
IXamlMethodBuilder<IXamlILEmitter>? buildMethod)
{
TypeBuilder = typeBuilder;
PopulateMethod = populateMethod;
BuildMethod = buildMethod;
}
public IXamlTypeBuilder<IXamlILEmitter> TypeBuilder { get; }
public IXamlMethodBuilder<IXamlILEmitter> PopulateMethod { get; }
public IXamlMethodBuilder<IXamlILEmitter>? BuildMethod { get; }
}

8
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlDocumentUsage.cs

@ -0,0 +1,8 @@
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions;
internal enum XamlDocumentUsage
{
Unknown,
Merged,
Used
}
Loading…
Cancel
Save