From 73a06de15c0b79aa9441e44b3f8bf1ec80920f1a Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 20 Dec 2022 11:10:03 -0600 Subject: [PATCH] [xamlc] remove `LoadInSeparateAppDomain` and `static` state (#11982) Fixes: https://github.com/dotnet/maui/issues/11885 Looking at the JITStats report in PerfView (for MSBuild.exe): | Name | JitTime (ms) | | --- | --: | | Microsoft.Maui.Controls.Build.Tasks.dll | 214.0 | | Mono.Cecil | 119.0 | It appears that `Microsoft.Maui.Controls.Build.Tasks.dll` spends a lot of time in the JIT. What is confusing, is this was an incremental build where everything should already be loaded. The JIT's work should be done already? I don't see the same behavior for Android MSBuild tasks or Windows App SDK tasks. The cause appears to be usage of `[LoadInSeparateAppDomain]` in .NET MAUI. However, we can't just *remove this* as there would be complications... `[LoadInSeparateAppDomain]` also conveniently resets all `static` state when `` runs again. Meaning that future incremental builds would potentially use old (garbage) values. There are several places that cache Mono.Cecil objects for performance reasons. Really weird bugs would result if we didn't address this. To make things correct *and* remove `[LoadInSeparateAppDomain]`: * Move all `static` state to a `XamlCache` class as instance values. * Each `ILContext` has an instance of `XamlCache`. * Any child `ILContext`'s such as with `DataTemplate` are passed the parent's `XamlCache`. * Various `static` extension methods now require a `XamlCache` to be passed in. This allows unit tests to do this as well. * Other `*Visitor` or `*Converter` types have an instance of `ILContext`, so they can access `ILContext.Cache` as needed. Unfortunately, I had to make small changes to lots of lines for this. Testing these changes inside Visual Studio with a `dotnet new maui` project template: Before: XamlCTask = 743 ms XamlCTask = 706 ms XamlCTask = 692 ms After: XamlCTask = 128 ms XamlCTask = 134 ms XamlCTask = 117 ms This saves about ~587ms on incremental builds on all platforms, an 82% improvement. This will help even more on large solutions with multiple .NET MAUI projects, where `` runs multiple times. --- .../BindablePropertyReferenceExtensions.cs | 24 +- .../BindablePropertyConverter.cs | 12 +- .../CompiledConverters/BoundsTypeConverter.cs | 6 +- .../CompiledConverters/BrushTypeConverter.cs | 5 +- .../CompiledConverters/ColorTypeConverter.cs | 6 +- ...ColumnDefinitionCollectionTypeConverter.cs | 6 +- .../ConstraintTypeConverter.cs | 2 +- .../CornerRadiusTypeConverter.cs | 8 +- .../CompiledConverters/EasingTypeConverter.cs | 2 +- .../FlexBasisTypeConverter.cs | 6 +- .../FontSizeTypeConverter.cs | 5 +- .../GridLengthTypeConverter.cs | 14 +- .../ImageSourceTypeConverter.cs | 6 +- .../LayoutOptionsConverter.cs | 2 +- .../ListStringTypeConverter.cs | 4 +- .../CompiledConverters/PointTypeConverter.cs | 6 +- .../RDSourceTypeConverter.cs | 21 +- .../RectangleTypeConverter.cs | 6 +- .../RowDefinitionCollectionTypeConverter.cs | 4 +- .../StrokeShapeTypeConverter.cs | 54 ++-- .../ThicknessTypeConverter.cs | 10 +- .../CompiledConverters/TypeTypeConverter.cs | 4 +- .../CompiledConverters/UriTypeConverter.cs | 2 +- .../ArrayExtension.cs | 4 +- .../DataTemplateExtension.cs | 8 +- .../StaticExtension.cs | 16 +- .../CompiledMarkupExtensions/TypeExtension.cs | 6 +- .../SetterValueProvider.cs | 10 +- .../StyleSheetProvider.cs | 14 +- .../src/Build.Tasks/CreateObjectVisitor.cs | 42 +-- .../src/Build.Tasks/DebugXamlCTask.cs | 4 +- .../src/Build.Tasks/ExpandMarkupsVisitor.cs | 2 +- src/Controls/src/Build.Tasks/ILContext.cs | 5 +- .../Build.Tasks/MethodDefinitionExtensions.cs | 2 +- .../Build.Tasks/ModuleDefinitionExtensions.cs | 204 +++++-------- .../src/Build.Tasks/NodeILExtensions.cs | 133 ++++----- .../src/Build.Tasks/SetFieldVisitor.cs | 2 +- .../SetNamescopesAndRegisterNamesVisitor.cs | 43 +-- .../src/Build.Tasks/SetPropertiesVisitor.cs | 279 +++++++++--------- .../src/Build.Tasks/SetResourcesVisitor.cs | 2 +- .../Build.Tasks/TypeDefinitionExtensions.cs | 16 +- .../Build.Tasks/TypeReferenceExtensions.cs | 96 +++--- .../VariableDefinitionExtensions.cs | 6 +- src/Controls/src/Build.Tasks/XamlCTask.cs | 15 +- src/Controls/src/Build.Tasks/XamlCache.cs | 76 +++++ src/Controls/src/Build.Tasks/XamlTask.cs | 9 +- .../src/Build.Tasks/XmlTypeExtensions.cs | 30 +- .../Xaml.UnitTests/CecilExtensionsTests.cs | 4 +- .../tests/Xaml.UnitTests/LoaderTests.cs | 2 +- .../XamlC/FieldReferenceExtensionsTests.cs | 9 +- .../XamlC/MethodDefinitionExtensionsTests.cs | 9 +- .../XamlC/MethodReferenceExtensionsTests.cs | 8 +- .../XamlC/ModuleDefinitionExtensionsTests.cs | 11 +- .../XamlC/TypeReferenceExtensionsTests.cs | 4 +- 54 files changed, 651 insertions(+), 635 deletions(-) create mode 100644 src/Controls/src/Build.Tasks/XamlCache.cs diff --git a/src/Controls/src/Build.Tasks/BindablePropertyReferenceExtensions.cs b/src/Controls/src/Build.Tasks/BindablePropertyReferenceExtensions.cs index 6323e820281e..f9bfbd6c002d 100644 --- a/src/Controls/src/Build.Tasks/BindablePropertyReferenceExtensions.cs +++ b/src/Controls/src/Build.Tasks/BindablePropertyReferenceExtensions.cs @@ -9,48 +9,48 @@ namespace Microsoft.Maui.Controls.Build.Tasks { static class BindablePropertyReferenceExtensions { - public static TypeReference GetBindablePropertyType(this FieldReference bpRef, IXmlLineInfo iXmlLineInfo, ModuleDefinition module) + public static TypeReference GetBindablePropertyType(this FieldReference bpRef, XamlCache cache, IXmlLineInfo iXmlLineInfo, ModuleDefinition module) { if (!bpRef.Name.EndsWith("Property", StringComparison.InvariantCulture)) throw new BuildException(BuildExceptionCode.BPName, iXmlLineInfo, null, bpRef.Name); var bpName = bpRef.Name.Substring(0, bpRef.Name.Length - 8); var owner = bpRef.DeclaringType; - var getter = owner.GetProperty(pd => pd.Name == bpName, out TypeReference declaringTypeRef)?.GetMethod; + var getter = owner.GetProperty(cache, pd => pd.Name == bpName, out TypeReference declaringTypeRef)?.GetMethod; if (getter == null || getter.IsStatic || !getter.IsPublic) getter = null; - getter = getter ?? owner.GetMethods(md => md.Name == $"Get{bpName}" && + getter = getter ?? owner.GetMethods(cache, md => md.Name == $"Get{bpName}" && md.IsStatic && md.IsPublic && md.Parameters.Count == 1 && - md.Parameters[0].ParameterType.InheritsFromOrImplements(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"))), module).FirstOrDefault()?.Item1; + md.Parameters[0].ParameterType.InheritsFromOrImplements(cache, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"))), module).FirstOrDefault()?.Item1; if (getter == null) throw new BuildException(BuildExceptionCode.BPName, iXmlLineInfo, null, bpName, bpRef.DeclaringType); return getter.ResolveGenericReturnType(declaringTypeRef, module); } - public static TypeReference GetBindablePropertyTypeConverter(this FieldReference bpRef, ModuleDefinition module) + public static TypeReference GetBindablePropertyTypeConverter(this FieldReference bpRef, XamlCache cache, ModuleDefinition module) { var owner = bpRef.DeclaringType; var bpName = bpRef.Name.EndsWith("Property", StringComparison.Ordinal) ? bpRef.Name.Substring(0, bpRef.Name.Length - 8) : bpRef.Name; - var property = owner.GetProperty(pd => pd.Name == bpName, out TypeReference propertyDeclaringType); + var property = owner.GetProperty(cache, pd => pd.Name == bpName, out TypeReference propertyDeclaringType); var propertyType = property?.PropertyType?.ResolveGenericParameters(propertyDeclaringType); - var staticGetter = owner.GetMethods(md => md.Name == $"Get{bpName}" && + var staticGetter = owner.GetMethods(cache, md => md.Name == $"Get{bpName}" && md.IsStatic && md.IsPublic && md.Parameters.Count == 1 && - md.Parameters[0].ParameterType.InheritsFromOrImplements(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"))), module).FirstOrDefault()?.Item1; + md.Parameters[0].ParameterType.InheritsFromOrImplements(cache, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"))), module).FirstOrDefault()?.Item1; var attributes = new List(); if (property != null && property.HasCustomAttributes) attributes.AddRange(property.CustomAttributes); - if (propertyType != null && propertyType.ResolveCached().HasCustomAttributes) - attributes.AddRange(propertyType.ResolveCached().CustomAttributes); + if (propertyType != null && propertyType.ResolveCached(cache).HasCustomAttributes) + attributes.AddRange(propertyType.ResolveCached(cache).CustomAttributes); if (staticGetter != null && staticGetter.HasCustomAttributes) attributes.AddRange(staticGetter.CustomAttributes); - if (staticGetter != null && staticGetter.ReturnType.ResolveGenericParameters(bpRef.DeclaringType).ResolveCached().HasCustomAttributes) - attributes.AddRange(staticGetter.ReturnType.ResolveGenericParameters(bpRef.DeclaringType).ResolveCached().CustomAttributes); + if (staticGetter != null && staticGetter.ReturnType.ResolveGenericParameters(bpRef.DeclaringType).ResolveCached(cache).HasCustomAttributes) + attributes.AddRange(staticGetter.ReturnType.ResolveGenericParameters(bpRef.DeclaringType).ResolveCached(cache).CustomAttributes); if (attributes.FirstOrDefault(cad => cad.AttributeType.FullName == "System.ComponentModel.TypeConverterAttribute")?.ConstructorArguments[0].Value is TypeReference typeConverter) return typeConverter; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/BindablePropertyConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/BindablePropertyConverter.cs index 556289c9777f..221d114ae111 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/BindablePropertyConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/BindablePropertyConverter.cs @@ -21,11 +21,11 @@ public IEnumerable ConvertFromString(string value, ILContext contex yield return Instruction.Create(OpCodes.Ldnull); yield break; } - var bpRef = GetBindablePropertyFieldReference(value, module, node); + var bpRef = GetBindablePropertyFieldReference(value, context, module, node); yield return Instruction.Create(OpCodes.Ldsfld, bpRef); } - public FieldReference GetBindablePropertyFieldReference(string value, ModuleDefinition module, BaseNode node) + public FieldReference GetBindablePropertyFieldReference(string value, ILContext context, ModuleDefinition module, BaseNode node) { FieldReference bpRef = null; string typeName = null, propertyName = null; @@ -70,11 +70,11 @@ public FieldReference GetBindablePropertyFieldReference(string value, ModuleDefi if (typeName == null || propertyName == null) throw new BuildException(Conversion, node, null, value, typeof(BindableProperty)); - var typeRef = XmlTypeExtensions.GetTypeReference(typeName, module, node); + var typeRef = XmlTypeExtensions.GetTypeReference(context.Cache, typeName, module, node); if (typeRef == null) throw new BuildException(TypeResolution, node, null, typeName); - bpRef = GetBindablePropertyFieldReference(typeRef, propertyName, module); + bpRef = GetBindablePropertyFieldReference(context.Cache, typeRef, propertyName, module); if (bpRef == null) throw new BuildException(PropertyResolution, node, null, propertyName, typeRef.Name); return bpRef; @@ -103,10 +103,10 @@ static string FindTypeNameForVisualState(IElementNode parent, IXmlLineInfo lineI return target.XmlType.Name; } - public static FieldReference GetBindablePropertyFieldReference(TypeReference typeRef, string propertyName, ModuleDefinition module) + public static FieldReference GetBindablePropertyFieldReference(XamlCache cache, TypeReference typeRef, string propertyName, ModuleDefinition module) { TypeReference declaringTypeReference; - FieldReference bpRef = typeRef.GetField(fd => fd.Name == $"{propertyName}Property" && fd.IsStatic && fd.IsPublic, out declaringTypeReference); + FieldReference bpRef = typeRef.GetField(cache, fd => fd.Name == $"{propertyName}Property" && fd.IsStatic && fd.IsPublic, out declaringTypeReference); if (bpRef != null) { bpRef = module.ImportReference(bpRef.ResolveGenericParameters(declaringTypeReference)); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/BoundsTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/BoundsTypeConverter.cs index 646b04b9f4d7..a08f0a391132 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/BoundsTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/BoundsTypeConverter.cs @@ -53,10 +53,10 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (!hasX || !hasY || !hasW || !hasH) throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(Rect)); - return GenerateIL(x, y, w, h, module); + return GenerateIL(context, x, y, w, h, module); } - IEnumerable GenerateIL(double x, double y, double w, double h, ModuleDefinition module) + IEnumerable GenerateIL(ILContext context, double x, double y, double w, double h, ModuleDefinition module) { // IL_0000: ldc.r8 3.1000000000000001 // IL_0009: ldc.r8 4.2000000000000002 @@ -68,7 +68,7 @@ IEnumerable GenerateIL(double x, double y, double w, double h, Modu yield return Instruction.Create(OpCodes.Ldc_R8, y); yield return Instruction.Create(OpCodes.Ldc_R8, w); yield return Instruction.Create(OpCodes.Ldc_R8, h); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Rect"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Rect"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/BrushTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/BrushTypeConverter.cs index f2366e18ad97..078c367cf2f1 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/BrushTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/BrushTypeConverter.cs @@ -22,13 +22,14 @@ public IEnumerable ConvertFromString(string value, ILContext contex foreach (var instruction in colorConverter.ConvertFromString(value, context, node)) yield return instruction; - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "SolidColorBrush"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "SolidColorBrush"), parameterTypes: new[] { ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Color")})); yield break; } - var propertyGetterReference = module.ImportPropertyGetterReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Brush"), + var propertyGetterReference = module.ImportPropertyGetterReference(context.Cache, + ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Brush"), value, isStatic: true, caseSensitive: false); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ColorTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ColorTypeConverter.cs index e5431598e03c..b5179c125c37 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ColorTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ColorTypeConverter.cs @@ -29,7 +29,7 @@ public virtual IEnumerable ConvertFromString(string value, ILContex yield return Instruction.Create(OpCodes.Ldc_R4, color.Blue); yield return Instruction.Create(OpCodes.Ldc_R4, color.Alpha); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Color"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Color"), parameterTypes: new[] { ("mscorlib", "System", "Single"), ("mscorlib", "System", "Single"), ("mscorlib", "System", "Single"), @@ -49,7 +49,7 @@ public virtual IEnumerable ConvertFromString(string value, ILContex yield break; } - var fieldReference = module.ImportFieldReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Colors"), + var fieldReference = module.ImportFieldReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Colors"), color, isStatic: true, caseSensitive: false); @@ -60,7 +60,7 @@ public virtual IEnumerable ConvertFromString(string value, ILContex yield break; } - var propertyGetterReference = module.ImportPropertyGetterReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Colors"), + var propertyGetterReference = module.ImportPropertyGetterReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Colors"), color, isStatic: true, caseSensitive: false); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ColumnDefinitionCollectionTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ColumnDefinitionCollectionTypeConverter.cs index 12e399c9f3be..fbeed055f0f6 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ColumnDefinitionCollectionTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ColumnDefinitionCollectionTypeConverter.cs @@ -20,19 +20,19 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(','); yield return Create(Ldc_I4, parts.Length); - yield return Create(Newarr, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ColumnDefinition"))); + yield return Create(Newarr, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ColumnDefinition"))); for (var i = 0; i < parts.Length; i++) { yield return Create(Dup); yield return Create(Ldc_I4, i); foreach (var instruction in gridlengthconverter.ConvertFromString(parts[i], context, node)) yield return instruction; - yield return Create(Newobj, module.ImportCtorReference( + yield return Create(Newobj, module.ImportCtorReference(context.Cache, type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ColumnDefinition"), parameterTypes: new[] { ("Microsoft.Maui", "Microsoft.Maui", "GridLength") })); yield return Create(Stelem_Ref); } - yield return Create(Newobj, module.ImportCtorReference( + yield return Create(Newobj, module.ImportCtorReference(context.Cache, type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ColumnDefinitionCollection"), paramCount: 1)); yield break; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ConstraintTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ConstraintTypeConverter.cs index cc1f493e58d8..d22679ab8c80 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ConstraintTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ConstraintTypeConverter.cs @@ -20,7 +20,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(Compatibility.Constraint)); yield return Create(Ldc_R8, size); - yield return Create(Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Compatibility", "Constraint"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Compatibility", "Constraint"), methodName: "Constant", parameterTypes: new[] { ("mscorlib", "System", "Double") }, isStatic: true)); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/CornerRadiusTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/CornerRadiusTypeConverter.cs index d5c4ccfdd3f2..98287c3c94b1 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/CornerRadiusTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/CornerRadiusTypeConverter.cs @@ -22,25 +22,25 @@ public IEnumerable ConvertFromString(string value, ILContext contex { case 1: if (double.TryParse(cornerradius[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l)) - return GenerateIL(module, l); + return GenerateIL(context, module, l); break; case 4: if (double.TryParse(cornerradius[0], NumberStyles.Number, CultureInfo.InvariantCulture, out tl) && double.TryParse(cornerradius[1], NumberStyles.Number, CultureInfo.InvariantCulture, out tr) && double.TryParse(cornerradius[2], NumberStyles.Number, CultureInfo.InvariantCulture, out bl) && double.TryParse(cornerradius[3], NumberStyles.Number, CultureInfo.InvariantCulture, out br)) - return GenerateIL(module, tl, tr, bl, br); + return GenerateIL(context, module, tl, tr, bl, br); break; } } throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(CornerRadius)); } - IEnumerable GenerateIL(ModuleDefinition module, params double[] args) + IEnumerable GenerateIL(ILContext context, ModuleDefinition module, params double[] args) { foreach (var d in args) yield return Instruction.Create(OpCodes.Ldc_R8, d); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui", "CornerRadius"), parameterTypes: args.Select(a => ("mscorlib", "System", "Double")).ToArray())); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "CornerRadius"), parameterTypes: args.Select(a => ("mscorlib", "System", "Double")).ToArray())); } } diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/EasingTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/EasingTypeConverter.cs index b7e52f52edc2..3234ec2f460f 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/EasingTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/EasingTypeConverter.cs @@ -25,7 +25,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var assemblyTypeInfo = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", nameof(Easing)); var module = context.Body.Method.Module; - var fieldReference = module.ImportFieldReference(assemblyTypeInfo, value, isStatic: true, caseSensitive: false); + var fieldReference = module.ImportFieldReference(context.Cache, assemblyTypeInfo, value, isStatic: true, caseSensitive: false); if (fieldReference != null) { diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/FlexBasisTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/FlexBasisTypeConverter.cs index 8c44a8ab69de..8b8d3453cc8d 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/FlexBasisTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/FlexBasisTypeConverter.cs @@ -19,7 +19,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (value == "Auto") { yield return Instruction.Create(OpCodes.Ldsfld, - module.ImportFieldReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), + module.ImportFieldReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), "Auto", isStatic: true)); yield break; @@ -29,7 +29,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex { yield return Instruction.Create(OpCodes.Ldc_R4, (float)(relflex / 100)); yield return Instruction.Create(OpCodes.Ldc_I4_1); //isRelative: true - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] { ("mscorlib", "System", "Single"), ("mscorlib", "System", "Boolean")})); yield break; @@ -38,7 +38,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex { yield return Instruction.Create(OpCodes.Ldc_R4, flex); yield return Instruction.Create(OpCodes.Ldc_I4_0); //isRelative: false - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] { ("mscorlib", "System", "Single"), ("mscorlib", "System", "Boolean")})); yield break; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/FontSizeTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/FontSizeTypeConverter.cs index 0ea509c80f6a..b6f89e55d531 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/FontSizeTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/FontSizeTypeConverter.cs @@ -32,19 +32,22 @@ public IEnumerable ConvertFromString(string value, ILContext contex { yield return Instruction.Create(OpCodes.Ldloc, context.Variables[parent]); yield return Instruction.Create(OpCodes.Callvirt, module.ImportMethodReference( + context.Cache, module.TypeSystem.Object, methodName: "GetType")); } else { - yield return Instruction.Create(OpCodes.Ldtoken, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Label"))); + yield return Instruction.Create(OpCodes.Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Label"))); yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference( + context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); } yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference( + context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Device"), methodName: "GetNamedSize", parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "NamedSize"), ("System.Runtime", "System", "Type") }, diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/GridLengthTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/GridLengthTypeConverter.cs index d5492be3ce77..c3e903236fb8 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/GridLengthTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/GridLengthTypeConverter.cs @@ -21,28 +21,28 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (value.Equals("auto", StringComparison.OrdinalIgnoreCase)) { - yield return Create(Ldsfld, module.ImportFieldReference(("Microsoft.Maui", "Microsoft.Maui", "GridLength"), nameof(GridLength.Auto), isStatic: true)); + yield return Create(Ldsfld, module.ImportFieldReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "GridLength"), nameof(GridLength.Auto), isStatic: true)); yield break; } if (value.Equals("*", StringComparison.OrdinalIgnoreCase)) { - yield return Create(Ldsfld, module.ImportFieldReference(("Microsoft.Maui", "Microsoft.Maui", "GridLength"), nameof(GridLength.Star), isStatic: true)); + yield return Create(Ldsfld, module.ImportFieldReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "GridLength"), nameof(GridLength.Star), isStatic: true)); yield break; } if (value.EndsWith("*", StringComparison.OrdinalIgnoreCase) && double.TryParse(value.Substring(0, value.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out var length)) { yield return Create(Ldc_R8, length); yield return Create(Ldc_I4, (int)GridUnitType.Star); - yield return Create(Newobj, module.ImportCtorReference( - type: module.GetTypeDefinition(("Microsoft.Maui", "Microsoft.Maui", "GridLength")), - parameterTypes: new[] { module.TypeSystem.Double, module.GetTypeDefinition(("Microsoft.Maui", "Microsoft.Maui", "GridUnitType")) })); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, + type: module.GetTypeDefinition(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "GridLength")), + parameterTypes: new[] { module.TypeSystem.Double, module.GetTypeDefinition(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "GridUnitType")) })); yield break; } if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out length)) { yield return Create(Ldc_R8, length); - yield return Create(Newobj, module.ImportCtorReference( - type: module.GetTypeDefinition(("Microsoft.Maui", "Microsoft.Maui", "GridLength")), + yield return Create(Newobj, module.ImportCtorReference(context.Cache, + type: module.GetTypeDefinition(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "GridLength")), parameterTypes: new[] { module.TypeSystem.Double })); yield break; } diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ImageSourceTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ImageSourceTypeConverter.cs index d5cb38daac07..c024c5850c68 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ImageSourceTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ImageSourceTypeConverter.cs @@ -19,16 +19,16 @@ public IEnumerable ConvertFromString(string value, ILContext contex { yield return Instruction.Create(OpCodes.Ldstr, value); yield return Instruction.Create(OpCodes.Ldc_I4_1); // (int)UriKind.Absolute is 1 - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("System", "System", "Uri"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("System", "System", "Uri"), parameterTypes: new[] { ("mscorlib", "System", "String"), ("System", "System", "UriKind")})); - yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ImageSource"), "FromUri", parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ImageSource"), "FromUri", parameterTypes: new[] { ("System", "System", "Uri")}, isStatic: true)); } else { yield return Instruction.Create(OpCodes.Ldstr, value); - yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ImageSource"), "FromFile", parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ImageSource"), "FromFile", parameterTypes: new[] { ("mscorlib", "System", "String")}, isStatic: true)); } yield break; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/LayoutOptionsConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/LayoutOptionsConverter.cs index e076cd0665ce..ad6bbb6948e9 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/LayoutOptionsConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/LayoutOptionsConverter.cs @@ -26,7 +26,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex { var options = parts[parts.Length - 1]; - var fieldReference = module.ImportFieldReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "LayoutOptions"), + var fieldReference = module.ImportFieldReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "LayoutOptions"), fieldName: options, isStatic: true); if (fieldReference != null) diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ListStringTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ListStringTypeConverter.cs index 0fa427e1d0b0..01d8ebbacfdc 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ListStringTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ListStringTypeConverter.cs @@ -23,14 +23,14 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList(); yield return Create(Ldc_I4, parts.Count); - yield return Create(Newobj, module.ImportCtorReference(("System.Collections", "System.Collections.Generic", "List`1"), + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("System.Collections", "System.Collections.Generic", "List`1"), parameterTypes: new[] { ("mscorlib", "System", "Int32") }, classArguments: new[] { ("mscorlib", "System", "String") })); foreach (var part in parts) { yield return Create(Dup); yield return Create(Ldstr, part); - yield return Create(Callvirt, module.ImportMethodReference(("mscorlib", "System.Collections.Generic", "ICollection`1"), + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, ("mscorlib", "System.Collections.Generic", "ICollection`1"), methodName: "Add", paramCount: 1, classArguments: new[] { ("mscorlib", "System", "String") })); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/PointTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/PointTypeConverter.cs index e7fbb5c8f22b..41e0f845510c 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/PointTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/PointTypeConverter.cs @@ -14,7 +14,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var module = context.Body.Method.Module; if (!string.IsNullOrEmpty(value) && Point.TryParse(value.Trim(), out var point)) { - foreach (var instruction in CreatePoint(module, point)) + foreach (var instruction in CreatePoint(context, module, point)) { yield return instruction; } @@ -23,11 +23,11 @@ public IEnumerable ConvertFromString(string value, ILContext contex throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(Point)); } - public IEnumerable CreatePoint(ModuleDefinition module, Point point) + public IEnumerable CreatePoint(ILContext context, ModuleDefinition module, Point point) { yield return Instruction.Create(OpCodes.Ldc_R8, point.X); yield return Instruction.Create(OpCodes.Ldc_R8, point.Y); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Point"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Point"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double")})); } diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs index 34ba4aa87146..e8876ea4761c 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/RDSourceTypeConverter.cs @@ -23,7 +23,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var rdNode = node.Parent as IElementNode; - var rootTargetPath = XamlCTask.GetPathForType(currentModule, ((ILRootNode)rootNode).TypeReference); + var rootTargetPath = XamlCTask.GetPathForType(context.Cache, currentModule, ((ILRootNode)rootNode).TypeReference); var module = currentModule; string asmName = null; @@ -45,7 +45,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early - var resourceId = XamlCTask.GetResourceIdForPath(module, resourcePath); + var resourceId = XamlCTask.GetResourceIdForPath(context.Cache, module, resourcePath); if (resourceId == null) throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); @@ -53,7 +53,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex //abuse the converter, produce some side effect, but leave the stack untouched //public void SetAndLoadSource(Uri value, string resourceID, Assembly assembly, System.Xml.IXmlLineInfo lineInfo) - foreach (var instruction in context.Variables[rdNode].LoadAs(currentModule.GetTypeDefinition(resourceDictionaryType), currentModule)) + foreach (var instruction in context.Variables[rdNode].LoadAs(context.Cache, currentModule.GetTypeDefinition(context.Cache, resourceDictionaryType), currentModule)) yield return instruction; //reappend assembly= in all cases, see other RD converter if (!string.IsNullOrEmpty(asmName)) @@ -65,7 +65,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex //keep the Uri for later yield return Create(Dup); - var uriVarDef = new VariableDefinition(currentModule.ImportReference(("System", "System", "Uri"))); + var uriVarDef = new VariableDefinition(currentModule.ImportReference(context.Cache, ("System", "System", "Uri"))); body.Variables.Add(uriVarDef); yield return Create(Stloc, uriVarDef); yield return Create(Ldstr, resourcePath); //resourcePath @@ -73,28 +73,29 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (!string.IsNullOrEmpty(asmName)) { yield return Create(Ldstr, asmName); - yield return Create(Call, currentModule.ImportMethodReference(("mscorlib", "System.Reflection", "Assembly"), methodName: "Load", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true)); + yield return Create(Call, currentModule.ImportMethodReference(context.Cache, ("mscorlib", "System.Reflection", "Assembly"), methodName: "Load", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true)); } else //we could use assembly.Load in the 'else' part too, but I don't want to change working code right now { yield return Create(Ldtoken, currentModule.ImportReference(((ILRootNode)rootNode).TypeReference)); - yield return Create(Call, currentModule.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Callvirt, currentModule.ImportPropertyGetterReference(("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); + yield return Create(Call, currentModule.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Callvirt, currentModule.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); } foreach (var instruction in node.PushXmlLineInfo(context)) yield return instruction; //lineinfo - yield return Create(Callvirt, currentModule.ImportMethodReference(resourceDictionaryType, + yield return Create(Callvirt, currentModule.ImportMethodReference(context.Cache, + resourceDictionaryType, methodName: "SetAndLoadSource", parameterTypes: new[] { ("System", "System", "Uri"), ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); //ldloc the stored uri as return value yield return Create(Ldloc, uriVarDef); } - internal static string GetPathForType(ModuleDefinition module, TypeReference type) + internal static string GetPathForType(ILContext context, ModuleDefinition module, TypeReference type) { foreach (var ca in type.Module.GetCustomAttributes()) { - if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) + if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) continue; if (!TypeRefComparer.Default.Equals(ca.ConstructorArguments[2].Value as TypeReference, type)) continue; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/RectangleTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/RectangleTypeConverter.cs index 653d4875cd32..fd8d035c1f8b 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/RectangleTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/RectangleTypeConverter.cs @@ -26,10 +26,10 @@ public IEnumerable ConvertFromString(string value, ILContext contex !double.TryParse(xywh[3], NumberStyles.Number, CultureInfo.InvariantCulture, out h)) throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(Rect)); - return GenerateIL(x, y, w, h, module); + return GenerateIL(context, x, y, w, h, module); } - IEnumerable GenerateIL(double x, double y, double w, double h, ModuleDefinition module) + IEnumerable GenerateIL(ILContext context, double x, double y, double w, double h, ModuleDefinition module) { // IL_0000: ldc.r8 3.1000000000000001 // IL_0009: ldc.r8 4.2000000000000002 @@ -41,7 +41,7 @@ IEnumerable GenerateIL(double x, double y, double w, double h, Modu yield return Instruction.Create(OpCodes.Ldc_R8, y); yield return Instruction.Create(OpCodes.Ldc_R8, w); yield return Instruction.Create(OpCodes.Ldc_R8, h); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Rect"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Rect"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/RowDefinitionCollectionTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/RowDefinitionCollectionTypeConverter.cs index f213d954eeb1..167ca402bef1 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/RowDefinitionCollectionTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/RowDefinitionCollectionTypeConverter.cs @@ -20,7 +20,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(','); yield return Create(Ldc_I4, parts.Length); - yield return Create(Newarr, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "RowDefinition"))); + yield return Create(Newarr, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "RowDefinition"))); for (var i = 0; i < parts.Length; i++) { yield return Create(Dup); @@ -28,11 +28,13 @@ public IEnumerable ConvertFromString(string value, ILContext contex foreach (var instruction in gridlengthconverter.ConvertFromString(parts[i], context, node)) yield return instruction; yield return Create(Newobj, module.ImportCtorReference( + context.Cache, type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "RowDefinition"), parameterTypes: new[] { ("Microsoft.Maui", "Microsoft.Maui", "GridLength") })); yield return Create(Stelem_Ref); } yield return Create(Newobj, module.ImportCtorReference( + context.Cache, type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "RowDefinitionCollection"), paramCount: 1)); yield break; diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/StrokeShapeTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/StrokeShapeTypeConverter.cs index 803a84b3b980..a5f210bb13af 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/StrokeShapeTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/StrokeShapeTypeConverter.cs @@ -23,7 +23,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (value.StartsWith(ShapeConverter.Ellipse, StringComparison.Ordinal)) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Ellipse"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Ellipse"), parameterTypes: null)); yield break; } @@ -33,7 +33,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(ShapeConverter.Delimiter, 2); if (parts.Length != 2) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: null)); yield break; } @@ -42,7 +42,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (points == null || points.Count == 0) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: null)); yield break; } @@ -53,7 +53,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex yield return Instruction.Create(OpCodes.Ldc_R8, p1.Y); yield return Instruction.Create(OpCodes.Ldc_R8, 0d); yield return Instruction.Create(OpCodes.Ldc_R8, 0d); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), @@ -68,7 +68,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex yield return Instruction.Create(OpCodes.Ldc_R8, p2.X); yield return Instruction.Create(OpCodes.Ldc_R8, p2.Y); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Line"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), @@ -85,17 +85,17 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(ShapeConverter.Delimiter, 2); if (parts.Length != 2) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), parameterTypes: null)); yield break; } - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), parameterTypes: null)); yield return Instruction.Create(OpCodes.Dup); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "PathGeometryConverter"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "PathGeometryConverter"), parameterTypes: null)); yield return Instruction.Create(OpCodes.Ldstr, parts[1]); - yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(("System", "System.ComponentModel", "TypeConverter"), "ConvertFromInvariantString", parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Call, module.ImportMethodReference(context.Cache, ("System", "System.ComponentModel", "TypeConverter"), "ConvertFromInvariantString", parameterTypes: new[] { ("mscorlib", "System", "String")})); - yield return Instruction.Create(OpCodes.Call, module.ImportPropertySetterReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), "Data")); + yield return Instruction.Create(OpCodes.Call, module.ImportPropertySetterReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Path"), "Data")); yield break; } @@ -104,7 +104,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(ShapeConverter.Delimiter, 2); if (parts.Length != 2) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: null)); yield break; } @@ -113,16 +113,16 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (points == null || points.Count == 0) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: null)); yield break; } - foreach (var instruction in CreatePointCollection(module, points)) + foreach (var instruction in CreatePointCollection(context, module, points)) { yield return instruction; } - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polygon"), parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "PointCollection")})); yield break; } @@ -132,7 +132,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(ShapeConverter.Delimiter, 2); if (parts.Length != 2) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: null)); yield break; } @@ -141,23 +141,23 @@ public IEnumerable ConvertFromString(string value, ILContext contex if (points == null || points.Count == 0) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: null)); yield break; } - foreach (var instruction in CreatePointCollection(module, points)) + foreach (var instruction in CreatePointCollection(context, module, points)) { yield return instruction; } - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Polyline"), parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "PointCollection")})); yield break; } if (value.StartsWith(ShapeConverter.Rectangle, StringComparison.Ordinal)) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Rectangle"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "Rectangle"), parameterTypes: null)); yield break; } @@ -166,11 +166,11 @@ public IEnumerable ConvertFromString(string value, ILContext contex var parts = value.Split(ShapeConverter.Delimiter, 2); if (parts.Length != 2) { - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), parameterTypes: null)); yield break; } - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), parameterTypes: null)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), parameterTypes: null)); yield return Instruction.Create(OpCodes.Dup); var cornerRadiusTypeConverter = new Converters.CornerRadiusTypeConverter(); @@ -181,22 +181,22 @@ public IEnumerable ConvertFromString(string value, ILContext contex yield return Instruction.Create(OpCodes.Ldc_R8, cornerRadius.BottomLeft); yield return Instruction.Create(OpCodes.Ldc_R8, cornerRadius.BottomRight); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui", "CornerRadius"), parameterTypes: new[] { + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "CornerRadius"), parameterTypes: new[] { ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double"), ("mscorlib", "System", "Double")})); - yield return Instruction.Create(OpCodes.Call, module.ImportPropertySetterReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), "CornerRadius")); + yield return Instruction.Create(OpCodes.Call, module.ImportPropertySetterReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Shapes", "RoundRectangle"), "CornerRadius")); yield break; } } throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(IShape)); } - IEnumerable CreatePointCollection(ModuleDefinition module, PointCollection points) + IEnumerable CreatePointCollection(ILContext context, ModuleDefinition module, PointCollection points) { - var pointType = module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Point")); + var pointType = module.ImportReference(context.Cache, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics", "Point")); yield return Instruction.Create(OpCodes.Ldc_I4, points.Count); yield return Instruction.Create(OpCodes.Newarr, pointType); @@ -206,7 +206,7 @@ IEnumerable CreatePointCollection(ModuleDefinition module, PointCol yield return Instruction.Create(OpCodes.Dup); yield return Instruction.Create(OpCodes.Ldc_I4, i); - foreach (var instruction in pointTypeConverter.CreatePoint(module, points[i])) + foreach (var instruction in pointTypeConverter.CreatePoint(context, module, points[i])) { yield return instruction; } @@ -215,6 +215,6 @@ IEnumerable CreatePointCollection(ModuleDefinition module, PointCol yield return Instruction.Create(OpCodes.Stelem_Any, pointType); } - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "PointCollection"), paramCount: 1)); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, type: ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "PointCollection"), paramCount: 1)); } } diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs index 7d11137cdd13..4f1893aa4f5f 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs @@ -22,30 +22,30 @@ public IEnumerable ConvertFromString(string value, ILContext contex { case 1: if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l)) - return GenerateIL(module, l); + return GenerateIL(context, module, l); break; case 2: if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) && double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t)) - return GenerateIL(module, l, t); + return GenerateIL(context, module, l, t); break; case 4: if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) && double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t) && double.TryParse(thickness[2], NumberStyles.Number, CultureInfo.InvariantCulture, out r) && double.TryParse(thickness[3], NumberStyles.Number, CultureInfo.InvariantCulture, out b)) - return GenerateIL(module, l, t, r, b); + return GenerateIL(context, module, l, t, r, b); break; } } throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(Thickness)); } - IEnumerable GenerateIL(ModuleDefinition module, params double[] args) + IEnumerable GenerateIL(ILContext context, ModuleDefinition module, params double[] args) { foreach (var d in args) yield return Instruction.Create(OpCodes.Ldc_R8, d); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui", "Thickness"), parameterTypes: args.Select(a => ("mscorlib", "System", "Double")).ToArray())); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui", "Microsoft.Maui", "Thickness"), parameterTypes: args.Select(a => ("mscorlib", "System", "Double")).ToArray())); } } diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/TypeTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/TypeTypeConverter.cs index c15c6bdc73e4..60dfd95fc6be 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/TypeTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/TypeTypeConverter.cs @@ -28,12 +28,12 @@ public IEnumerable ConvertFromString(string value, ILContext contex else xmlType = new XmlType(node.NamespaceResolver.LookupNamespace(""), split[0], null); - var typeRef = xmlType.GetTypeReference(module, (IXmlLineInfo)node); + var typeRef = xmlType.GetTypeReference(context.Cache, module, (IXmlLineInfo)node); if (typeRef == null) goto error; yield return Create(Ldtoken, module.ImportReference(typeRef)); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); diff --git a/src/Controls/src/Build.Tasks/CompiledConverters/UriTypeConverter.cs b/src/Controls/src/Build.Tasks/CompiledConverters/UriTypeConverter.cs index f42da9cf898b..3a06cf141e24 100644 --- a/src/Controls/src/Build.Tasks/CompiledConverters/UriTypeConverter.cs +++ b/src/Controls/src/Build.Tasks/CompiledConverters/UriTypeConverter.cs @@ -21,7 +21,7 @@ public IEnumerable ConvertFromString(string value, ILContext contex yield return Create(Ldstr, value); yield return Create(Ldc_I4_0); //UriKind.RelativeOrAbsolute - yield return Create(Newobj, module.ImportCtorReference(("System", "System", "Uri"), parameterTypes: new[] { + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("System", "System", "Uri"), parameterTypes: new[] { ("mscorlib", "System", "String"), ("System", "System", "UriKind")})); } diff --git a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/ArrayExtension.cs b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/ArrayExtension.cs index f1591058723f..38a84d2a2b86 100644 --- a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/ArrayExtension.cs +++ b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/ArrayExtension.cs @@ -32,7 +32,7 @@ IEnumerable ProvideValue(TypeReference typeTypeRef, IReadOnlyList ProvideValue(TypeReference typeTypeRef, IReadOnlyList ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference typeRef) { - typeRef = module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "DataTemplate")); + typeRef = module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "DataTemplate")); var name = new XmlName("", "TypeName"); if (!node.Properties.TryGetValue(name, out INode typeNameNode) && node.CollectionItems.Any()) @@ -22,13 +22,13 @@ public IEnumerable ProvideValue(IElementNode node, ModuleDefinition if (!(typeNameNode is ValueNode valueNode)) throw new BuildException(BuildExceptionCode.PropertyMissing, node as IXmlLineInfo, null, "TypeName", typeof(Microsoft.Maui.Controls.Xaml.DataTemplateExtension)); - var contentTypeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(valueNode.Value as string, module, node as BaseNode)) + var contentTypeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, valueNode.Value as string, module, node as BaseNode)) ?? throw new BuildException(BuildExceptionCode.TypeResolution, node as IXmlLineInfo, null, valueNode.Value); - var dataTemplateCtor = module.ImportCtorReference(typeRef, new[] { module.ImportReference(("mscorlib", "System", "Type")) }); + var dataTemplateCtor = module.ImportCtorReference(context.Cache, typeRef, new[] { module.ImportReference(context.Cache, ("mscorlib", "System", "Type")) }); return new List { Create(Ldtoken, module.ImportReference(contentTypeRef)), - Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)), + Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)), Create(Newobj, dataTemplateCtor), }; } diff --git a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticExtension.cs b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticExtension.cs index 858cedaca345..48be68f53d0b 100644 --- a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticExtension.cs +++ b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/StaticExtension.cs @@ -24,9 +24,9 @@ public IEnumerable ProvideValue(IElementNode node, ModuleDefinition var typename = member.Substring(0, dotIdx); var membername = member.Substring(dotIdx + 1); - var typeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(typename, module, node as BaseNode)); - var fieldRef = GetFieldReference(typeRef, membername, module); - var propertyDef = GetPropertyDefinition(typeRef, membername, module); + var typeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, typename, module, node as BaseNode)); + var fieldRef = GetFieldReference(context.Cache, typeRef, membername, module); + var propertyDef = GetPropertyDefinition(context.Cache, typeRef, membername, module); if (fieldRef == null && propertyDef == null) throw new BuildException(BuildExceptionCode.XStaticResolution, node as IXmlLineInfo, null, membername, typename); @@ -61,7 +61,7 @@ public IEnumerable ProvideValue(IElementNode node, ModuleDefinition return new[] { Instruction.Create(OpCodes.Ldc_I8, (ulong)fieldDef.Constant) }; //enum values - if (memberRef.ResolveCached().IsEnum) + if (memberRef.ResolveCached(context.Cache).IsEnum) { if (fieldDef.Constant is long) return new[] { Instruction.Create(OpCodes.Ldc_I8, (long)fieldDef.Constant) }; @@ -79,9 +79,9 @@ public IEnumerable ProvideValue(IElementNode node, ModuleDefinition return new[] { Instruction.Create(OpCodes.Call, getterDef) }; } - public static FieldReference GetFieldReference(TypeReference typeRef, string fieldName, ModuleDefinition module) + public static FieldReference GetFieldReference(XamlCache cache, TypeReference typeRef, string fieldName, ModuleDefinition module) { - FieldReference fRef = typeRef.GetField(fd => fd.Name == fieldName + FieldReference fRef = typeRef.GetField(cache, fd => fd.Name == fieldName && fd.IsStatic && IsPublicOrVisibleInternal(fd, module), out TypeReference declaringTypeReference); if (fRef != null) @@ -109,9 +109,9 @@ static bool IsPublicOrVisibleInternal(FieldDefinition fd, ModuleDefinition modul return false; } - public static PropertyDefinition GetPropertyDefinition(TypeReference typeRef, string propertyName, ModuleDefinition module) + public static PropertyDefinition GetPropertyDefinition(XamlCache cache, TypeReference typeRef, string propertyName, ModuleDefinition module) { - PropertyDefinition pDef = typeRef.GetProperty(pd => pd.Name == propertyName + PropertyDefinition pDef = typeRef.GetProperty(cache, pd => pd.Name == propertyName && IsPublicOrVisibleInternal(pd.GetMethod, module) && pd.GetMethod.IsStatic, out TypeReference declaringTypeReference); return pDef; diff --git a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/TypeExtension.cs b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/TypeExtension.cs index d5dfe9595209..add45a05eea9 100644 --- a/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/TypeExtension.cs +++ b/src/Controls/src/Build.Tasks/CompiledMarkupExtensions/TypeExtension.cs @@ -13,7 +13,7 @@ class TypeExtension : ICompiledMarkupExtension { public IEnumerable ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef) { - memberRef = module.ImportReference(("mscorlib", "System", "Type")); + memberRef = module.ImportReference(context.Cache, ("mscorlib", "System", "Type")); var name = new XmlName("", "TypeName"); if (!node.Properties.TryGetValue(name, out INode typeNameNode) && node.CollectionItems.Any()) @@ -28,13 +28,13 @@ public IEnumerable ProvideValue(IElementNode node, ModuleDefinition node.CollectionItems.Clear(); } - var typeref = module.ImportReference(XmlTypeExtensions.GetTypeReference(valueNode.Value as string, module, node as BaseNode)); + var typeref = module.ImportReference(XmlTypeExtensions.GetTypeReference(context.Cache, valueNode.Value as string, module, node as BaseNode)); context.TypeExtensions[node] = typeref ?? throw new BuildException(BuildExceptionCode.TypeResolution, node as IXmlLineInfo, null, valueNode.Value); return new List { Create(Ldtoken, module.ImportReference(typeref)), - Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), + Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)), diff --git a/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs b/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs index 084f52910293..e4560ccd967d 100644 --- a/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs +++ b/src/Controls/src/Build.Tasks/CompiledValueProviders/SetterValueProvider.cs @@ -18,7 +18,7 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr valueNode = ((IElementNode)node).CollectionItems[0]; var bpNode = ((ValueNode)((IElementNode)node).Properties[new XmlName("", "Property")]); - var bpRef = (new BindablePropertyConverter()).GetBindablePropertyFieldReference((string)bpNode.Value, module, bpNode); + var bpRef = (new BindablePropertyConverter()).GetBindablePropertyFieldReference((string)bpNode.Value, context, module, bpNode); if (SetterValueIsCollection(bpRef, module, node, context)) yield break; @@ -34,7 +34,7 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr var setterType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Setter"); //push the setter - foreach (var instruction in vardefref.VariableDefinition.LoadAs(module.GetTypeDefinition(setterType), module)) + foreach (var instruction in vardefref.VariableDefinition.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, setterType), module)) yield return instruction; //push the value @@ -42,7 +42,7 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr yield return instruction; //set the value - yield return Instruction.Create(OpCodes.Callvirt, module.ImportPropertySetterReference(setterType, propertyName: "Value")); + yield return Instruction.Create(OpCodes.Callvirt, module.ImportPropertySetterReference(context.Cache, setterType, propertyName: "Value")); } static bool SetterValueIsCollection(FieldReference bindablePropertyReference, ModuleDefinition module, BaseNode node, ILContext context) @@ -53,7 +53,7 @@ static bool SetterValueIsCollection(FieldReference bindablePropertyReference, Mo return false; // Is this a generic type ? - var generic = bindablePropertyReference.GetBindablePropertyType(node, module) as GenericInstanceType; + var generic = bindablePropertyReference.GetBindablePropertyType(context.Cache, node, module) as GenericInstanceType; // With a single generic argument? if (generic?.GenericArguments.Count != 1) @@ -65,7 +65,7 @@ static bool SetterValueIsCollection(FieldReference bindablePropertyReference, Mo if (!(items[0] is IElementNode firstItem)) return false; - return context.Variables[firstItem].VariableType.InheritsFromOrImplements(genericType); + return context.Variables[firstItem].VariableType.InheritsFromOrImplements(context.Cache, genericType); } } } \ No newline at end of file diff --git a/src/Controls/src/Build.Tasks/CompiledValueProviders/StyleSheetProvider.cs b/src/Controls/src/Build.Tasks/CompiledValueProviders/StyleSheetProvider.cs index 2e2536ae53f5..37000220dd63 100644 --- a/src/Controls/src/Build.Tasks/CompiledValueProviders/StyleSheetProvider.cs +++ b/src/Controls/src/Build.Tasks/CompiledValueProviders/StyleSheetProvider.cs @@ -40,7 +40,7 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr { var style = (styleNode as ValueNode).Value as string; yield return Create(Ldstr, style); - yield return Create(Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"), methodName: "FromString", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true)); @@ -52,31 +52,31 @@ public IEnumerable ProvideValue(VariableDefinitionReference vardefr while (!(rootNode is ILRootNode)) rootNode = rootNode.Parent; - var rootTargetPath = RDSourceTypeConverter.GetPathForType(module, ((ILRootNode)rootNode).TypeReference); + var rootTargetPath = RDSourceTypeConverter.GetPathForType(context, module, ((ILRootNode)rootNode).TypeReference); var uri = new Uri(source, UriKind.Relative); var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early - if (XamlCTask.GetResourceIdForPath(module, resourcePath) == null) + if (XamlCTask.GetResourceIdForPath(context.Cache, module, resourcePath) == null) throw new XamlParseException($"Resource '{source}' not found.", node); yield return Create(Ldstr, resourcePath); //resourcePath yield return Create(Ldtoken, module.ImportReference(((ILRootNode)rootNode).TypeReference)); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Callvirt, module.ImportPropertyGetterReference(("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); //assembly + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Callvirt, module.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); //assembly foreach (var instruction in node.PushXmlLineInfo(context)) yield return instruction; //lineinfo - yield return Create(Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"), methodName: "FromResource", parameterTypes: new[] { ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") }, isStatic: true)); } //the variable is of type `object`. fix that - var vardef = new VariableDefinition(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"))); + var vardef = new VariableDefinition(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.StyleSheets", "StyleSheet"))); yield return Create(Stloc, vardef); vardefref.VariableDefinition = vardef; } diff --git a/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs b/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs index ff08d0f16cc1..543a8f4bbe80 100644 --- a/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs +++ b/src/Controls/src/Build.Tasks/CreateObjectVisitor.cs @@ -48,8 +48,8 @@ public void Visit(MarkupNode node, INode parentNode) public void Visit(ElementNode node, INode parentNode) { - var typeref = Module.ImportReference(node.XmlType.GetTypeReference(Module, node)); - TypeDefinition typedef = typeref.ResolveCached(); + var typeref = Module.ImportReference(node.XmlType.GetTypeReference(Context.Cache, Module, node)); + TypeDefinition typedef = typeref.ResolveCached(Context.Cache); if (IsXaml2009LanguagePrimitive(node)) { @@ -64,7 +64,7 @@ public void Visit(ElementNode node, INode parentNode) //if this is a MarkupExtension that can be compiled directly, compile and returns the value var compiledMarkupExtensionName = typeref - .GetCustomAttribute(Module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute")) + .GetCustomAttribute(Context.Cache, Module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute")) ?.ConstructorArguments?[0].Value as string; Type compiledMarkupExtensionType; ICompiledMarkupExtension markupProvider; @@ -99,7 +99,7 @@ public void Visit(ElementNode node, INode parentNode) if (node.Properties.ContainsKey(XmlName.xArguments) && !node.Properties.ContainsKey(XmlName.xFactoryMethod)) { - factoryCtorInfo = typedef.AllMethods().FirstOrDefault(md => md.methodDef.IsConstructor && + factoryCtorInfo = typedef.AllMethods(Context.Cache).FirstOrDefault(md => md.methodDef.IsConstructor && !md.methodDef.IsStatic && md.methodDef.HasParameters && md.methodDef.MatchXArguments(node, typeref, Module, Context)).methodDef; @@ -110,7 +110,7 @@ public void Visit(ElementNode node, INode parentNode) else if (node.Properties.ContainsKey(XmlName.xFactoryMethod)) { var factoryMethod = (string)(node.Properties[XmlName.xFactoryMethod] as ValueNode).Value; - factoryMethodInfo = typedef.AllMethods().FirstOrDefault(md => !md.methodDef.IsConstructor && + factoryMethodInfo = typedef.AllMethods(Context.Cache).FirstOrDefault(md => !md.methodDef.IsConstructor && md.methodDef.Name == factoryMethod && md.methodDef.IsStatic && md.methodDef.MatchXArguments(node, typeref, Module, Context)).methodDef; @@ -302,13 +302,13 @@ IEnumerable PushCtorArguments(MethodReference ctorinfo, ElementNode ValueNode vnode = null; if (node is IElementNode && (vardef = Context.Variables[node as IElementNode]) != null) - foreach (var instruction in vardef.LoadAs(parameter.ParameterType.ResolveGenericParameters(ctorinfo), Module)) + foreach (var instruction in vardef.LoadAs(Context.Cache, parameter.ParameterType.ResolveGenericParameters(ctorinfo), Module)) yield return instruction; else if ((vnode = node as ValueNode) != null) { foreach (var instruction in vnode.PushConvertedValue(Context, parameter.ParameterType, - new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached() }, + new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached(Context.Cache) }, enode.PushServiceProvider(Context), false, true)) yield return instruction; } @@ -339,13 +339,13 @@ IEnumerable PushCtorXArguments(MethodReference factoryCtorInfo, Ele ValueNode vnode = null; if (arg is IElementNode && (vardef = Context.Variables[arg as IElementNode]) != null) - foreach (var instruction in vardef.LoadAs(parameter.ParameterType.ResolveGenericParameters(factoryCtorInfo), Module)) + foreach (var instruction in vardef.LoadAs(Context.Cache, parameter.ParameterType.ResolveGenericParameters(factoryCtorInfo), Module)) yield return instruction; else if ((vnode = arg as ValueNode) != null) { foreach (var instruction in vnode.PushConvertedValue(Context, parameter.ParameterType, - new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached() }, + new ICustomAttributeProvider[] { parameter, parameter.ParameterType.ResolveCached(Context.Cache) }, enode.PushServiceProvider(Context), false, true)) yield return instruction; } @@ -449,7 +449,7 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, break; case "System.Object": var ctorinfo = - module.TypeSystem.Object.ResolveCached() + module.TypeSystem.Object.ResolveCached(Context.Cache) .Methods.FirstOrDefault(md => md.IsConstructor && !md.HasParameters); var ctor = module.ImportReference(ctorinfo); yield return Create(Newobj, ctor); @@ -464,7 +464,7 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, decimal outdecimal; if (hasValue && decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) { - var vardef = new VariableDefinition(module.ImportReference(("mscorlib", "System", "Decimal"))); + var vardef = new VariableDefinition(module.ImportReference(Context.Cache, ("mscorlib", "System", "Decimal"))); Context.Body.Variables.Add(vardef); //Use an extra temp var so we can push the value to the stack, just like other cases // IL_0003: ldstr "adecimal" @@ -475,11 +475,11 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, // IL_0016: pop yield return Create(Ldstr, valueString); yield return Create(Ldc_I4, 0x6f); //NumberStyles.Number - yield return Create(Call, module.ImportPropertyGetterReference(("mscorlib", "System.Globalization", "CultureInfo"), + yield return Create(Call, module.ImportPropertyGetterReference(Context.Cache, ("mscorlib", "System.Globalization", "CultureInfo"), propertyName: "InvariantCulture", isStatic: true)); yield return Create(Ldloca, vardef); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Decimal"), + yield return Create(Call, module.ImportMethodReference(Context.Cache, ("mscorlib", "System", "Decimal"), methodName: "TryParse", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -494,7 +494,7 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, else { yield return Create(Ldc_I4_0); - yield return Create(Newobj, module.ImportCtorReference(("mscorlib", "System", "Decimal"), parameterTypes: new[] { ("mscorlib", "System", "Int32") })); + yield return Create(Newobj, module.ImportCtorReference(Context.Cache, ("mscorlib", "System", "Decimal"), parameterTypes: new[] { ("mscorlib", "System", "Int32") })); } break; case "System.Single": @@ -512,14 +512,14 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, case "System.TimeSpan": if (hasValue && TimeSpan.TryParse(valueString, CultureInfo.InvariantCulture, out TimeSpan outspan)) { - var vardef = new VariableDefinition(module.ImportReference(("mscorlib", "System", "TimeSpan"))); + var vardef = new VariableDefinition(module.ImportReference(Context.Cache, ("mscorlib", "System", "TimeSpan"))); Context.Body.Variables.Add(vardef); //Use an extra temp var so we can push the value to the stack, just like other cases yield return Create(Ldstr, valueString); - yield return Create(Call, module.ImportPropertyGetterReference(("mscorlib", "System.Globalization", "CultureInfo"), + yield return Create(Call, module.ImportPropertyGetterReference(Context.Cache, ("mscorlib", "System.Globalization", "CultureInfo"), propertyName: "InvariantCulture", isStatic: true)); yield return Create(Ldloca, vardef); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "TimeSpan"), + yield return Create(Call, module.ImportMethodReference(Context.Cache, ("mscorlib", "System", "TimeSpan"), methodName: "TryParse", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -533,19 +533,19 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, else { yield return Create(Ldc_I8, 0L); - yield return Create(Newobj, module.ImportCtorReference(("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); + yield return Create(Newobj, module.ImportCtorReference(Context.Cache, ("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); } break; case "System.Uri": if (hasValue && Uri.TryCreate(valueString, UriKind.RelativeOrAbsolute, out _)) { - var vardef = new VariableDefinition(module.ImportReference(("System", "System", "Uri"))); + var vardef = new VariableDefinition(module.ImportReference(Context.Cache, ("System", "System", "Uri"))); Context.Body.Variables.Add(vardef); //Use an extra temp var so we can push the value to the stack, just like other cases yield return Create(Ldstr, valueString); yield return Create(Ldc_I4, (int)UriKind.RelativeOrAbsolute); yield return Create(Ldloca, vardef); - yield return Create(Call, module.ImportMethodReference(("System", "System", "Uri"), + yield return Create(Call, module.ImportMethodReference(Context.Cache, ("System", "System", "Uri"), methodName: "TryCreate", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -560,7 +560,7 @@ IEnumerable PushValueFromLanguagePrimitive(TypeDefinition typedef, yield return Create(Ldnull); break; default: - var defaultCtor = module.ImportCtorReference(typedef, parameterTypes: null); + var defaultCtor = module.ImportCtorReference(Context.Cache, typedef, parameterTypes: null); if (defaultCtor != null) yield return Create(Newobj, defaultCtor); else diff --git a/src/Controls/src/Build.Tasks/DebugXamlCTask.cs b/src/Controls/src/Build.Tasks/DebugXamlCTask.cs index b439f8a5e41c..d717ee3f61c3 100644 --- a/src/Controls/src/Build.Tasks/DebugXamlCTask.cs +++ b/src/Controls/src/Build.Tasks/DebugXamlCTask.cs @@ -11,6 +11,8 @@ namespace Microsoft.Maui.Controls.Build.Tasks { public class DebugXamlCTask : XamlTask { + readonly XamlCache cache = new(); + public override bool Execute(out IList thrownExceptions) { thrownExceptions = null; @@ -42,7 +44,7 @@ public override bool Execute(out IList thrownExceptions) foreach (var resource in module.Resources.OfType()) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); - if (!resource.IsXaml(module, out var classname)) + if (!resource.IsXaml(cache, module, out var classname)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}skipped."); continue; diff --git a/src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs b/src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs index c710f9840aeb..824697d7298b 100644 --- a/src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs +++ b/src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs @@ -190,7 +190,7 @@ public INode Parse(string match, ref string remaining, IServiceProvider serviceP //The order of lookup is to look for the Extension-suffixed class name first and then look for the class name without the Extension suffix. XmlType type = new XmlType(namespaceuri, name + "Extension", typeArguments); - if (!type.TryGetTypeReference(contextProvider.Context.Module, null, out _)) + if (!type.TryGetTypeReference(contextProvider.Context.Cache, contextProvider.Context.Module, null, out _)) type = new XmlType(namespaceuri, name, typeArguments); if (type == null) diff --git a/src/Controls/src/Build.Tasks/ILContext.cs b/src/Controls/src/Build.Tasks/ILContext.cs index 6eaed3505d1d..c1e4a3942115 100644 --- a/src/Controls/src/Build.Tasks/ILContext.cs +++ b/src/Controls/src/Build.Tasks/ILContext.cs @@ -9,7 +9,7 @@ namespace Microsoft.Maui.Controls.Build.Tasks { class ILContext { - public ILContext(ILProcessor il, MethodBody body, ModuleDefinition module, FieldDefinition parentContextValues = null) + public ILContext(ILProcessor il, MethodBody body, ModuleDefinition module, XamlCache cache, FieldDefinition parentContextValues = null) { IL = il; Body = body; @@ -19,8 +19,11 @@ public ILContext(ILProcessor il, MethodBody body, ModuleDefinition module, Field TypeExtensions = new Dictionary(); ParentContextValues = parentContextValues; Module = module; + Cache = cache; } + public XamlCache Cache { get; private set; } + public Dictionary Values { get; private set; } public Dictionary Variables { get; private set; } diff --git a/src/Controls/src/Build.Tasks/MethodDefinitionExtensions.cs b/src/Controls/src/Build.Tasks/MethodDefinitionExtensions.cs index f94c90c7f0ed..8c44720d5363 100644 --- a/src/Controls/src/Build.Tasks/MethodDefinitionExtensions.cs +++ b/src/Controls/src/Build.Tasks/MethodDefinitionExtensions.cs @@ -34,7 +34,7 @@ public static bool MatchXArguments(this MethodDefinition methodDef, ElementNode paramType = (declaringTypeRef as GenericInstanceType).GenericArguments[index]; } var argType = context.Variables[arguments[i] as IElementNode].VariableType; - if (!argType.InheritsFromOrImplements(paramType)) + if (!argType.InheritsFromOrImplements(context.Cache, paramType)) return false; } return true; diff --git a/src/Controls/src/Build.Tasks/ModuleDefinitionExtensions.cs b/src/Controls/src/Build.Tasks/ModuleDefinitionExtensions.cs index b85a5a5e37e1..705bffa6319e 100644 --- a/src/Controls/src/Build.Tasks/ModuleDefinitionExtensions.cs +++ b/src/Controls/src/Build.Tasks/ModuleDefinitionExtensions.cs @@ -8,35 +8,23 @@ namespace Microsoft.Maui.Controls.Build.Tasks { static class ModuleDefinitionExtensions { - static Dictionary<(ModuleDefinition module, string typeKey), TypeReference> TypeRefCache = new Dictionary<(ModuleDefinition module, string typeKey), TypeReference>(); - public static TypeReference ImportReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type) - { - var typeKey = type.ToString(); - if (!TypeRefCache.TryGetValue((module, typeKey), out var typeRef)) - TypeRefCache.Add((module, typeKey), typeRef = module.ImportReference(module.GetTypeDefinition(type))); - return typeRef; - } + public static TypeReference ImportReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type) => cache.GetOrAddTypeReference(module, type); - public static TypeReference ImportReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] classArguments) + public static TypeReference ImportReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] classArguments) { var typeKey = $"{type}<{string.Join(",", classArguments)}>"; - if (!TypeRefCache.TryGetValue((module, typeKey), out var typeRef)) - TypeRefCache.Add((module, typeKey), typeRef = module.ImportReference(module.ImportReference(type).MakeGenericInstanceType(classArguments.Select(gp => module.GetTypeDefinition((gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray()))); - return typeRef; + return cache.GetOrAddTypeReference(module, typeKey, x => module.ImportReference(module.ImportReference(cache, type).MakeGenericInstanceType(classArguments.Select(gp => module.GetTypeDefinition(cache, (gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray()))); } - public static TypeReference ImportArrayReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type) + public static TypeReference ImportArrayReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type) { - var typeKey = "${type}[]"; - if (!TypeRefCache.TryGetValue((module, typeKey), out var typeRef)) - TypeRefCache.Add((module, typeKey), typeRef = module.ImportReference(module.ImportReference(type).MakeArrayType())); - return typeRef; + var typeKey = $"{type}[]"; + return cache.GetOrAddTypeReference(module, typeKey, x => module.ImportReference(module.ImportReference(cache, type).MakeArrayType())); } - static Dictionary<(ModuleDefinition module, string methodRefKey), MethodReference> MethodRefCache = new Dictionary<(ModuleDefinition module, string methodRefKey), MethodReference>(); - static MethodReference ImportCtorReference(this ModuleDefinition module, TypeReference type, TypeReference[] classArguments, Func predicate) + static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, TypeReference type, TypeReference[] classArguments, Func predicate) { - var ctor = module.ImportReference(type).ResolveCached().Methods.FirstOrDefault(md => !md.IsPrivate && !md.IsStatic && md.IsConstructor && (predicate?.Invoke(md) ?? true)); + var ctor = module.ImportReference(type).ResolveCached(cache).Methods.FirstOrDefault(md => !md.IsPrivate && !md.IsStatic && md.IsConstructor && (predicate?.Invoke(md) ?? true)); if (ctor is null) return null; var ctorRef = module.ImportReference(ctor); @@ -45,99 +33,79 @@ static MethodReference ImportCtorReference(this ModuleDefinition module, TypeRef return module.ImportReference(ctorRef.ResolveGenericParameters(type.MakeGenericInstanceType(classArguments), module)); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, TypeReference type, TypeReference[] parameterTypes) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, TypeReference type, TypeReference[] parameterTypes) { var ctorKey = $"{type}.ctor({(parameterTypes == null ? "" : string.Join(",", parameterTypes.Select(SerializeTypeReference)))})"; - if (MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - return ctorRef; - ctorRef = module.ImportCtorReference(type, classArguments: null, predicate: md => + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, type, classArguments: null, predicate: md => { if (md.Parameters.Count != (parameterTypes?.Length ?? 0)) return false; for (var i = 0; i < md.Parameters.Count; i++) - if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, module.ImportReference(parameterTypes[i]))) + if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, x.module.ImportReference(parameterTypes[i]))) return false; return true; - }); - MethodRefCache.Add((module, ctorKey), ctorRef); - return ctorRef; + })); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, int paramCount) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, int paramCount) { var ctorKey = $"{type}.ctor({(string.Join(",", Enumerable.Repeat("_", paramCount)))})"; - if (!MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - MethodRefCache.Add((module, ctorKey), ctorRef = module.ImportCtorReference(module.GetTypeDefinition(type), null, md => md.Parameters.Count == paramCount)); - return ctorRef; + return cache.GetOrAddMethodReference (module, ctorKey, x => x.module.ImportCtorReference(cache, x.module.GetTypeDefinition(cache, type), null, md => md.Parameters.Count == paramCount)); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, TypeReference type, int paramCount) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, TypeReference type, int paramCount) { var ctorKey = $"{type}.ctor({(string.Join(",", Enumerable.Repeat("_", paramCount)))})"; - if (!MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - MethodRefCache.Add((module, ctorKey), ctorRef = module.ImportCtorReference(type, null, md => md.Parameters.Count == paramCount)); - return ctorRef; + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, type, null, md => md.Parameters.Count == paramCount)); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, int paramCount, (string assemblyName, string clrNamespace, string typeName)[] classArguments) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, int paramCount, (string assemblyName, string clrNamespace, string typeName)[] classArguments) { var ctorKey = $"{type}<{(string.Join(",", classArguments))}>.ctor({(string.Join(",", Enumerable.Repeat("_", paramCount)))})"; - if (!MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - MethodRefCache.Add((module, ctorKey), ctorRef = module.ImportCtorReference(module.GetTypeDefinition(type), classArguments.Select(module.GetTypeDefinition).ToArray(), md => md.Parameters.Count == paramCount)); - return ctorRef; + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, x.module.GetTypeDefinition(cache, type), classArguments.Select(args => x.module.GetTypeDefinition(cache, args)).ToArray(), md => md.Parameters.Count == paramCount)); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, int paramCount, TypeReference[] classArguments) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, int paramCount, TypeReference[] classArguments) { var ctorKey = $"{type}<{string.Join(",", classArguments.Select(SerializeTypeReference))}>.ctor({(string.Join(",", Enumerable.Repeat("_", paramCount)))})"; - if (!MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - MethodRefCache.Add((module, ctorKey), ctorRef = module.ImportCtorReference(module.GetTypeDefinition(type), classArguments, predicate: md => md.Parameters.Count == paramCount)); - return ctorRef; + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, x.module.GetTypeDefinition(cache, type), classArguments, predicate: md => md.Parameters.Count == paramCount)); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] parameterTypes, (string assemblyName, string clrNamespace, string typeName)[] classArguments) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] parameterTypes, (string assemblyName, string clrNamespace, string typeName)[] classArguments) { var ctorKey = $"{type}<{(string.Join(",", classArguments))}>.ctor({(parameterTypes == null ? "" : string.Join(",", parameterTypes))})"; - if (MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - return ctorRef; - ctorRef = module.ImportCtorReference(module.GetTypeDefinition(type), classArguments.Select(module.GetTypeDefinition).ToArray(), md => + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, x.module.GetTypeDefinition(cache, type), classArguments.Select(args => x.module.GetTypeDefinition(cache, args)).ToArray(), md => { if (md.Parameters.Count != (parameterTypes?.Length ?? 0)) return false; for (var i = 0; i < md.Parameters.Count; i++) - if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, module.ImportReference(parameterTypes[i]))) + if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, x.module.ImportReference(cache, parameterTypes[i]))) return false; return true; - }); - MethodRefCache.Add((module, ctorKey), ctorRef); - return ctorRef; + })); } - public static MethodReference ImportCtorReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] parameterTypes) + public static MethodReference ImportCtorReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, (string assemblyName, string clrNamespace, string typeName)[] parameterTypes) { var ctorKey = $"{type}.ctor({(parameterTypes == null ? "" : string.Join(",", parameterTypes))})"; - if (MethodRefCache.TryGetValue((module, ctorKey), out var ctorRef)) - return ctorRef; - ctorRef = module.ImportCtorReference(module.GetTypeDefinition(type), classArguments: null, predicate: md => + return cache.GetOrAddMethodReference(module, ctorKey, x => x.module.ImportCtorReference(cache, x.module.GetTypeDefinition(cache, type), classArguments: null, predicate: md => { if (md.Parameters.Count != (parameterTypes?.Length ?? 0)) return false; for (var i = 0; i < md.Parameters.Count; i++) - if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, module.ImportReference(parameterTypes[i]))) + if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, x.module.ImportReference(cache, parameterTypes[i]))) return false; return true; - }); - MethodRefCache.Add((module, ctorKey), ctorRef); - return ctorRef; + })); } - static MethodReference ImportPropertyGetterReference(this ModuleDefinition module, TypeReference type, string propertyName, Func predicate = null, bool flatten = false, bool caseSensitive = true) + static MethodReference ImportPropertyGetterReference(this ModuleDefinition module, XamlCache cache, TypeReference type, string propertyName, Func predicate = null, bool flatten = false, bool caseSensitive = true) { var properties = module.ImportReference(type).Resolve().Properties; var getter = module .ImportReference(type) - .ResolveCached() - .Properties(flatten) + .ResolveCached(cache) + .Properties(cache, flatten) .FirstOrDefault(pd => string.Equals(pd.Name, propertyName, caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase) && !pd.GetMethod.IsPrivate @@ -146,19 +114,17 @@ static MethodReference ImportPropertyGetterReference(this ModuleDefinition modul return getter == null ? null : module.ImportReference(getter); } - public static MethodReference ImportPropertyGetterReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, string propertyName, bool isStatic = false, bool flatten = false, bool caseSensitive = true) + public static MethodReference ImportPropertyGetterReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, string propertyName, bool isStatic = false, bool flatten = false, bool caseSensitive = true) { var getterKey = $"{(isStatic ? "static " : "")}{type}.get_{propertyName}{(flatten ? "*" : "")}"; - if (!MethodRefCache.TryGetValue((module, getterKey), out var methodReference)) - MethodRefCache.Add((module, getterKey), methodReference = module.ImportPropertyGetterReference(module.GetTypeDefinition(type), propertyName, pd => pd.GetMethod.IsStatic == isStatic, flatten, caseSensitive: caseSensitive)); - return methodReference; + return cache.GetOrAddMethodReference(module, getterKey, x => x.module.ImportPropertyGetterReference(cache, x.module.GetTypeDefinition(cache, type), propertyName, pd => pd.GetMethod.IsStatic == isStatic, flatten, caseSensitive: caseSensitive)); } - static MethodReference ImportPropertySetterReference(this ModuleDefinition module, TypeReference type, string propertyName, Func predicate = null) + static MethodReference ImportPropertySetterReference(this ModuleDefinition module, XamlCache cache, TypeReference type, string propertyName, Func predicate = null) { var setter = module .ImportReference(type) - .ResolveCached() + .ResolveCached(cache) .Properties .FirstOrDefault(pd => pd.Name == propertyName @@ -168,19 +134,17 @@ static MethodReference ImportPropertySetterReference(this ModuleDefinition modul return setter == null ? null : module.ImportReference(setter); } - public static MethodReference ImportPropertySetterReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, string propertyName, bool isStatic = false) + public static MethodReference ImportPropertySetterReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, string propertyName, bool isStatic = false) { var setterKey = $"{(isStatic ? "static " : "")}{type}.set{propertyName}"; - if (!MethodRefCache.TryGetValue((module, setterKey), out var methodReference)) - MethodRefCache.Add((module, setterKey), methodReference = module.ImportPropertySetterReference(module.GetTypeDefinition(type), propertyName, pd => pd.SetMethod.IsStatic == isStatic)); - return methodReference; + return cache.GetOrAddMethodReference(module, setterKey, x => x.module.ImportPropertySetterReference(cache, x.module.GetTypeDefinition(cache, type), propertyName, pd => pd.SetMethod.IsStatic == isStatic)); } - static MethodReference ImportMethodReference(this ModuleDefinition module, TypeReference type, string methodName, Func predicate = null, TypeReference[] classArguments = null) + static MethodReference ImportMethodReference(this ModuleDefinition module, XamlCache cache, TypeReference type, string methodName, Func predicate = null, TypeReference[] classArguments = null) { var method = module .ImportReference(type) - .ResolveCached() + .ResolveCached(cache) .Methods .FirstOrDefault(md => !md.IsConstructor @@ -196,13 +160,14 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR } public static MethodReference ImportMethodReference(this ModuleDefinition module, + XamlCache cache, TypeReference type, string methodName, TypeReference[] parameterTypes = null, TypeReference[] classArguments = null, bool isStatic = false) { - return module.ImportMethodReference(type, + return module.ImportMethodReference(cache, type, methodName: methodName, predicate: md => { @@ -219,6 +184,7 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR } public static MethodReference ImportMethodReference(this ModuleDefinition module, + XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, string methodName, (string assemblyName, string clrNamespace, string typeName)[] parameterTypes, @@ -226,9 +192,8 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR bool isStatic = false) { var methodKey = $"{(isStatic ? "static " : "")}{type}<{(classArguments == null ? "" : string.Join(",", classArguments))}>.({(parameterTypes == null ? "" : string.Join(",", parameterTypes))})"; - if (MethodRefCache.TryGetValue((module, methodKey), out var methodReference)) - return methodReference; - methodReference = module.ImportMethodReference(module.GetTypeDefinition(type), + return cache.GetOrAddMethodReference(module, methodKey, x => x.module.ImportMethodReference(cache, + x.module.GetTypeDefinition(cache, type), methodName: methodName, predicate: md => { @@ -237,16 +202,15 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR if (md.Parameters.Count != (parameterTypes?.Length ?? 0)) return false; for (var i = 0; i < md.Parameters.Count; i++) - if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, module.ImportReference(parameterTypes[i]))) + if (!TypeRefComparer.Default.Equals(md.Parameters[i].ParameterType, x.module.ImportReference(cache, parameterTypes[i]))) return false; return true; }, - classArguments: classArguments?.Select(gp => module.GetTypeDefinition((gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray()); - MethodRefCache.Add((module, methodKey), methodReference); - return methodReference; + classArguments: classArguments?.Select(gp => x.module.GetTypeDefinition(cache, (gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray())); } public static MethodReference ImportMethodReference(this ModuleDefinition module, + XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, string methodName, int paramCount, @@ -254,9 +218,8 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR bool isStatic = false) { var methodKey = $"{(isStatic ? "static " : "")}{type}<{(classArguments == null ? "" : string.Join(",", classArguments))}>.({(string.Join(",", Enumerable.Repeat("_", paramCount)))})"; - if (MethodRefCache.TryGetValue((module, methodKey), out var methodReference)) - return methodReference; - methodReference = module.ImportMethodReference(module.GetTypeDefinition(type), + return cache.GetOrAddMethodReference(module, methodKey, x => x.module.ImportMethodReference(cache, + x.module.GetTypeDefinition(cache, type), methodName: methodName, predicate: md => { @@ -266,17 +229,14 @@ static MethodReference ImportMethodReference(this ModuleDefinition module, TypeR return false; return true; }, - classArguments: classArguments?.Select(gp => module.GetTypeDefinition((gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray()); - MethodRefCache.Add((module, methodKey), methodReference); - return methodReference; + classArguments: classArguments?.Select(gp => x.module.GetTypeDefinition(cache, (gp.assemblyName, gp.clrNamespace, gp.typeName))).ToArray())); } - static Dictionary<(ModuleDefinition module, string fieldRefKey), FieldReference> FieldRefCache = new Dictionary<(ModuleDefinition module, string fieldRefKey), FieldReference>(); - static FieldReference ImportFieldReference(this ModuleDefinition module, TypeReference type, string fieldName, Func predicate = null, bool caseSensitive = true) + static FieldReference ImportFieldReference(this ModuleDefinition module, XamlCache cache, TypeReference type, string fieldName, Func predicate = null, bool caseSensitive = true) { var field = module .ImportReference(type) - .ResolveCached() + .ResolveCached(cache) .Fields .FirstOrDefault(fd => string.Equals(fd.Name, fieldName, caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase) @@ -284,53 +244,47 @@ static FieldReference ImportFieldReference(this ModuleDefinition module, TypeRef return field == null ? null : module.ImportReference(field); } - public static FieldReference ImportFieldReference(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, string fieldName, bool isStatic = false, bool caseSensitive = true) + public static FieldReference ImportFieldReference(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type, string fieldName, bool isStatic = false, bool caseSensitive = true) { var fieldKey = $"{(isStatic ? "static " : "")}{type}.{(caseSensitive ? fieldName : fieldName.ToLowerInvariant())}"; - if (!FieldRefCache.TryGetValue((module, fieldKey), out var fieldReference)) - FieldRefCache.Add((module, fieldKey), fieldReference = module.ImportFieldReference(module.GetTypeDefinition(type), fieldName: fieldName, predicate: fd => fd.IsStatic == isStatic, caseSensitive: caseSensitive)); - return fieldReference; + return cache.GetOrAddFieldReference((module, fieldKey), _ => module.ImportFieldReference(cache, module.GetTypeDefinition(cache, type), fieldName: fieldName, predicate: fd => fd.IsStatic == isStatic, caseSensitive: caseSensitive)); } - static Dictionary<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition> typeDefCache - = new Dictionary<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition>(); - - public static TypeDefinition GetTypeDefinition(this ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type) + public static TypeDefinition GetTypeDefinition(this ModuleDefinition module, XamlCache cache, (string assemblyName, string clrNamespace, string typeName) type) { - if (typeDefCache.TryGetValue((module, type), out TypeDefinition cachedTypeDefinition)) - return cachedTypeDefinition; - - var asm = module.Assembly.Name.Name == type.assemblyName - ? module.Assembly - : module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(type.assemblyName)); - var typeDef = asm.MainModule.GetType($"{type.clrNamespace}.{type.typeName}"); - if (typeDef != null) - { - typeDefCache.Add((module, type), typeDef); - return typeDef; - } - var exportedType = asm.MainModule.ExportedTypes.FirstOrDefault( - arg => arg.IsForwarder && arg.Namespace == type.clrNamespace && arg.Name == type.typeName); - if (exportedType != null) + return cache.GetOrAddTypeDefinition(module, type, x => { - typeDef = exportedType.Resolve(); - typeDefCache.Add((module, type), typeDef); - return typeDef; - } + var asm = module.Assembly.Name.Name == type.assemblyName + ? module.Assembly + : module.AssemblyResolver.Resolve(AssemblyNameReference.Parse(type.assemblyName)); + var typeDef = asm.MainModule.GetType($"{type.clrNamespace}.{type.typeName}"); + if (typeDef != null) + { + return typeDef; + } + var exportedType = asm.MainModule.ExportedTypes.FirstOrDefault( + arg => arg.IsForwarder && arg.Namespace == type.clrNamespace && arg.Name == type.typeName); + if (exportedType != null) + { + typeDef = exportedType.Resolve(); + return typeDef; + } - //I hate you, netstandard - if (type.assemblyName == "mscorlib" && type.clrNamespace == "System.Reflection") - return module.GetTypeDefinition(("System.Reflection", type.clrNamespace, type.typeName)); - return null; + //I hate you, netstandard + if (type.assemblyName == "mscorlib" && type.clrNamespace == "System.Reflection") + return module.GetTypeDefinition(cache, ("System.Reflection", type.clrNamespace, type.typeName)); + + return null; + }); } - static IEnumerable Properties(this TypeDefinition typedef, bool flatten) + static IEnumerable Properties(this TypeDefinition typedef, XamlCache cache, bool flatten) { foreach (var property in typedef.Properties) yield return property; if (!flatten || typedef.BaseType == null) yield break; - foreach (var property in typedef.BaseType.ResolveCached().Properties(true)) + foreach (var property in typedef.BaseType.ResolveCached(cache).Properties(cache, flatten: true)) yield return property; } diff --git a/src/Controls/src/Build.Tasks/NodeILExtensions.cs b/src/Controls/src/Build.Tasks/NodeILExtensions.cs index 592ebbb1cfb7..e036a16a4cb8 100644 --- a/src/Controls/src/Build.Tasks/NodeILExtensions.cs +++ b/src/Controls/src/Build.Tasks/NodeILExtensions.cs @@ -37,8 +37,8 @@ public static bool CanConvertValue(this ValueNode node, ILContext context, TypeR public static bool CanConvertValue(this ValueNode node, ILContext context, FieldReference bpRef) { var module = context.Body.Method.Module; - var targetTypeRef = bpRef.GetBindablePropertyType(node, module); - var typeConverter = bpRef.GetBindablePropertyTypeConverter(module); + var targetTypeRef = bpRef.GetBindablePropertyType(context.Cache, node, module); + var typeConverter = bpRef.GetBindablePropertyTypeConverter(context.Cache, module); return node.CanConvertValue(context, targetTypeRef, typeConverter); } @@ -52,9 +52,9 @@ public static bool CanConvertValue(this ValueNode node, ILContext context, TypeR return true; //check if it's assignable from a string - if (targetTypeRef.ResolveCached().FullName == "System.Nullable`1") + if (targetTypeRef.ResolveCached(context.Cache).FullName == "System.Nullable`1") targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; - if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum") + if (targetTypeRef.ResolveCached(context.Cache).BaseType != null && targetTypeRef.ResolveCached(context.Cache).BaseType.FullName == "System.Enum") return true; if (targetTypeRef.FullName == "System.Char") return true; @@ -90,7 +90,7 @@ public static bool CanConvertValue(this ValueNode node, ILContext context, TypeR return true; if (targetTypeRef.FullName == "System.Decimal") return true; - var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module); + var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(context.Cache, targetTypeRef, module); if (implicitOperator != null) return true; return false; @@ -122,8 +122,8 @@ public static bool CanConvertValue(this ValueNode node, ILContext context, TypeR IEnumerable pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; - var targetTypeRef = bpRef.GetBindablePropertyType(node, module); - var typeConverter = bpRef.GetBindablePropertyTypeConverter(module); + var targetTypeRef = bpRef.GetBindablePropertyType(context.Cache, node, module); + var typeConverter = bpRef.GetBindablePropertyTypeConverter(context.Cache, module); return node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes, unboxValueTypes); @@ -141,40 +141,19 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) } } - static Dictionary KnownCompiledTypeConverters; - public static IEnumerable PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; - if (KnownCompiledTypeConverters == null) - { - KnownCompiledTypeConverters = new Dictionary(TypeRefComparer.Default) - { - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "ThicknessTypeConverter")), typeof(ThicknessTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "CornerRadiusTypeConverter")), typeof(CornerRadiusTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "EasingTypeConverter")), typeof(EasingTypeConverter) }, - { module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "ColorTypeConverter")), typeof(ColorTypeConverter) }, - { module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "PointTypeConverter")), typeof(PointTypeConverter) }, - { module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "RectTypeConverter")), typeof(RectangleTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexJustifyTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexDirectionTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignContentTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignItemsTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignSelfTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexWrapTypeConverter")), typeof(EnumTypeConverter) }, - { module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexBasisTypeConverter")), typeof(FlexBasisTypeConverter) }, - - }; - } + var knownCompiledTypeConverters = context.Cache.GetKnownCompiledTypeConverters(module); var str = (string)node.Value; //If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this Type compiledConverterType; - if (typeConverter?.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName + if (typeConverter?.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName && (compiledConverterType = Type.GetType(compiledConverterName)) != null - || (typeConverter != null && KnownCompiledTypeConverters.TryGetValue(typeConverter, out compiledConverterType))) + || (typeConverter != null && knownCompiledTypeConverters.TryGetValue(typeConverter, out compiledConverterType))) { var compiledConverter = Activator.CreateInstance(compiledConverterType); var converter = typeof(ICompiledTypeConverter).GetMethods().FirstOrDefault(md => md.Name == "ConvertFromString"); @@ -202,14 +181,14 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) //If there's a [TypeConverter], use it if (typeConverter != null) { - var isExtendedConverter = typeConverter.ImplementsInterface(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "IExtendedTypeConverter"))); - var typeConverterCtorRef = module.ImportCtorReference(typeConverter, paramCount: 0); + var isExtendedConverter = typeConverter.ImplementsInterface(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "IExtendedTypeConverter"))); + var typeConverterCtorRef = module.ImportCtorReference(context.Cache, typeConverter, paramCount: 0); var convertFromInvariantStringDefinition = isExtendedConverter - ? module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "IExtendedTypeConverter")) - .ResolveCached() + ? module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "IExtendedTypeConverter")) + .ResolveCached(context.Cache) .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2) - : typeConverter.ResolveCached() - .AllMethods() + : typeConverter.ResolveCached(context.Cache) + .AllMethods(context.Cache) .FirstOrDefault(md => md.methodDef.Name == "ConvertFromInvariantString" && md.methodDef.Parameters.Count == 1).methodDef; var convertFromInvariantStringReference = module.ImportReference(convertFromInvariantStringDefinition); @@ -233,20 +212,20 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) var originalTypeRef = targetTypeRef; var isNullable = false; MethodReference nullableCtor = null; - if (targetTypeRef.ResolveCached().FullName == "System.Nullable`1") + if (targetTypeRef.ResolveCached(context.Cache).FullName == "System.Nullable`1") { var nullableTypeRef = targetTypeRef; targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; isNullable = true; - nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1; + nullableCtor = originalTypeRef.GetMethods(context.Cache, md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1; nullableCtor = nullableCtor.ResolveGenericParameters(nullableTypeRef, module); } - var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module); + var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(context.Cache, targetTypeRef, module); //Obvious Built-in conversions - if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum") - yield return PushParsedEnum(targetTypeRef, str, node); + if (targetTypeRef.ResolveCached(context.Cache).BaseType != null && targetTypeRef.ResolveCached(context.Cache).BaseType.FullName == "System.Enum") + yield return PushParsedEnum(context.Cache, targetTypeRef, str, node); else if (targetTypeRef.FullName == "System.Char") yield return Instruction.Create(OpCodes.Ldc_I4, unchecked((int)TryFormat(Char.Parse, node, str))); else if (targetTypeRef.FullName == "System.SByte") @@ -281,14 +260,14 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) var ts = TryFormat(s => TimeSpan.Parse(s, CultureInfo.InvariantCulture), node, str); var ticks = ts.Ticks; yield return Instruction.Create(OpCodes.Ldc_I8, ticks); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); } else if (targetTypeRef.FullName == "System.DateTime") { var dt = TryFormat(s => DateTime.Parse(s, CultureInfo.InvariantCulture), node, str); var ticks = dt.Ticks; yield return Instruction.Create(OpCodes.Ldc_I8, ticks); - yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("mscorlib", "System", "DateTime"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); + yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(context.Cache, ("mscorlib", "System", "DateTime"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })); } else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal)) yield return Instruction.Create(OpCodes.Ldstr, str.Substring(2)); @@ -301,7 +280,7 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) decimal outdecimal; if (decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) { - var vardef = new VariableDefinition(module.ImportReference(("mscorlib", "System", "Decimal"))); + var vardef = new VariableDefinition(module.ImportReference(context.Cache, ("mscorlib", "System", "Decimal"))); context.Body.Variables.Add(vardef); //Use an extra temp var so we can push the value to the stack, just like other cases // IL_0003: ldstr "adecimal" @@ -312,10 +291,10 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) // IL_0016: pop yield return Create(Ldstr, str); yield return Create(Ldc_I4, 0x6f); //NumberStyles.Number - yield return Create(Call, module.ImportPropertyGetterReference(("mscorlib", "System.Globalization", "CultureInfo"), + yield return Create(Call, module.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System.Globalization", "CultureInfo"), propertyName: "InvariantCulture", isStatic: true)); yield return Create(Ldloca, vardef); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Decimal"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Decimal"), methodName: "TryParse", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -330,7 +309,7 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) else { yield return Create(Ldc_I4_0); - yield return Create(Newobj, module.ImportCtorReference(("mscorlib", "System", "Decimal"), parameterTypes: new[] { ("mscorlib", "System", "Int32") })); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("mscorlib", "System", "Decimal"), parameterTypes: new[] { ("mscorlib", "System", "Int32") })); } } else if (implicitOperator != null) @@ -347,9 +326,9 @@ static T TryFormat(Func func, IXmlLineInfo lineInfo, string str) yield return Create(Box, module.ImportReference(originalTypeRef)); } - static Instruction PushParsedEnum(TypeReference enumRef, string value, IXmlLineInfo lineInfo) + static Instruction PushParsedEnum(XamlCache cache, TypeReference enumRef, string value, IXmlLineInfo lineInfo) { - var enumDef = enumRef.ResolveCached(); + var enumDef = enumRef.ResolveCached(cache); if (!enumDef.IsEnum) throw new InvalidOperationException(); @@ -456,13 +435,13 @@ public static IEnumerable PushXmlLineInfo(this INode node, ILContex { yield return Create(Ldc_I4, xmlLineInfo.LineNumber); yield return Create(Ldc_I4, xmlLineInfo.LinePosition); - ctor = module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XmlLineInfo"), parameterTypes: new[] { + ctor = module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XmlLineInfo"), parameterTypes: new[] { ("mscorlib", "System", "Int32"), ("mscorlib", "System", "Int32"), }); } else - ctor = module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XmlLineInfo"), parameterTypes: null); + ctor = module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XmlLineInfo"), parameterTypes: null); yield return Create(Newobj, ctor); } @@ -512,7 +491,7 @@ public static IEnumerable PushParentObjectsArray(this INode node, I yield return Instruction.Create(OpCodes.Ldc_I4, nodes.Count); yield return Instruction.Create(OpCodes.Add); yield return Instruction.Create(OpCodes.Newarr, module.TypeSystem.Object); - var finalArray = new VariableDefinition(module.ImportArrayReference(("mscorlib", "System", "Object"))); + var finalArray = new VariableDefinition(module.ImportArrayReference(context.Cache, ("mscorlib", "System", "Object"))); context.Body.Variables.Add(finalArray); yield return Instruction.Create(OpCodes.Stloc, finalArray); @@ -525,7 +504,7 @@ public static IEnumerable PushParentObjectsArray(this INode node, I yield return Create(Ldloc, finalArray); //destinationArray yield return Create(Ldc_I4, nodes.Count); //destinationIndex yield return Create(Ldloc, parentObjectLength); //length - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Array"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Array"), methodName: "Copy", parameterTypes: new[] { ("mscorlib", "System", "Array"), @@ -546,14 +525,14 @@ public static IEnumerable PushParentObjectsArray(this INode node, I var en = nodes[i]; yield return Instruction.Create(OpCodes.Dup); yield return Instruction.Create(OpCodes.Ldc_I4, i); - foreach (var instruction in context.Variables[en].LoadAs(module.TypeSystem.Object, module)) + foreach (var instruction in context.Variables[en].LoadAs(context.Cache, module.TypeSystem.Object, module)) yield return instruction; yield return Instruction.Create(OpCodes.Stelem_Ref); } } } - static IEnumerable PushTargetProperty(FieldReference bpRef, PropertyReference propertyRef, TypeReference declaringTypeReference, ModuleDefinition module) + static IEnumerable PushTargetProperty(ILContext context, FieldReference bpRef, PropertyReference propertyRef, TypeReference declaringTypeReference, ModuleDefinition module) { if (bpRef != null) { @@ -563,9 +542,9 @@ static IEnumerable PushTargetProperty(FieldReference bpRef, Propert if (propertyRef != null) { yield return Create(Ldtoken, module.ImportReference(declaringTypeReference ?? propertyRef.DeclaringType)); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); yield return Create(Ldstr, propertyRef.Name); - yield return Create(Call, module.ImportMethodReference(("System.Reflection.Extensions", "System.Reflection", "RuntimeReflectionExtensions"), + yield return Create(Call, module.ImportMethodReference(context.Cache, ("System.Reflection.Extensions", "System.Reflection", "RuntimeReflectionExtensions"), methodName: "GetRuntimeProperty", parameterTypes: new[]{ ("mscorlib", "System", "Type"), @@ -587,27 +566,27 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo yield break; #endif - var addService = module.ImportMethodReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), + var addService = module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), methodName: "Add", parameterTypes: new[] { ("mscorlib", "System", "Type"), ("mscorlib", "System", "Object"), }); - yield return Create(Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), parameterTypes: null)); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlServiceProvider"), parameterTypes: null)); //Add a SimpleValueTargetProvider and register it as IProvideValueTarget and IReferenceProvider var pushParentIl = node.PushParentObjectsArray(context).ToList(); if (pushParentIl[pushParentIl.Count - 1].OpCode != Ldnull) { yield return Create(Dup); //Keep the serviceProvider on the stack - yield return Create(Ldtoken, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideValueTarget"))); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IProvideValueTarget"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); foreach (var instruction in pushParentIl) yield return instruction; - foreach (var instruction in PushTargetProperty(bpRef, propertyRef, declaringTypeReference, module)) + foreach (var instruction in PushTargetProperty(context, bpRef, propertyRef, declaringTypeReference, module)) yield return instruction; if (context.Scopes.TryGetValue(node, out var scope)) @@ -615,17 +594,17 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo else yield return Create(Ldnull); - yield return Create(Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "SimpleValueTargetProvider"), paramCount: 3)); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "SimpleValueTargetProvider"), paramCount: 3)); //store the provider so we can register it again with a different key yield return Create(Dup); - var refProvider = new VariableDefinition(module.ImportReference(("mscorlib", "System", "Object"))); + var refProvider = new VariableDefinition(module.ImportReference(context.Cache, ("mscorlib", "System", "Object"))); context.Body.Variables.Add(refProvider); yield return Create(Stloc, refProvider); yield return Create(Callvirt, addService); yield return Create(Dup); //Keep the serviceProvider on the stack - yield return Create(Ldtoken, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IReferenceProvider"))); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IReferenceProvider"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); yield return Create(Ldloc, refProvider); yield return Create(Callvirt, addService); } @@ -634,15 +613,15 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo if (node.NamespaceResolver != null) { yield return Create(Dup); //Duplicate the serviceProvider - yield return Create(Ldtoken, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXamlTypeResolver"))); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlNamespaceResolver"), parameterTypes: null)); + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXamlTypeResolver"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlNamespaceResolver"), parameterTypes: null)); foreach (var kvp in node.NamespaceResolver.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { yield return Create(Dup); //dup the resolver yield return Create(Ldstr, kvp.Key); yield return Create(Ldstr, kvp.Value); - yield return Create(Callvirt, module.ImportMethodReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlNamespaceResolver"), + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlNamespaceResolver"), methodName: "Add", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -650,20 +629,20 @@ public static IEnumerable PushServiceProvider(this INode node, ILCo })); } yield return Create(Ldtoken, context.Body.Method.DeclaringType); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Callvirt, module.ImportPropertyGetterReference(("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); - yield return Create(Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlTypeResolver"), paramCount: 2)); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Callvirt, module.ImportPropertyGetterReference(context.Cache, ("mscorlib", "System", "Type"), propertyName: "Assembly", flatten: true)); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XamlTypeResolver"), paramCount: 2)); yield return Create(Callvirt, addService); } if (node is IXmlLineInfo) { yield return Create(Dup); //Duplicate the serviceProvider - yield return Create(Ldtoken, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXmlLineInfoProvider"))); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); + yield return Create(Ldtoken, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IXmlLineInfoProvider"))); + yield return Create(Call, module.ImportMethodReference(context.Cache, ("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); foreach (var instruction in node.PushXmlLineInfo(context)) yield return instruction; - yield return Create(Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlLineInfoProvider"), parameterTypes: new[] { ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml.Internals", "XmlLineInfoProvider"), parameterTypes: new[] { ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); yield return Create(Callvirt, addService); } } diff --git a/src/Controls/src/Build.Tasks/SetFieldVisitor.cs b/src/Controls/src/Build.Tasks/SetFieldVisitor.cs index 0e269aa82e21..1155bc28675a 100644 --- a/src/Controls/src/Build.Tasks/SetFieldVisitor.cs +++ b/src/Controls/src/Build.Tasks/SetFieldVisitor.cs @@ -34,7 +34,7 @@ public void Visit(ValueNode node, INode parentNode) if (field == null) return; Context.IL.Emit(OpCodes.Ldarg_0); - Context.IL.Append(Context.Variables[(IElementNode)parentNode].LoadAs(field.FieldType, Context.Module)); + Context.IL.Append(Context.Variables[(IElementNode)parentNode].LoadAs(Context.Cache, field.FieldType, Context.Module)); Context.IL.Emit(OpCodes.Stfld, field); } diff --git a/src/Controls/src/Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs b/src/Controls/src/Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs index 0be7e55fbf19..2e8b09230506 100644 --- a/src/Controls/src/Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs +++ b/src/Controls/src/Build.Tasks/SetNamescopesAndRegisterNamesVisitor.cs @@ -57,7 +57,7 @@ public void Visit(ElementNode node, INode parentNode) namescopeVarDef = Context.Scopes[parentNode].Item1; namesInNamescope = Context.Scopes[parentNode].Item2; } - if (setNameScope && Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Body.Method.Module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) + if (setNameScope && Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Cache, Context.Body.Method.Module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) SetNameScope(node, namescopeVarDef); Context.Scopes[node] = new Tuple>(namescopeVarDef, namesInNamescope); } @@ -66,7 +66,7 @@ public void Visit(RootNode node, INode parentNode) { var namescopeVarDef = GetOrCreateNameScope(node); IList namesInNamescope = new List(); - if (Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Body.Method.Module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) + if (Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Cache, Context.Body.Method.Module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) SetNameScope(node, namescopeVarDef); Context.Scopes[node] = new System.Tuple>(namescopeVarDef, namesInNamescope); } @@ -89,15 +89,15 @@ static bool IsXNameProperty(ValueNode node, INode parentNode) VariableDefinition GetOrCreateNameScope(ElementNode node) { var module = Context.Body.Method.Module; - var vardef = new VariableDefinition(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"))); + var vardef = new VariableDefinition(module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"))); Context.Body.Variables.Add(vardef); var stloc = Instruction.Create(OpCodes.Stloc, vardef); - if (Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Body.Method.Module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) + if (Context.Variables[node].VariableType.InheritsFromOrImplements(Context.Cache, Context.Body.Method.Module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) { var namescoperef = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"); - Context.IL.Append(Context.Variables[node].LoadAs(module.GetTypeDefinition(namescoperef), module)); - Context.IL.Emit(OpCodes.Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), + Context.IL.Append(Context.Variables[node].LoadAs(Context.Cache, module.GetTypeDefinition(Context.Cache, namescoperef), module)); + Context.IL.Emit(OpCodes.Call, module.ImportMethodReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), methodName: "GetNameScope", parameterTypes: new[] { namescoperef }, isStatic: true)); @@ -106,7 +106,7 @@ VariableDefinition GetOrCreateNameScope(ElementNode node) Context.IL.Emit(OpCodes.Pop); } - Context.IL.Emit(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), parameterTypes: null)); + Context.IL.Emit(OpCodes.Newobj, module.ImportCtorReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), parameterTypes: null)); Context.IL.Append(stloc); return vardef; @@ -115,9 +115,9 @@ VariableDefinition GetOrCreateNameScope(ElementNode node) VariableDefinition CreateNamescope() { var module = Context.Body.Method.Module; - var vardef = new VariableDefinition(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"))); + var vardef = new VariableDefinition(module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"))); Context.Body.Variables.Add(vardef); - Context.IL.Emit(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), parameterTypes: null)); + Context.IL.Emit(OpCodes.Newobj, module.ImportCtorReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), parameterTypes: null)); Context.IL.Emit(OpCodes.Stloc, vardef); return vardef; } @@ -129,9 +129,9 @@ void SetNameScope(ElementNode node, VariableDefinition ns) ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"), ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "INameScope"), }; - Context.IL.Append(Context.Variables[node].LoadAs(module.GetTypeDefinition(parameterTypes[0]), module)); - Context.IL.Append(ns.LoadAs(module.GetTypeDefinition(parameterTypes[1]), module)); - Context.IL.Emit(OpCodes.Call, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), + Context.IL.Append(Context.Variables[node].LoadAs(Context.Cache, module.GetTypeDefinition(Context.Cache, parameterTypes[0]), module)); + Context.IL.Append(ns.LoadAs(Context.Cache, module.GetTypeDefinition(Context.Cache, parameterTypes[1]), module)); + Context.IL.Emit(OpCodes.Call, module.ImportMethodReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "NameScope"), methodName: "SetNameScope", parameterTypes: parameterTypes, isStatic: true)); @@ -145,10 +145,11 @@ void RegisterName(string str, VariableDefinition namescopeVarDef, IList var module = Context.Body.Method.Module; var namescopeType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "INameScope"); - Context.IL.Append(namescopeVarDef.LoadAs(module.GetTypeDefinition(namescopeType), module)); + Context.IL.Append(namescopeVarDef.LoadAs(Context.Cache, module.GetTypeDefinition(Context.Cache, namescopeType), module)); Context.IL.Emit(OpCodes.Ldstr, str); - Context.IL.Append(element.LoadAs(module.TypeSystem.Object, module)); - Context.IL.Emit(OpCodes.Callvirt, module.ImportMethodReference(namescopeType, + Context.IL.Append(element.LoadAs(Context.Cache, module.TypeSystem.Object, module)); + Context.IL.Emit(OpCodes.Callvirt, module.ImportMethodReference(Context.Cache, + namescopeType, methodName: "RegisterName", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -158,20 +159,20 @@ void RegisterName(string str, VariableDefinition namescopeVarDef, IList void SetStyleId(string str, VariableDefinition element) { - if (!element.VariableType.InheritsFromOrImplements(Context.Body.Method.Module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Element")))) + if (!element.VariableType.InheritsFromOrImplements(Context.Cache, Context.Body.Method.Module.ImportReference(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Element")))) return; var module = Context.Body.Method.Module; var elementType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "Element"); - var elementTypeRef = module.GetTypeDefinition(elementType); + var elementTypeRef = module.GetTypeDefinition(Context.Cache, elementType); var nop = Instruction.Create(OpCodes.Nop); - Context.IL.Append(element.LoadAs(elementTypeRef, module)); - Context.IL.Emit(OpCodes.Callvirt, module.ImportPropertyGetterReference(elementType, propertyName: "StyleId")); + Context.IL.Append(element.LoadAs(Context.Cache, elementTypeRef, module)); + Context.IL.Emit(OpCodes.Callvirt, module.ImportPropertyGetterReference(Context.Cache, elementType, propertyName: "StyleId")); Context.IL.Emit(OpCodes.Brtrue, nop); - Context.IL.Append(element.LoadAs(elementTypeRef, module)); + Context.IL.Append(element.LoadAs(Context.Cache, elementTypeRef, module)); Context.IL.Emit(OpCodes.Ldstr, str); - Context.IL.Emit(OpCodes.Callvirt, module.ImportPropertySetterReference(elementType, propertyName: "StyleId")); + Context.IL.Emit(OpCodes.Callvirt, module.ImportPropertySetterReference(Context.Cache, elementType, propertyName: "StyleId")); Context.IL.Append(nop); } } diff --git a/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs b/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs index fc18374a1b0d..311a630cbedf 100644 --- a/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs +++ b/src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs @@ -15,9 +15,6 @@ namespace Microsoft.Maui.Controls.Build.Tasks { class SetPropertiesVisitor : IXamlNodeVisitor { - static int dtcount; - static int typedBindingCount; - static readonly IList skips = new List { XmlName.xKey, @@ -63,7 +60,7 @@ public void Visit(ValueNode node, INode parentNode) if (!Context.Variables.ContainsKey((IElementNode)parentNode)) return; var parentVar = Context.Variables[(IElementNode)parentNode]; - if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null) + if ((contentProperty = GetContentProperty(Context.Cache, parentVar.VariableType)) != null) propertyName = new XmlName(((IElementNode)parentNode).NamespaceURI, contentProperty); else return; @@ -116,7 +113,7 @@ public void Visit(ElementNode node, INode parentNode) if (parentNode is IElementNode && propertyName != XmlName.Empty) { bpRef = GetBindablePropertyReference(Context.Variables[(IElementNode)parentNode], propertyName.NamespaceURI, ref localName, out _, Context, node); - propertyRef = Context.Variables[(IElementNode)parentNode].VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference); + propertyRef = Context.Variables[(IElementNode)parentNode].VariableType.GetProperty(Context.Cache, pd => pd.Name == localName, out declaringTypeReference); } Context.IL.Append(ProvideValue(vardefref, Context, Module, node, bpRef: bpRef, propertyRef: propertyRef, propertyDeclaringTypeRef: declaringTypeReference)); if (vardef != vardefref.VariableDefinition) @@ -142,10 +139,10 @@ public void Visit(ElementNode node, INode parentNode) if (CanAddToResourceDictionary(parentVar, parentVar.VariableType, node, node, Context)) { - Context.IL.Append(parentVar.LoadAs(Module.GetTypeDefinition(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), Module)); + Context.IL.Append(parentVar.LoadAs(Context.Cache, Module.GetTypeDefinition(Context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), Module)); Context.IL.Append(AddToResourceDictionary(parentVar, node, node, Context)); } - else if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null) + else if ((contentProperty = GetContentProperty(Context.Cache, parentVar.VariableType)) != null) { var name = new XmlName(node.NamespaceURI, contentProperty); if (skips.Contains(name)) @@ -155,16 +152,16 @@ public void Visit(ElementNode node, INode parentNode) Context.IL.Append(SetPropertyValue(Context.Variables[(IElementNode)parentNode], name, node, Context, node)); } // Collection element, implicit content, or implicit collection element. - else if (parentVar.VariableType.ImplementsInterface(Module.ImportReference(("mscorlib", "System.Collections", "IEnumerable"))) - && parentVar.VariableType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).Any()) + else if (parentVar.VariableType.ImplementsInterface(Context.Cache, Module.ImportReference(Context.Cache, ("mscorlib", "System.Collections", "IEnumerable"))) + && parentVar.VariableType.GetMethods(Context.Cache, md => md.Name == "Add" && md.Parameters.Count == 1, Module).Any()) { var elementType = parentVar.VariableType; - var adderTuple = elementType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).First(); + var adderTuple = elementType.GetMethods(Context.Cache, md => md.Name == "Add" && md.Parameters.Count == 1, Module).First(); var adderRef = Module.ImportReference(adderTuple.Item1); adderRef = Module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, Module)); Context.IL.Emit(Ldloc, parentVar); - Context.IL.Append(vardef.LoadAs(adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), Module)); + Context.IL.Append(vardef.LoadAs(Context.Cache, adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), Module)); Context.IL.Emit(Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") Context.IL.Emit(Pop); @@ -198,13 +195,13 @@ public void Visit(ElementNode node, INode parentNode) Context.IL.Append(AddToResourceDictionary(parent, node, node, Context)); return; } - var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).FirstOrDefault() ?? + var adderTuple = propertyType.GetMethods(Context.Cache, md => md.Name == "Add" && md.Parameters.Count == 1, Module).FirstOrDefault() ?? throw new BuildException(BuildExceptionCode.AdderMissing, node, null, parent.VariableType, localname); var adderRef = Module.ImportReference(adderTuple.Item1); adderRef = Module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, Module)); - Context.IL.Append(vardef.LoadAs(adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), Module)); + Context.IL.Append(vardef.LoadAs(Context.Cache, adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), Module)); Context.IL.Emit(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") Context.IL.Emit(OpCodes.Pop); @@ -241,9 +238,9 @@ static bool IsCollectionItem(INode node, INode parentNode) return parentList.CollectionItems.Contains(node); } - internal static string GetContentProperty(TypeReference typeRef) + internal static string GetContentProperty(XamlCache cache, TypeReference typeRef) { - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); var attributes = typeDef.CustomAttributes; var attr = attributes.FirstOrDefault(cad => ContentPropertyAttribute.ContentPropertyTypes.Contains(cad.AttributeType.FullName)); @@ -251,7 +248,7 @@ internal static string GetContentProperty(TypeReference typeRef) return attr.ConstructorArguments[0].Value as string; if (typeDef.BaseType == null) return null; - return GetContentProperty(typeDef.BaseType); + return GetContentProperty(cache, typeDef.BaseType); } public static IEnumerable ProvideValue(VariableDefinitionReference vardefref, ILContext context, @@ -261,10 +258,10 @@ internal static string GetContentProperty(TypeReference typeRef) GenericInstanceType markupExtension; IList genericArguments; if (vardefref.VariableDefinition.VariableType.FullName == "Microsoft.Maui.Controls.Xaml.ArrayExtension" && - vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Microsoft.Maui.Controls.Xaml.IMarkupExtension`1", + vardefref.VariableDefinition.VariableType.ImplementsGenericInterface(context.Cache, "Microsoft.Maui.Controls.Xaml.IMarkupExtension`1", out markupExtension, out genericArguments)) { - var markExt = markupExtension.ResolveCached(); + var markExt = markupExtension.ResolveCached(context.Cache); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.ImportReference(provideValueInfo); provideValue = @@ -276,7 +273,7 @@ internal static string GetContentProperty(TypeReference typeRef) vardefref.VariableDefinition = new VariableDefinition(module.ImportReference(arrayTypeRef.MakeArrayType())); else vardefref.VariableDefinition = new VariableDefinition(module.ImportReference(genericArguments.First())); - foreach (var instruction in context.Variables[node].LoadAs(markupExtension, module)) + foreach (var instruction in context.Variables[node].LoadAs(context.Cache, markupExtension, module)) yield return instruction; foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; @@ -286,10 +283,10 @@ internal static string GetContentProperty(TypeReference typeRef) yield return Instruction.Create(OpCodes.Castclass, module.ImportReference(arrayTypeRef.MakeArrayType())); yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition); } - else if (vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Microsoft.Maui.Controls.Xaml.IMarkupExtension`1", + else if (vardefref.VariableDefinition.VariableType.ImplementsGenericInterface(context.Cache, "Microsoft.Maui.Controls.Xaml.IMarkupExtension`1", out markupExtension, out genericArguments)) { - var acceptEmptyServiceProvider = vardefref.VariableDefinition.VariableType.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; + var acceptEmptyServiceProvider = vardefref.VariableDefinition.VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; if (vardefref.VariableDefinition.VariableType.FullName == "Microsoft.Maui.Controls.Xaml.BindingExtension" && (node.Properties == null || !node.Properties.ContainsKey(new XmlName("", "Source"))) //do not compile bindings if Source is set && bpRef != null //do not compile bindings if we're not gonna SetBinding @@ -297,14 +294,14 @@ internal static string GetContentProperty(TypeReference typeRef) foreach (var instruction in CompileBindingPath(node, context, vardefref.VariableDefinition)) yield return instruction; - var markExt = markupExtension.ResolveCached(); + var markExt = markupExtension.ResolveCached(context.Cache); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.ImportReference(provideValueInfo); provideValue = module.ImportReference(provideValue.ResolveGenericParameters(markupExtension, module)); vardefref.VariableDefinition = new VariableDefinition(module.ImportReference(genericArguments.First())); - foreach (var instruction in context.Variables[node].LoadAs(markupExtension, module)) + foreach (var instruction in context.Variables[node].LoadAs(context.Cache, markupExtension, module)) yield return instruction; if (acceptEmptyServiceProvider) yield return Instruction.Create(OpCodes.Ldnull); @@ -314,29 +311,30 @@ internal static string GetContentProperty(TypeReference typeRef) yield return Instruction.Create(OpCodes.Callvirt, provideValue); yield return Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition); } - else if (context.Variables[node].VariableType.ImplementsInterface(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IMarkupExtension")))) + else if (context.Variables[node].VariableType.ImplementsInterface(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IMarkupExtension")))) { - var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; + var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; var markupExtensionType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IMarkupExtension"); vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object); - foreach (var instruction in context.Variables[node].LoadAs(module.GetTypeDefinition(markupExtensionType), module)) + foreach (var instruction in context.Variables[node].LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, markupExtensionType), module)) yield return instruction; if (acceptEmptyServiceProvider) yield return Create(Ldnull); else foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; - yield return Create(Callvirt, module.ImportMethodReference(markupExtensionType, + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, + markupExtensionType, methodName: "ProvideValue", parameterTypes: new[] { ("System.ComponentModel", "System", "IServiceProvider") })); yield return Create(Stloc, vardefref.VariableDefinition); } - else if (context.Variables[node].VariableType.ImplementsInterface(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IValueProvider")))) + else if (context.Variables[node].VariableType.ImplementsInterface(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IValueProvider")))) { - var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; + var acceptEmptyServiceProvider = context.Variables[node].VariableType.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "AcceptEmptyServiceProviderAttribute")) != null; var valueProviderType = context.Variables[node].VariableType; //If the IValueProvider has a ProvideCompiledAttribute that can be resolved, shortcut this - var compiledValueProviderName = valueProviderType?.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?[0].Value as string; + var compiledValueProviderName = valueProviderType?.GetCustomAttribute(context.Cache, module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?[0].Value as string; Type compiledValueProviderType; if (compiledValueProviderName != null && (compiledValueProviderType = Type.GetType(compiledValueProviderName)) != null) { @@ -354,14 +352,15 @@ internal static string GetContentProperty(TypeReference typeRef) var valueProviderInterface = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "IValueProvider"); vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object); - foreach (var instruction in context.Variables[node].LoadAs(module.GetTypeDefinition(valueProviderInterface), module)) + foreach (var instruction in context.Variables[node].LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, valueProviderInterface), module)) yield return instruction; if (acceptEmptyServiceProvider) yield return Create(Ldnull); else foreach (var instruction in node.PushServiceProvider(context, bpRef, propertyRef, propertyDeclaringTypeRef)) yield return instruction; - yield return Create(Callvirt, module.ImportMethodReference(valueProviderInterface, + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, + valueProviderInterface, methodName: "ProvideValue", parameterTypes: new[] { ("System.ComponentModel", "System", "IServiceProvider") })); yield return Create(Stloc, vardefref.VariableDefinition); @@ -420,11 +419,11 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c var dtXType = new XmlType(namespaceuri, dataType, null); - var tSourceRef = dtXType.GetTypeReference(module, (IXmlLineInfo)node); + var tSourceRef = dtXType.GetTypeReference(context.Cache, module, (IXmlLineInfo)node); if (tSourceRef == null) yield break; //throw - var properties = ParsePath(path, tSourceRef, node as IXmlLineInfo, module); + var properties = ParsePath(context, path, tSourceRef, node as IXmlLineInfo, module); TypeReference tPropertyRef = tSourceRef; if (properties != null && properties.Count > 0) { @@ -432,24 +431,24 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c tPropertyRef = lastProp.property.PropertyType.ResolveGenericParameters(lastProp.propDeclTypeRef); } tPropertyRef = module.ImportReference(tPropertyRef); - var valuetupleRef = context.Module.ImportReference(module.ImportReference(("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); - var funcRef = module.ImportReference(module.ImportReference(("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, valuetupleRef })); - var actionRef = module.ImportReference(module.ImportReference(("mscorlib", "System", "Action`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); - var funcObjRef = module.ImportReference(module.ImportReference(("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); - var tupleRef = module.ImportReference(module.ImportReference(("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); - var typedBindingRef = module.ImportReference(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "TypedBinding`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); + var valuetupleRef = context.Module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); + var funcRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, valuetupleRef })); + var actionRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Action`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); + var funcObjRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); + var tupleRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); + var typedBindingRef = module.ImportReference(module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "TypedBinding`2")).MakeGenericInstanceType(new[] { tSourceRef, tPropertyRef })); //FIXME: make sure the non-deprecated one is used - var ctorInfo = module.ImportReference(typedBindingRef.ResolveCached().Methods.FirstOrDefault(md => + var ctorInfo = module.ImportReference(typedBindingRef.ResolveCached(context.Cache).Methods.FirstOrDefault(md => md.IsConstructor && !md.IsStatic && md.Parameters.Count == 3 - && !md.HasCustomAttributes(module.ImportReference(("mscorlib", "System", "ObsoleteAttribute"))))); + && !md.HasCustomAttributes(module.ImportReference(context.Cache, ("mscorlib", "System", "ObsoleteAttribute"))))); var ctorinforef = ctorInfo.MakeGeneric(typedBindingRef, funcRef, actionRef, tupleRef); var bindingExtensionType = ("Microsoft.Maui.Controls.Xaml", "Microsoft.Maui.Controls.Xaml", "BindingExtension"); - foreach (var instruction in bindingExt.LoadAs(module.GetTypeDefinition(bindingExtensionType), module)) + foreach (var instruction in bindingExt.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindingExtensionType), module)) yield return instruction; foreach (var instruction in CompiledBindingGetGetter(tSourceRef, tPropertyRef, properties, node, context)) yield return instruction; @@ -468,10 +467,10 @@ static IEnumerable CompileBindingPath(ElementNode node, ILContext c else yield return Create(Ldnull); yield return Create(Newobj, module.ImportReference(ctorinforef)); - yield return Create(Callvirt, module.ImportPropertySetterReference(bindingExtensionType, propertyName: "TypedBinding")); + yield return Create(Callvirt, module.ImportPropertySetterReference(context.Cache, bindingExtensionType, propertyName: "TypedBinding")); } - static IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> ParsePath(string path, TypeReference tSourceRef, IXmlLineInfo lineInfo, ModuleDefinition module) + static IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> ParsePath(ILContext context, string path, TypeReference tSourceRef, IXmlLineInfo lineInfo, ModuleDefinition module) { if (string.IsNullOrWhiteSpace(path)) return null; @@ -505,29 +504,32 @@ static IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string if (p.Length > 0) { - var property = previousPartTypeRef.GetProperty(pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic, out var propDeclTypeRef) + var property = previousPartTypeRef.GetProperty(context.Cache, pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic, out var propDeclTypeRef) ?? throw new BuildException(BuildExceptionCode.BindingPropertyNotFound, lineInfo, null, p, previousPartTypeRef); properties.Add((property, propDeclTypeRef, null)); previousPartTypeRef = property.PropertyType.ResolveGenericParameters(propDeclTypeRef); } if (indexArg != null) { - var defaultMemberAttribute = previousPartTypeRef.GetCustomAttribute(module, ("mscorlib", "System.Reflection", "DefaultMemberAttribute")); + var defaultMemberAttribute = previousPartTypeRef.GetCustomAttribute(context.Cache, module, ("mscorlib", "System.Reflection", "DefaultMemberAttribute")); var indexerName = defaultMemberAttribute?.ConstructorArguments?.FirstOrDefault().Value as string ?? "Item"; PropertyDefinition indexer = null; TypeReference indexerDeclTypeRef = null; if (int.TryParse(indexArg, out _)) - indexer = previousPartTypeRef.GetProperty(pd => pd.Name == indexerName + indexer = previousPartTypeRef.GetProperty(context.Cache, + pd => pd.Name == indexerName && pd.GetMethod != null - && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(("mscorlib", "System", "Int32"))) + && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(context.Cache, ("mscorlib", "System", "Int32"))) && pd.GetMethod.IsPublic, out indexerDeclTypeRef); - indexer = indexer ?? previousPartTypeRef.GetProperty(pd => pd.Name == indexerName + indexer = indexer ?? previousPartTypeRef.GetProperty(context.Cache, + pd => pd.Name == indexerName && pd.GetMethod != null - && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(("mscorlib", "System", "String"))) + && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(context.Cache, ("mscorlib", "System", "String"))) && pd.GetMethod.IsPublic, out indexerDeclTypeRef); - indexer = indexer ?? previousPartTypeRef.GetProperty(pd => pd.Name == indexerName + indexer = indexer ?? previousPartTypeRef.GetProperty(context.Cache, + pd => pd.Name == indexerName && pd.GetMethod != null - && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(("mscorlib", "System", "Object"))) + && TypeRefComparer.Default.Equals(pd.GetMethod.Parameters[0].ParameterType.ResolveGenericParameters(previousPartTypeRef), module.ImportReference(context.Cache, ("mscorlib", "System", "Object"))) && pd.GetMethod.IsPublic, out indexerDeclTypeRef); properties.Add((indexer, indexerDeclTypeRef, indexArg)); @@ -611,15 +613,15 @@ static IEnumerable CompiledBindingGetGetter(TypeReference tSourceRe // } var module = context.Module; - var tupleRef = module.ImportReference(module.ImportReference(("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); - var tupleCtorRef = module.ImportCtorReference(tupleRef, 2); + var tupleRef = module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean })); + var tupleCtorRef = module.ImportCtorReference(context.Cache, tupleRef, 2); tupleCtorRef = module.ImportReference(tupleCtorRef.ResolveGenericParameters(tupleRef, module)); - var getter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{typedBindingCount++}", + var getter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{context.Cache.TypedBindingCount++}", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, tupleRef) { Parameters = { new ParameterDefinition(tSourceRef) }, - CustomAttributes = { new CustomAttribute(module.ImportCtorReference(("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) } + CustomAttributes = { new CustomAttribute(module.ImportCtorReference(context.Cache, ("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) } }; getter.Body.InitLocals = true; @@ -679,7 +681,7 @@ static IEnumerable CompiledBindingGetGetter(TypeReference tSourceRe // IL_0301: newobj instance void class [mscorlib] System.Func`2>::'.ctor'(object, native int) yield return Create(Ldnull); yield return Create(Ldftn, getter); - yield return Create(Newobj, module.ImportCtorReference(("mscorlib", "System", "Func`2"), paramCount: 2, classArguments: new[] { tSourceRef, tupleRef })); + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("mscorlib", "System", "Func`2"), paramCount: 2, classArguments: new[] { tSourceRef, tupleRef })); } static IEnumerable CompiledBindingGetSetter(TypeReference tSourceRef, TypeReference tPropertyRef, IList<(PropertyDefinition property, TypeReference propDeclTypeRef, string indexArg)> properties, ElementNode node, ILContext context) @@ -702,7 +704,7 @@ static IEnumerable CompiledBindingGetSetter(TypeReference tSourceRe // } var module = context.Module; - var setter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{typedBindingCount++}", + var setter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{context.Cache.TypedBindingCount++}", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, module.TypeSystem.Void) { @@ -711,7 +713,7 @@ static IEnumerable CompiledBindingGetSetter(TypeReference tSourceRe new ParameterDefinition(tPropertyRef) }, CustomAttributes = { - new CustomAttribute (module.ImportCtorReference(("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) + new CustomAttribute (module.ImportCtorReference(context.Cache, ("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) } }; setter.Body.InitLocals = true; @@ -801,7 +803,7 @@ static IEnumerable CompiledBindingGetSetter(TypeReference tSourceRe // IL_002b: newobj instance void class [mscorlib]System.Action`2::'.ctor'(object, native int) yield return Create(Ldnull); yield return Create(Ldftn, setter); - yield return Create(Newobj, module.ImportCtorReference(("mscorlib", "System", "Action`2"), + yield return Create(Newobj, module.ImportCtorReference(context.Cache, ("mscorlib", "System", "Action`2"), paramCount: 2, classArguments: new[] { tSourceRef, tPropertyRef })); @@ -834,13 +836,13 @@ static IEnumerable CompiledBindingGetHandlers(TypeReference tSource for (int i = 0; i < properties.Count; i++) { var tuple = properties[i]; - var partGetter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{typedBindingCount++}", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, module.TypeSystem.Object) + var partGetter = new MethodDefinition($"<{context.Body.Method.Name}>typedBindingsM__{context.Cache.TypedBindingCount++}", MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, module.TypeSystem.Object) { Parameters = { new ParameterDefinition(tSourceRef) }, CustomAttributes = { - new CustomAttribute (module.ImportCtorReference(("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) + new CustomAttribute (module.ImportCtorReference(context.Cache, ("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)) } }; partGetter.Body.InitLocals = true; @@ -875,11 +877,11 @@ static IEnumerable CompiledBindingGetHandlers(TypeReference tSource partGetters.Add(partGetter); } - var funcObjRef = context.Module.ImportReference(module.ImportReference(("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); - var tupleRef = context.Module.ImportReference(module.ImportReference(("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); - var funcCtor = module.ImportReference(funcObjRef.ResolveCached().GetConstructors().First()); + var funcObjRef = context.Module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Func`2")).MakeGenericInstanceType(new[] { tSourceRef, module.TypeSystem.Object })); + var tupleRef = context.Module.ImportReference(module.ImportReference(context.Cache, ("mscorlib", "System", "Tuple`2")).MakeGenericInstanceType(new[] { funcObjRef, module.TypeSystem.String })); + var funcCtor = module.ImportReference(funcObjRef.ResolveCached(context.Cache).GetConstructors().First()); funcCtor = funcCtor.MakeGeneric(funcObjRef, new[] { tSourceRef, module.TypeSystem.Object }); - var tupleCtor = module.ImportReference(tupleRef.ResolveCached().GetConstructors().First()); + var tupleCtor = module.ImportReference(tupleRef.ResolveCached(context.Cache).GetConstructors().First()); tupleCtor = tupleCtor.MakeGeneric(tupleRef, new[] { funcObjRef, module.TypeSystem.String }); // IL_003a: ldc.i4.2 @@ -925,7 +927,7 @@ public static IEnumerable SetPropertyValue(VariableDefinition paren var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, out System.Boolean attached, context, iXmlLineInfo); //If the target is an event, connect - if (CanConnectEvent(parent, localName, valueNode, attached)) + if (CanConnectEvent(parent, localName, valueNode, attached, context)) return ConnectEvent(parent, localName, valueNode, iXmlLineInfo, context); //If Value is DynamicResource, SetDynamicResource @@ -978,7 +980,8 @@ static FieldReference GetBindablePropertyReference(VariableDefinition parent, st var bpOwnerType = parent.VariableType; attached = GetNameAndTypeRef(ref bpOwnerType, namespaceURI, ref localName, context, iXmlLineInfo); var name = $"{localName}Property"; - FieldDefinition bpDef = bpOwnerType.GetField(fd => fd.Name == name && + FieldDefinition bpDef = bpOwnerType.GetField(context.Cache, + fd => fd.Name == name && fd.IsStatic && (fd.IsPublic || fd.IsAssembly), out declaringTypeReference); if (bpDef == null) @@ -993,9 +996,9 @@ static FieldReference GetBindablePropertyReference(VariableDefinition parent, st return bpRef; } - static bool CanConnectEvent(VariableDefinition parent, string localName, INode valueNode, bool attached) + static bool CanConnectEvent(VariableDefinition parent, string localName, INode valueNode, bool attached, ILContext context) { - return !attached && valueNode is ValueNode && parent.VariableType.GetEvent(ed => ed.Name == localName, out _) != null; + return !attached && valueNode is ValueNode && parent.VariableType.GetEvent(context.Cache, ed => ed.Name == localName, out _) != null; } static IEnumerable ConnectEvent(VariableDefinition parent, string localName, INode valueNode, IXmlLineInfo iXmlLineInfo, ILContext context) @@ -1003,7 +1006,7 @@ static IEnumerable ConnectEvent(VariableDefinition parent, string l var elementType = parent.VariableType; var module = context.Body.Method.Module; TypeReference eventDeclaringTypeRef; - var eventinfo = elementType.GetEvent(ed => ed.Name == localName, out eventDeclaringTypeRef); + var eventinfo = elementType.GetEvent(context.Cache, ed => ed.Name == localName, out eventDeclaringTypeRef); var adder = module.ImportReference(eventinfo.AddMethod); adder = adder.ResolveGenericParameters(eventDeclaringTypeRef, module); @@ -1024,20 +1027,20 @@ static IEnumerable ConnectEvent(VariableDefinition parent, string l var declaringType = context.Body.Method.DeclaringType; while (declaringType.IsNested) declaringType = declaringType.DeclaringType; - var handler = declaringType.AllMethods().FirstOrDefault(md => + var handler = declaringType.AllMethods(context.Cache).FirstOrDefault(md => { if (md.methodDef.Name != value as string) return false; //check if the handler signature matches the Invoke signature; - var invoke = module.ImportReference(eventinfo.EventType.ResolveCached().GetMethods().First(eventmd => eventmd.Name == "Invoke")); + var invoke = module.ImportReference(eventinfo.EventType.ResolveCached(context.Cache).GetMethods().First(eventmd => eventmd.Name == "Invoke")); invoke = invoke.ResolveGenericParameters(eventinfo.EventType, module); - if (!md.methodDef.ReturnType.InheritsFromOrImplements(invoke.ReturnType) || invoke.Parameters.Count != md.methodDef.Parameters.Count) + if (!md.methodDef.ReturnType.InheritsFromOrImplements(context.Cache, invoke.ReturnType) || invoke.Parameters.Count != md.methodDef.Parameters.Count) return false; if (!invoke.ContainsGenericParameter) for (var i = 0; i < invoke.Parameters.Count; i++) - if (!invoke.Parameters[i].ParameterType.InheritsFromOrImplements(md.methodDef.Parameters[i].ParameterType)) + if (!invoke.Parameters[i].ParameterType.InheritsFromOrImplements(context.Cache, md.methodDef.Parameters[i].ParameterType)) return false; //TODO check generic parameters if any @@ -1050,7 +1053,7 @@ static IEnumerable ConnectEvent(VariableDefinition parent, string l throw new BuildException(MissingEventHandler, iXmlLineInfo, null, value, declaringType); //FIXME: eventually get the right ctor instead fo the First() one, just in case another one could exists (not even sure it's possible). - var ctor = module.ImportReference(eventinfo.EventType.ResolveCached().GetConstructors().First()); + var ctor = module.ImportReference(eventinfo.EventType.ResolveCached(context.Cache).GetConstructors().First()); ctor = ctor.ResolveGenericParameters(eventinfo.EventType, module); if (handler.methodDef.IsStatic) @@ -1060,7 +1063,7 @@ static IEnumerable ConnectEvent(VariableDefinition parent, string l else { if (context.Root is VariableDefinition) - foreach (var instruction in (context.Root as VariableDefinition).LoadAs(ctor.Parameters[0].ParameterType.ResolveGenericParameters(ctor), module)) + foreach (var instruction in (context.Root as VariableDefinition).LoadAs(context.Cache, ctor.Parameters[0].ParameterType.ResolveGenericParameters(ctor), module)) yield return instruction; else if (context.Root is FieldDefinition) { @@ -1104,13 +1107,14 @@ static IEnumerable SetDynamicResource(VariableDefinition parent, Fi var dynamicResourceType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "DynamicResource"); var dynamicResourceHandlerType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Internals", "IDynamicResourceHandler"); - foreach (var instruction in parent.LoadAs(module.GetTypeDefinition(dynamicResourceHandlerType), module)) + foreach (var instruction in parent.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, dynamicResourceHandlerType), module)) yield return instruction; yield return Create(Ldsfld, bpRef); - foreach (var instruction in context.Variables[elementNode].LoadAs(module.GetTypeDefinition(dynamicResourceType), module)) + foreach (var instruction in context.Variables[elementNode].LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, dynamicResourceType), module)) yield return instruction; - yield return Create(Callvirt, module.ImportPropertyGetterReference(dynamicResourceType, propertyName: "Key")); - yield return Create(Callvirt, module.ImportMethodReference(dynamicResourceHandlerType, + yield return Create(Callvirt, module.ImportPropertyGetterReference(context.Cache, dynamicResourceType, propertyName: "Key")); + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, + dynamicResourceHandlerType, methodName: "SetDynamicResource", parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableProperty"), @@ -1129,11 +1133,11 @@ static bool CanSetBinding(FieldReference bpRef, INode valueNode, ILContext conte if (!context.Variables.TryGetValue(valueNode as IElementNode, out VariableDefinition varValue)) return false; - var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindingBase")), module); + var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindingBase")), module); if (implicitOperator != null) return true; - return varValue.VariableType.InheritsFromOrImplements(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindingBase"))); + return varValue.VariableType.InheritsFromOrImplements(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindingBase"))); } static IEnumerable SetBinding(VariableDefinition parent, FieldReference bpRef, IElementNode elementNode, IXmlLineInfo iXmlLineInfo, ILContext context) @@ -1146,12 +1150,12 @@ static IEnumerable SetBinding(VariableDefinition parent, FieldRefer }; //TODO: check if parent is a BP - foreach (var instruction in parent.LoadAs(module.GetTypeDefinition(bindableObjectType), module)) + foreach (var instruction in parent.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindableObjectType), module)) yield return instruction; yield return Create(Ldsfld, bpRef); - foreach (var instruction in context.Variables[elementNode].LoadAs(module.GetTypeDefinition(parameterTypes[1]), module)) + foreach (var instruction in context.Variables[elementNode].LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, parameterTypes[1]), module)) yield return instruction; - yield return Create(Callvirt, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"), + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"), methodName: "SetBinding", parameterTypes: parameterTypes)); } @@ -1172,12 +1176,12 @@ static bool CanSetValue(FieldReference bpRef, bool attached, INode node, IXmlLin if (!context.Variables.TryGetValue(elementNode, out VariableDefinition varValue)) return false; - var bpTypeRef = bpRef.GetBindablePropertyType(iXmlLineInfo, module); + var bpTypeRef = bpRef.GetBindablePropertyType(context.Cache, iXmlLineInfo, module); // If it's an attached BP, there's no second chance to handle IMarkupExtensions, so we try here. // Worst case scenario ? InvalidCastException at runtime if (attached && varValue.VariableType.FullName == "System.Object") return true; - var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(bpTypeRef, module); + var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(context.Cache, bpTypeRef, module); if (implicitOperator != null) return true; @@ -1185,7 +1189,7 @@ static bool CanSetValue(FieldReference bpRef, bool attached, INode node, IXmlLin if (varValue.VariableType.IsValueType && bpTypeRef.FullName == "System.Object") return true; - return varValue.VariableType.InheritsFromOrImplements(bpTypeRef); + return varValue.VariableType.InheritsFromOrImplements(context.Cache, bpTypeRef); } static bool CanGetValue(VariableDefinition parent, FieldReference bpRef, bool attached, IXmlLineInfo iXmlLineInfo, ILContext context, out TypeReference propertyType) @@ -1196,10 +1200,10 @@ static bool CanGetValue(VariableDefinition parent, FieldReference bpRef, bool at if (bpRef == null) return false; - if (!parent.VariableType.InheritsFromOrImplements(module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) + if (!parent.VariableType.InheritsFromOrImplements(context.Cache, module.ImportReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject")))) return false; - propertyType = bpRef.GetBindablePropertyType(iXmlLineInfo, module); + propertyType = bpRef.GetBindablePropertyType(context.Cache, iXmlLineInfo, module); return true; } @@ -1215,7 +1219,7 @@ static IEnumerable SetValue(VariableDefinition parent, FieldReferen // IL_000d: ldstr "foo" // IL_0012: callvirt instance void class [Microsoft.Maui.Controls]Microsoft.Maui.Controls.BindableObject::SetValue(class [Microsoft.Maui.Controls]Microsoft.Maui.Controls.BindableProperty, object) - foreach (var instruction in parent.LoadAs(module.GetTypeDefinition(bindableObjectType), module)) + foreach (var instruction in parent.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindableObjectType), module)) yield return instruction; yield return Create(Ldsfld, bpRef); @@ -1227,13 +1231,14 @@ static IEnumerable SetValue(VariableDefinition parent, FieldReferen } else if (elementNode != null) { - var bpTypeRef = bpRef.GetBindablePropertyType(iXmlLineInfo, module); - foreach (var instruction in context.Variables[elementNode].LoadAs(bpTypeRef, module)) + var bpTypeRef = bpRef.GetBindablePropertyType(context.Cache, iXmlLineInfo, module); + foreach (var instruction in context.Variables[elementNode].LoadAs(context.Cache, bpTypeRef, module)) yield return instruction; if (bpTypeRef.IsValueType) yield return Create(Box, module.ImportReference(bpTypeRef)); } - yield return Create(Callvirt, module.ImportMethodReference(bindableObjectType, + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, + bindableObjectType, methodName: "SetValue", parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableProperty"), @@ -1243,7 +1248,7 @@ static IEnumerable SetValue(VariableDefinition parent, FieldReferen static IEnumerable GetValue(VariableDefinition parent, FieldReference bpRef, IXmlLineInfo iXmlLineInfo, ILContext context, out TypeReference propertyType) { - propertyType = bpRef.GetBindablePropertyType(iXmlLineInfo, context.Body.Method.Module); + propertyType = bpRef.GetBindablePropertyType(context.Cache, iXmlLineInfo, context.Body.Method.Module); return GetValue(parent, bpRef, iXmlLineInfo, context); } @@ -1252,11 +1257,12 @@ static IEnumerable GetValue(VariableDefinition parent, FieldReferen var module = context.Body.Method.Module; var bindableObjectType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableObject"); - foreach (var instruction in parent.LoadAs(module.GetTypeDefinition(bindableObjectType), module)) + foreach (var instruction in parent.LoadAs(context.Cache, module.GetTypeDefinition(context.Cache, bindableObjectType), module)) yield return instruction; yield return Create(Ldsfld, bpRef); - yield return Create(Callvirt, module.ImportMethodReference(bindableObjectType, + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, + bindableObjectType, methodName: "GetValue", parameterTypes: new[] { ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "BindableProperty") })); } @@ -1265,7 +1271,7 @@ static bool CanSet(VariableDefinition parent, string localName, INode node, ILCo { var module = context.Body.Method.Module; TypeReference declaringTypeReference; - var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference); + var property = parent.VariableType.GetProperty(context.Cache, pd => pd.Name == localName, out declaringTypeReference); if (property == null) return false; var propertyType = property.PropertyType.ResolveGenericParameters(declaringTypeReference); @@ -1274,7 +1280,7 @@ static bool CanSet(VariableDefinition parent, string localName, INode node, ILCo return false; var valueNode = node as ValueNode; - if (valueNode != null && valueNode.CanConvertValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached() })) + if (valueNode != null && valueNode.CanConvertValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached(context.Cache) })) return true; var elementNode = node as IElementNode; @@ -1282,9 +1288,9 @@ static bool CanSet(VariableDefinition parent, string localName, INode node, ILCo return false; var vardef = context.Variables[elementNode]; - var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module); + var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(context.Cache, propertyType, module); - if (vardef.VariableType.InheritsFromOrImplements(propertyType)) + if (vardef.VariableType.InheritsFromOrImplements(context.Cache, propertyType)) return true; if (implicitOperator != null) return true; @@ -1303,14 +1309,14 @@ static bool CanGet(VariableDefinition parent, string localName, ILContext contex var module = context.Body.Method.Module; propertyType = null; TypeReference declaringTypeReference; - var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference); + var property = parent.VariableType.GetProperty(context.Cache, pd => pd.Name == localName, out declaringTypeReference); if (property == null) return false; var propertyGetter = property.GetMethod; if (propertyGetter == null || !propertyGetter.IsPublic || propertyGetter.IsStatic) return false; - module.ImportReference(parent.VariableType.ResolveCached()); + module.ImportReference(parent.VariableType.ResolveCached(context.Cache)); var propertyGetterRef = module.ImportReference(module.ImportReference(propertyGetter).ResolveGenericParameters(declaringTypeReference, module)); propertyGetterRef.ImportTypes(module); propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference); @@ -1322,7 +1328,7 @@ static IEnumerable Set(VariableDefinition parent, string localName, { var module = context.Body.Method.Module; TypeReference declaringTypeReference; - var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference); + var property = parent.VariableType.GetProperty(context.Cache, pd => pd.Name == localName, out declaringTypeReference); var propertyIsObsolete = property.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.ObsoleteAttribute"); if (propertyIsObsolete) context.LoggingHelper.LogWarning("XamlC", null, null, context.XamlFilePath, iXmlLineInfo.LineNumber, iXmlLineInfo.LinePosition, 0, 0, $"Property {localName} is deprecated.", null); @@ -1336,7 +1342,7 @@ static IEnumerable Set(VariableDefinition parent, string localName, // IL_0008: ldstr "foo" // IL_000d: callvirt instance void class [Microsoft.Maui.Controls]Microsoft.Maui.Controls.Label::set_Text(string) - module.ImportReference(parent.VariableType.ResolveCached()); + module.ImportReference(parent.VariableType.ResolveCached(context.Cache)); var propertySetterRef = module.ImportReference(module.ImportReference(propertySetter).ResolveGenericParameters(declaringTypeReference, module)); propertySetterRef.ImportTypes(module); var propertyType = property.PropertyType.ResolveGenericParameters(declaringTypeReference); @@ -1351,7 +1357,7 @@ static IEnumerable Set(VariableDefinition parent, string localName, if (valueNode != null) { - foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached() }, valueNode.PushServiceProvider(context, propertyRef: property), false, true)) + foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.ResolveCached(context.Cache) }, valueNode.PushServiceProvider(context, propertyRef: property), false, true)) yield return instruction; if (parent.VariableType.IsValueType) yield return Instruction.Create(OpCodes.Call, propertySetterRef); @@ -1360,7 +1366,7 @@ static IEnumerable Set(VariableDefinition parent, string localName, } else if (elementNode != null) { - foreach (var instruction in context.Variables[elementNode].LoadAs(propertyType, module)) + foreach (var instruction in context.Variables[elementNode].LoadAs(context.Cache, propertyType, module)) yield return instruction; if (parent.VariableType.IsValueType) yield return Instruction.Create(OpCodes.Call, propertySetterRef); @@ -1372,10 +1378,10 @@ static IEnumerable Set(VariableDefinition parent, string localName, static IEnumerable Get(VariableDefinition parent, string localName, IXmlLineInfo iXmlLineInfo, ILContext context, out TypeReference propertyType) { var module = context.Body.Method.Module; - var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out var declaringTypeReference); + var property = parent.VariableType.GetProperty(context.Cache, pd => pd.Name == localName, out var declaringTypeReference); var propertyGetter = property.GetMethod; - module.ImportReference(parent.VariableType.ResolveCached()); + module.ImportReference(parent.VariableType.ResolveCached(context.Cache)); var propertyGetterRef = module.ImportReference(module.ImportReference(propertyGetter).ResolveGenericParameters(declaringTypeReference, module)); propertyGetterRef.ImportTypes(module); propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference); @@ -1408,7 +1414,7 @@ static bool CanAdd(VariableDefinition parent, XmlName propertyName, INode valueN if (!context.Variables.TryGetValue(elementNode, out VariableDefinition varValue)) return false; - var adderTuple = propertyType.GetMethods(md => md.Name == "Add" + var adderTuple = propertyType.GetMethods(context.Cache, md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault(); if (adderTuple == null) return false; @@ -1416,10 +1422,10 @@ static bool CanAdd(VariableDefinition parent, XmlName propertyName, INode valueN var adderRef = module.ImportReference(adderTuple.Item1); adderRef = module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, module)); var paramType = adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef); - if (varValue.VariableType.InheritsFromOrImplements(paramType)) + if (varValue.VariableType.InheritsFromOrImplements(context.Cache, paramType)) return true; - if (varValue.VariableType.GetImplicitOperatorTo(paramType, module) != null) + if (varValue.VariableType.GetImplicitOperatorTo(context.Cache, paramType, module) != null) return true; if (paramType.FullName == "System.Object" && varValue.VariableType.IsValueType) @@ -1428,19 +1434,17 @@ static bool CanAdd(VariableDefinition parent, XmlName propertyName, INode valueN return CanAddToResourceDictionary(parent, propertyType, elementNode, lineInfo, context); } - static Dictionary> resourceNamesInUse = new Dictionary>(); static bool CanAddToResourceDictionary(VariableDefinition parent, TypeReference collectionType, IElementNode node, IXmlLineInfo lineInfo, ILContext context) { if (collectionType.FullName != "Microsoft.Maui.Controls.ResourceDictionary" - && collectionType.ResolveCached().BaseType?.FullName != "Microsoft.Maui.Controls.ResourceDictionary") + && collectionType.ResolveCached(context.Cache).BaseType?.FullName != "Microsoft.Maui.Controls.ResourceDictionary") return false; if (node.Properties.ContainsKey(XmlName.xKey)) { var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null); var key = (valueNode).Value as string; - if (!resourceNamesInUse.TryGetValue(parent, out var names)) - resourceNamesInUse[parent] = (names = new List()); + var names = context.Cache.GetResourceNamesInUse(parent); if (names.Contains(key)) throw new BuildException(ResourceDictDuplicateKey, lineInfo, null, key); return true; @@ -1449,7 +1453,8 @@ static bool CanAddToResourceDictionary(VariableDefinition parent, TypeReference //is there a RD.Add() overrides that accepts this ? var nodeTypeRef = context.Variables[node].VariableType; var module = context.Body.Method.Module; - if (module.ImportMethodReference(module.GetTypeDefinition(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), + if (module.ImportMethodReference(context.Cache, + module.GetTypeDefinition(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary")), methodName: "Add", parameterTypes: new[] { (nodeTypeRef) }) != null) return true; @@ -1473,11 +1478,11 @@ static IEnumerable Add(VariableDefinition parent, XmlName propertyN yield break; } - var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault(); + var adderTuple = propertyType.GetMethods(context.Cache, md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault(); var adderRef = module.ImportReference(adderTuple.Item1); adderRef = module.ImportReference(adderRef.ResolveGenericParameters(adderTuple.Item2, module)); - foreach (var instruction in vardef.LoadAs(adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), module)) + foreach (var instruction in vardef.LoadAs(context.Cache, adderRef.Parameters[0].ParameterType.ResolveGenericParameters(adderRef), module)) yield return instruction; yield return Instruction.Create(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") @@ -1490,7 +1495,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren if (node.Properties.ContainsKey(XmlName.xKey)) { - var names = resourceNamesInUse[parent]; + var names = context.Cache.GetResourceNamesInUse(parent); var valueNode = node.Properties[XmlName.xKey] as ValueNode ?? throw new BuildException(XKeyNotLiteral, lineInfo, null); var key = (valueNode).Value as string; names.Add(key); @@ -1499,9 +1504,9 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren // IL_0019: ldstr "foo" // IL_001e: callvirt instance void class [Microsoft.Maui.Controls]Microsoft.Maui.Controls.ResourceDictionary::Add(string, object) yield return Create(Ldstr, (key)); - foreach (var instruction in context.Variables[node].LoadAs(module.TypeSystem.Object, module)) + foreach (var instruction in context.Variables[node].LoadAs(context.Cache, module.TypeSystem.Object, module)) yield return instruction; - yield return Create(Callvirt, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), methodName: "Add", parameterTypes: new[] { ("mscorlib", "System", "String"), @@ -1512,7 +1517,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren var nodeTypeRef = context.Variables[node].VariableType; yield return Create(Ldloc, context.Variables[node]); - yield return Create(Callvirt, module.ImportMethodReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), + yield return Create(Callvirt, module.ImportMethodReference(context.Cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"), methodName: "Add", parameterTypes: new[] { (nodeTypeRef.Scope.Name, nodeTypeRef.Namespace, nodeTypeRef.Name) })); yield break; @@ -1526,7 +1531,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren { var typename = localname.Substring(0, dotIdx); localname = localname.Substring(dotIdx + 1); - elementType = new XmlType(namespaceURI, typename, null).GetTypeReference(context.Body.Method.Module, lineInfo); + elementType = new XmlType(namespaceURI, typename, null).GetTypeReference(context.Cache, context.Body.Method.Module, lineInfo); return true; } return false; @@ -1539,7 +1544,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren var dataTemplateType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ElementTemplate"); var parentVar = parentContext.Variables[parentNode]; //Push the DataTemplate to the stack, for setting the template - parentContext.IL.Append(parentVar.LoadAs(module.GetTypeDefinition(dataTemplateType), module)); + parentContext.IL.Append(parentVar.LoadAs(parentContext.Cache, module.GetTypeDefinition(parentContext.Cache, dataTemplateType), module)); //Create nested class // .class nested private auto ansi sealed beforefieldinit '
c__AnonStorey0' @@ -1548,19 +1553,19 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren var anonType = new TypeDefinition( null, - "<" + parentContext.Body.Method.Name + ">_anonXamlCDataTemplate_" + dtcount++, + "<" + parentContext.Body.Method.Name + ">_anonXamlCDataTemplate_" + parentContext.Cache.DataTemplateCount++, TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed | TypeAttributes.NestedPrivate) { BaseType = module.TypeSystem.Object, CustomAttributes = { - new CustomAttribute (module.ImportCtorReference(("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)), + new CustomAttribute (module.ImportCtorReference(parentContext.Cache, ("mscorlib", "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"), parameterTypes: null)), } }; parentContext.Body.Method.DeclaringType.NestedTypes.Add(anonType); - var ctor = anonType.AddDefaultConstructor(); + var ctor = anonType.AddDefaultConstructor(parentContext.Cache); var loadTemplate = new MethodDefinition("LoadDataTemplate", MethodAttributes.Assembly | MethodAttributes.HideBySig, @@ -1568,7 +1573,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren loadTemplate.Body.InitLocals = true; anonType.Methods.Add(loadTemplate); - var parentValues = new FieldDefinition("parentValues", FieldAttributes.Assembly, module.ImportArrayReference(("mscorlib", "System", "Object"))); + var parentValues = new FieldDefinition("parentValues", FieldAttributes.Assembly, module.ImportArrayReference(parentContext.Cache, ("mscorlib", "System", "Object"))); anonType.Fields.Add(parentValues); TypeReference rootType = null; @@ -1585,7 +1590,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren //Fill the loadTemplate Body var templateIl = loadTemplate.Body.GetILProcessor(); templateIl.Emit(OpCodes.Nop); - var templateContext = new ILContext(templateIl, loadTemplate.Body, module, parentValues) + var templateContext = new ILContext(templateIl, loadTemplate.Body, module, parentContext.Cache, parentValues) { Root = root, XamlFilePath = parentContext.XamlFilePath, @@ -1596,7 +1601,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren node.Accept(new SetResourcesVisitor(templateContext), null); node.Accept(new SetPropertiesVisitor(templateContext, stopOnResourceDictionary: true), null); - templateIl.Append(templateContext.Variables[node].LoadAs(module.TypeSystem.Object, module)); + templateIl.Append(templateContext.Variables[node].LoadAs(parentContext.Cache, module.TypeSystem.Object, module)); templateIl.Emit(OpCodes.Ret); //Instanciate nested class @@ -1609,7 +1614,7 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren parentIl.Emit(OpCodes.Stfld, parentValues); parentIl.Emit(OpCodes.Dup); //Duplicate the nestedclass instance if (parentContext.Root is VariableDefinition) - parentIl.Append((parentContext.Root as VariableDefinition).LoadAs(module.TypeSystem.Object, module)); + parentIl.Append((parentContext.Root as VariableDefinition).LoadAs(parentContext.Cache, module.TypeSystem.Object, module)); else if (parentContext.Root is FieldDefinition) { parentIl.Emit(OpCodes.Ldarg_0); @@ -1621,11 +1626,11 @@ static IEnumerable AddToResourceDictionary(VariableDefinition paren //SetDataTemplate parentIl.Emit(Ldftn, loadTemplate); - parentIl.Emit(Newobj, module.ImportCtorReference(("mscorlib", "System", "Func`1"), + parentIl.Emit(Newobj, module.ImportCtorReference(parentContext.Cache, ("mscorlib", "System", "Func`1"), classArguments: new[] { ("mscorlib", "System", "Object") }, paramCount: 2)); - parentContext.IL.Emit(OpCodes.Callvirt, module.ImportPropertySetterReference(dataTemplateType, propertyName: "LoadTemplate")); + parentContext.IL.Emit(OpCodes.Callvirt, module.ImportPropertySetterReference(parentContext.Cache, dataTemplateType, propertyName: "LoadTemplate")); loadTemplate.Body.Optimize(); } @@ -1635,7 +1640,7 @@ bool TrySetRuntimeName(XmlName propertyName, VariableDefinition variableDefiniti if (propertyName != XmlName.xName) return false; - var attributes = variableDefinition.VariableType.ResolveCached() + var attributes = variableDefinition.VariableType.ResolveCached(Context.Cache) .CustomAttributes.Where(attribute => attribute.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.RuntimeNamePropertyAttribute").ToList(); if (!attributes.Any()) diff --git a/src/Controls/src/Build.Tasks/SetResourcesVisitor.cs b/src/Controls/src/Build.Tasks/SetResourcesVisitor.cs index b3b13f571b10..87c64bf45b2c 100644 --- a/src/Controls/src/Build.Tasks/SetResourcesVisitor.cs +++ b/src/Controls/src/Build.Tasks/SetResourcesVisitor.cs @@ -73,7 +73,7 @@ bool IsResourceDictionary(IElementNode node) { var parentVar = Context.Variables[(IElementNode)node]; return parentVar.VariableType.FullName == "Microsoft.Maui.Controls.ResourceDictionary" - || parentVar.VariableType.ResolveCached().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary"; + || parentVar.VariableType.ResolveCached(Context.Cache).BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary"; } public bool SkipChildren(INode node, INode parentNode) diff --git a/src/Controls/src/Build.Tasks/TypeDefinitionExtensions.cs b/src/Controls/src/Build.Tasks/TypeDefinitionExtensions.cs index 86b871dacd98..f4c84d297fbb 100644 --- a/src/Controls/src/Build.Tasks/TypeDefinitionExtensions.cs +++ b/src/Controls/src/Build.Tasks/TypeDefinitionExtensions.cs @@ -10,24 +10,24 @@ namespace Microsoft.Maui.Controls.Build.Tasks { static class TypeDefinitionExtensions { - public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType) + public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType, XamlCache cache) { var module = targetType.Module; - var parentType = module.ImportReference(("mscorlib", "System", "Object")); + var parentType = module.ImportReference(cache, ("mscorlib", "System", "Object")); - return AddDefaultConstructor(targetType, parentType); + return AddDefaultConstructor(targetType, cache, parentType); } - public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType, TypeReference parentType) + public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetType, XamlCache cache, TypeReference parentType) { var module = targetType.Module; - var voidType = module.ImportReference(("mscorlib", "System", "Void")); + var voidType = module.ImportReference(cache, ("mscorlib", "System", "Void")); var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; - var parentctor = module.ImportCtorReference(parentType, paramCount: 0) ?? module.ImportCtorReference(("mscorlib", "System", "Object"), parameterTypes: null); + var parentctor = module.ImportCtorReference(cache, parentType, paramCount: 0) ?? module.ImportCtorReference(cache, ("mscorlib", "System", "Object"), parameterTypes: null); var ctor = new MethodDefinition(".ctor", methodAttributes, voidType) { @@ -46,7 +46,7 @@ public static MethodDefinition AddDefaultConstructor(this TypeDefinition targetT return ctor; } - public static IEnumerable<(MethodDefinition methodDef, TypeReference declTypeRef)> AllMethods(this TypeDefinition self) + public static IEnumerable<(MethodDefinition methodDef, TypeReference declTypeRef)> AllMethods(this TypeDefinition self, XamlCache cache) { TypeReference selfTypeRef = self; while (self != null) @@ -54,7 +54,7 @@ public static IEnumerable<(MethodDefinition methodDef, TypeReference declTypeRef foreach (var md in self.Methods) yield return (md, selfTypeRef); selfTypeRef = self.BaseType; - self = self.BaseType?.ResolveCached(); + self = self.BaseType?.ResolveCached(cache); } } } diff --git a/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs b/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs index 1fce25cd52be..aa0c6bac6478 100644 --- a/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs +++ b/src/Controls/src/Build.Tasks/TypeReferenceExtensions.cs @@ -59,11 +59,11 @@ public int GetHashCode(TypeReference obj) static class TypeReferenceExtensions { - public static PropertyDefinition GetProperty(this TypeReference typeRef, Func predicate, + public static PropertyDefinition GetProperty(this TypeReference typeRef, XamlCache cache, Func predicate, out TypeReference declaringTypeRef) { declaringTypeRef = typeRef; - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); var properties = typeDef.Properties.Where(predicate); if (properties.Any()) return properties.Single(); @@ -71,7 +71,7 @@ static class TypeReferenceExtensions { foreach (var face in typeDef.Interfaces) { - var p = face.InterfaceType.ResolveGenericParameters(typeRef).GetProperty(predicate, out var interfaceDeclaringTypeRef); + var p = face.InterfaceType.ResolveGenericParameters(typeRef).GetProperty(cache, predicate, out var interfaceDeclaringTypeRef); if (p != null) { declaringTypeRef = interfaceDeclaringTypeRef; @@ -81,27 +81,27 @@ static class TypeReferenceExtensions } if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object") return null; - return typeDef.BaseType.ResolveGenericParameters(typeRef).GetProperty(predicate, out declaringTypeRef); + return typeDef.BaseType.ResolveGenericParameters(typeRef).GetProperty(cache, predicate, out declaringTypeRef); } - public static EventDefinition GetEvent(this TypeReference typeRef, Func predicate, + public static EventDefinition GetEvent(this TypeReference typeRef, XamlCache cache, Func predicate, out TypeReference declaringTypeRef) { declaringTypeRef = typeRef; - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); var events = typeDef.Events.Where(predicate); if (events.Any()) { var ev = events.Single(); - return ev.ResolveGenericEvent(declaringTypeRef); + return ev.ResolveGenericEvent(cache, declaringTypeRef); } if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object") return null; - return typeDef.BaseType.ResolveGenericParameters(typeRef).GetEvent(predicate, out declaringTypeRef); + return typeDef.BaseType.ResolveGenericParameters(typeRef).GetEvent(cache, predicate, out declaringTypeRef); } //this resolves generic eventargs (https://bugzilla.xamarin.com/show_bug.cgi?id=57574) - static EventDefinition ResolveGenericEvent(this EventDefinition eventDef, TypeReference declaringTypeRef) + static EventDefinition ResolveGenericEvent(this EventDefinition eventDef, XamlCache cache, TypeReference declaringTypeRef) { if (eventDef == null) throw new ArgumentNullException(nameof(eventDef)); @@ -109,7 +109,7 @@ static EventDefinition ResolveGenericEvent(this EventDefinition eventDef, TypeRe throw new ArgumentNullException(nameof(declaringTypeRef)); if (!eventDef.EventType.IsGenericInstance) return eventDef; - if (eventDef.EventType.ResolveCached().FullName != "System.EventHandler`1") + if (eventDef.EventType.ResolveCached(cache).FullName != "System.EventHandler`1") return eventDef; var git = eventDef.EventType as GenericInstanceType; @@ -121,37 +121,37 @@ static EventDefinition ResolveGenericEvent(this EventDefinition eventDef, TypeRe return eventDef; } - public static FieldDefinition GetField(this TypeReference typeRef, Func predicate, + public static FieldDefinition GetField(this TypeReference typeRef, XamlCache cache, Func predicate, out TypeReference declaringTypeRef) { declaringTypeRef = typeRef; - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); var bp = typeDef.Fields.Where (predicate); if (bp.Any()) return bp.Single(); if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object") return null; - return typeDef.BaseType.ResolveGenericParameters(typeRef).GetField(predicate, out declaringTypeRef); + return typeDef.BaseType.ResolveGenericParameters(typeRef).GetField(cache, predicate, out declaringTypeRef); } - public static bool ImplementsInterface(this TypeReference typeRef, TypeReference @interface) + public static bool ImplementsInterface(this TypeReference typeRef, XamlCache cache, TypeReference @interface) { - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); if (typeDef.Interfaces.Any(tr => tr.InterfaceType.FullName == @interface.FullName)) return true; var baseTypeRef = typeDef.BaseType; if (baseTypeRef != null && baseTypeRef.FullName != "System.Object") - return baseTypeRef.ImplementsInterface(@interface); + return baseTypeRef.ImplementsInterface(cache, @interface); return false; } - public static bool ImplementsGenericInterface(this TypeReference typeRef, string @interface, + public static bool ImplementsGenericInterface(this TypeReference typeRef, XamlCache cache, string @interface, out GenericInstanceType interfaceReference, out IList genericArguments) { interfaceReference = null; genericArguments = null; - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); InterfaceImplementation iface; if ((iface = typeDef.Interfaces.FirstOrDefault(tr => tr.InterfaceType.FullName.StartsWith(@interface, StringComparison.Ordinal) && @@ -163,7 +163,7 @@ public static bool ImplementsInterface(this TypeReference typeRef, TypeReference } var baseTypeRef = typeDef.BaseType; if (baseTypeRef != null && baseTypeRef.FullName != "System.Object") - return baseTypeRef.ResolveGenericParameters(typeRef).ImplementsGenericInterface(@interface, out interfaceReference, out genericArguments); + return baseTypeRef.ResolveGenericParameters(typeRef).ImplementsGenericInterface(cache, @interface, out interfaceReference, out genericArguments); return false; } @@ -184,26 +184,26 @@ public static bool ImplementsInterface(this TypeReference typeRef, TypeReference "System.Collections.Generic.IReadOnlyList`1", }; - public static bool InheritsFromOrImplements(this TypeReference typeRef, TypeReference baseClass) + public static bool InheritsFromOrImplements(this TypeReference typeRef, XamlCache cache, TypeReference baseClass) { if (typeRef is GenericInstanceType genericInstance) { if (baseClass is GenericInstanceType genericInstanceBaseClass && TypeRefComparer.Default.Equals(genericInstance.ElementType, genericInstanceBaseClass.ElementType)) { - foreach (var parameter in genericInstanceBaseClass.ElementType.ResolveCached().GenericParameters) + foreach (var parameter in genericInstanceBaseClass.ElementType.ResolveCached(cache).GenericParameters) { var argument = genericInstance.GenericArguments[parameter.Position]; var baseClassArgument = genericInstanceBaseClass.GenericArguments[parameter.Position]; if (parameter.IsCovariant) { - if (!argument.InheritsFromOrImplements(baseClassArgument)) + if (!argument.InheritsFromOrImplements(cache, baseClassArgument)) return false; } else if (parameter.IsContravariant) { - if (!baseClassArgument.InheritsFromOrImplements(argument)) + if (!baseClassArgument.InheritsFromOrImplements(cache, argument)) return false; } else if (!TypeRefComparer.Default.Equals(argument, baseClassArgument)) @@ -223,11 +223,11 @@ public static bool InheritsFromOrImplements(this TypeReference typeRef, TypeRefe if (typeRef.IsArray) { var array = (ArrayType)typeRef; - var arrayType = typeRef.ResolveCached(); + var arrayType = typeRef.ResolveCached(cache); if (arrayInterfaces.Contains(baseClass.FullName)) return true; if (array.IsVector && //generic interfaces are not implemented on multidimensional arrays - arrayGenericInterfaces.Contains(baseClass.ResolveCached().FullName) && + arrayGenericInterfaces.Contains(baseClass.ResolveCached(cache).FullName) && baseClass.IsGenericInstance && TypeRefComparer.Default.Equals((baseClass as GenericInstanceType).GenericArguments[0], arrayType)) return true; @@ -240,44 +240,44 @@ public static bool InheritsFromOrImplements(this TypeReference typeRef, TypeRefe if (typeRef.FullName == "System.Object") return false; - var typeDef = typeRef.ResolveCached(); - if (typeDef.Interfaces.Any(ir => ir.InterfaceType.ResolveGenericParameters(typeRef).InheritsFromOrImplements(baseClass))) + var typeDef = typeRef.ResolveCached(cache); + if (typeDef.Interfaces.Any(ir => ir.InterfaceType.ResolveGenericParameters(typeRef).InheritsFromOrImplements(cache, baseClass))) return true; if (typeDef.BaseType == null) return false; typeRef = typeDef.BaseType.ResolveGenericParameters(typeRef); - return typeRef.InheritsFromOrImplements(baseClass); + return typeRef.InheritsFromOrImplements(cache, baseClass); } - static CustomAttribute GetCustomAttribute(this TypeReference typeRef, TypeReference attribute) + static CustomAttribute GetCustomAttribute(this TypeReference typeRef, XamlCache cache, TypeReference attribute) { - var typeDef = typeRef.ResolveCached(); + var typeDef = cache.Resolve(typeRef); //FIXME: avoid string comparison. make sure the attribute TypeRef is the same one var attr = typeDef.CustomAttributes.SingleOrDefault(ca => ca.AttributeType.FullName == attribute.FullName); if (attr != null) return attr; var baseTypeRef = typeDef.BaseType; if (baseTypeRef != null && baseTypeRef.FullName != "System.Object") - return baseTypeRef.GetCustomAttribute(attribute); + return baseTypeRef.GetCustomAttribute(cache, attribute); return null; } - public static CustomAttribute GetCustomAttribute(this TypeReference typeRef, ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) attributeType) + public static CustomAttribute GetCustomAttribute(this TypeReference typeRef, XamlCache cache, ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) attributeType) { - return typeRef.GetCustomAttribute(module.ImportReference(attributeType)); + return typeRef.GetCustomAttribute(cache, module.ImportReference(cache, attributeType)); } - public static IEnumerable> GetMethods(this TypeReference typeRef, + public static IEnumerable> GetMethods(this TypeReference typeRef, XamlCache cache, Func predicate, ModuleDefinition module) { - return typeRef.GetMethods((md, tr) => predicate(md), module); + return typeRef.GetMethods(cache, (md, tr) => predicate(md), module); } - public static IEnumerable> GetMethods(this TypeReference typeRef, + public static IEnumerable> GetMethods(this TypeReference typeRef, XamlCache cache, Func predicate, ModuleDefinition module) { - var typeDef = typeRef.ResolveCached(); + var typeDef = typeRef.ResolveCached(cache); foreach (var method in typeDef.Methods.Where(md => predicate(md, typeRef))) yield return new Tuple(method, typeRef); if (typeDef.IsInterface) @@ -290,7 +290,7 @@ public static CustomAttribute GetCustomAttribute(this TypeReference typeRef, Mod foreach (var arg in ((GenericInstanceType)typeRef).GenericArguments) ((GenericInstanceType)face.InterfaceType).GenericArguments[i++] = module.ImportReference(arg); } - foreach (var tuple in face.InterfaceType.GetMethods(predicate, module)) + foreach (var tuple in face.InterfaceType.GetMethods(cache, predicate, module)) yield return tuple; } yield break; @@ -298,20 +298,20 @@ public static CustomAttribute GetCustomAttribute(this TypeReference typeRef, Mod if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object") yield break; var baseType = typeDef.BaseType.ResolveGenericParameters(typeRef); - foreach (var tuple in baseType.GetMethods(predicate, module)) + foreach (var tuple in baseType.GetMethods(cache, predicate, module)) yield return tuple; } - public static MethodReference GetImplicitOperatorTo(this TypeReference fromType, TypeReference toType, ModuleDefinition module) + public static MethodReference GetImplicitOperatorTo(this TypeReference fromType, XamlCache cache, TypeReference toType, ModuleDefinition module) { if (TypeRefComparer.Default.Equals(fromType, toType)) return null; - var implicitOperatorsOnFromType = fromType.GetMethods(md => md.IsPublic + var implicitOperatorsOnFromType = fromType.GetMethods(cache, md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit", module); - var implicitOperatorsOnToType = toType.GetMethods(md => md.IsPublic + var implicitOperatorsOnToType = toType.GetMethods(cache, md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit", module); @@ -327,10 +327,10 @@ public static MethodReference GetImplicitOperatorTo(this TypeReference fromType, var returnType = castDef.ReturnType; if (returnType.IsGenericParameter) returnType = ((GenericInstanceType)opDeclTypeRef).GenericArguments[((GenericParameter)returnType).Position]; - if (!returnType.InheritsFromOrImplements(toType)) + if (!returnType.InheritsFromOrImplements(cache, toType)) continue; var paramType = cast.Parameters[0].ParameterType.ResolveGenericParameters(castDef); - if (!fromType.InheritsFromOrImplements(paramType)) + if (!fromType.InheritsFromOrImplements(cache, paramType)) continue; return castDef; } @@ -421,12 +421,6 @@ public static GenericInstanceType ResolveGenericParameters(this GenericInstanceT return self.ElementType.MakeGenericInstanceType(args.ToArray()); } - static Dictionary resolves = new Dictionary(); - public static TypeDefinition ResolveCached(this TypeReference typeReference) - { - if (resolves.TryGetValue(typeReference, out var typeDefinition)) - return typeDefinition; - return (resolves[typeReference] = typeReference.Resolve()); - } + public static TypeDefinition ResolveCached(this TypeReference typeReference, XamlCache cache) => cache.Resolve(typeReference); } } diff --git a/src/Controls/src/Build.Tasks/VariableDefinitionExtensions.cs b/src/Controls/src/Build.Tasks/VariableDefinitionExtensions.cs index 67c608bae072..b99f2848d834 100644 --- a/src/Controls/src/Build.Tasks/VariableDefinitionExtensions.cs +++ b/src/Controls/src/Build.Tasks/VariableDefinitionExtensions.cs @@ -6,13 +6,13 @@ namespace Microsoft.Maui.Controls.Build.Tasks { static class VariableDefinitionExtensions { - public static IEnumerable LoadAs(this VariableDefinition self, TypeReference type, ModuleDefinition module) + public static IEnumerable LoadAs(this VariableDefinition self, XamlCache cache, TypeReference type, ModuleDefinition module) { - var implicitOperator = self.VariableType.GetImplicitOperatorTo(type, module); + var implicitOperator = self.VariableType.GetImplicitOperatorTo(cache, type, module); yield return Instruction.Create(OpCodes.Ldloc, self); - if (!self.VariableType.InheritsFromOrImplements(type) && implicitOperator != null) + if (!self.VariableType.InheritsFromOrImplements(cache, type) && implicitOperator != null) yield return Instruction.Create(OpCodes.Call, module.ImportReference(implicitOperator)); else if (self.VariableType.IsValueType && !type.IsValueType) yield return Instruction.Create(OpCodes.Box, module.ImportReference(self.VariableType)); diff --git a/src/Controls/src/Build.Tasks/XamlCTask.cs b/src/Controls/src/Build.Tasks/XamlCTask.cs index 865d6e6d925c..9aead7dd5609 100644 --- a/src/Controls/src/Build.Tasks/XamlCTask.cs +++ b/src/Controls/src/Build.Tasks/XamlCTask.cs @@ -16,6 +16,7 @@ namespace Microsoft.Maui.Controls.Build.Tasks { public class XamlCTask : XamlTask { + readonly XamlCache cache = new(); bool hasCompiledXamlResources; public bool KeepXamlResources { get; set; } public bool OptimizeIL { get; set; } = true; @@ -110,7 +111,7 @@ public override bool Execute(out IList thrownExceptions) { LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); string classname; - if (!resource.IsXaml(module, out classname)) + if (!resource.IsXaml(cache, module, out classname)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}skipped."); continue; @@ -260,11 +261,11 @@ bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string xamlF var module = body.Method.Module; body.InitLocals = true; var il = body.GetILProcessor(); - var resourcePath = GetPathForType(module, initComp.DeclaringType); + var resourcePath = GetPathForType(cache, module, initComp.DeclaringType); il.Emit(Nop); - var visitorContext = new ILContext(il, body, module) + var visitorContext = new ILContext(il, body, module, cache) { XamlFilePath = xamlFilePath, LoggingHelper = loggingHelper, @@ -293,11 +294,11 @@ bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string xamlF } } - internal static string GetPathForType(ModuleDefinition module, TypeReference type) + internal static string GetPathForType(XamlCache cache, ModuleDefinition module, TypeReference type) { foreach (var ca in type.Module.GetCustomAttributes()) { - if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) + if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) continue; if (!TypeRefComparer.Default.Equals(ca.ConstructorArguments[2].Value as TypeReference, type)) continue; @@ -306,11 +307,11 @@ internal static string GetPathForType(ModuleDefinition module, TypeReference typ return null; } - internal static string GetResourceIdForPath(ModuleDefinition module, string path) + internal static string GetResourceIdForPath(XamlCache cache, ModuleDefinition module, string path) { foreach (var ca in module.GetCustomAttributes()) { - if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) + if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) continue; if (ca.ConstructorArguments[1].Value as string != path) continue; diff --git a/src/Controls/src/Build.Tasks/XamlCache.cs b/src/Controls/src/Build.Tasks/XamlCache.cs new file mode 100644 index 000000000000..080e1ab5c60e --- /dev/null +++ b/src/Controls/src/Build.Tasks/XamlCache.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using Microsoft.Maui.Controls.XamlC; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace Microsoft.Maui.Controls.Build.Tasks; + +/// +/// Class for caching various Mono.Cecil objects +/// +class XamlCache +{ + readonly Dictionary> _xmlnsDefinitions = new(); + readonly Dictionary _resolvedTypes = new(); + readonly Dictionary<(ModuleDefinition module, string fieldRefKey), FieldReference> _fieldReferenceCache = new(); + readonly Dictionary<(ModuleDefinition module, string typeKey), TypeReference> _typeReferenceCache = new(); + readonly Dictionary<(ModuleDefinition module, string methodRefKey), MethodReference> _methodReferenceCache = new(); + readonly Dictionary<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition> _typeDefinitionCache = new(); + readonly Dictionary> _resourceNamesInUse = new(); + Dictionary _knownCompiledTypeConverters; + + static TValue GetOrAdd(Dictionary dictionary, TKey key, Func valueFactory) + { + if (!dictionary.TryGetValue (key, out TValue value)) + { + value = dictionary[key] = valueFactory(key); + } + return value; + } + + public IList GetXmlsDefinitions(ModuleDefinition module, Func> valueFactory) => + GetOrAdd(_xmlnsDefinitions, module, valueFactory); + + public TypeDefinition Resolve(TypeReference typeReference) => + GetOrAdd(_resolvedTypes, typeReference, t => t.Resolve()); + + public FieldReference GetOrAddFieldReference((ModuleDefinition module, string fieldRefKey) key, Func<(ModuleDefinition module, string fieldRefKey), FieldReference> valueFactory) => + GetOrAdd(_fieldReferenceCache, key, valueFactory); + + public TypeReference GetOrAddTypeReference(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type) => + GetOrAdd(_typeReferenceCache, (module, type.ToString()), x => x.module.ImportReference(x.module.GetTypeDefinition(this, type))); + + public TypeReference GetOrAddTypeReference(ModuleDefinition module, string typeKey, Func<(ModuleDefinition module, string typeKey), TypeReference> valueFactory) => + GetOrAdd(_typeReferenceCache, (module, typeKey), valueFactory); + + public MethodReference GetOrAddMethodReference(ModuleDefinition module, string methodRefKey, Func<(ModuleDefinition module, string methodRefKey), MethodReference> valueFactory) => + GetOrAdd(_methodReferenceCache, (module, methodRefKey), valueFactory); + + public TypeDefinition GetOrAddTypeDefinition(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName) type, Func<(ModuleDefinition module, (string assemblyName, string clrNamespace, string typeName)), TypeDefinition> valueFactory) => + GetOrAdd(_typeDefinitionCache, (module, type), valueFactory); + + public ICollection GetResourceNamesInUse(VariableDefinition variableDefinition) => + GetOrAdd(_resourceNamesInUse, variableDefinition, _ => new HashSet(StringComparer.Ordinal)); + + public Dictionary GetKnownCompiledTypeConverters(ModuleDefinition module) => _knownCompiledTypeConverters ??= new(TypeRefComparer.Default) + { + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "ThicknessTypeConverter")), typeof(ThicknessTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "CornerRadiusTypeConverter")), typeof(CornerRadiusTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "EasingTypeConverter")), typeof(EasingTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "ColorTypeConverter")), typeof(ColorTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "PointTypeConverter")), typeof(PointTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "RectTypeConverter")), typeof(RectangleTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexJustifyTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexDirectionTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignContentTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignItemsTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignSelfTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexWrapTypeConverter")), typeof(EnumTypeConverter) }, + { module.ImportReference(this, ("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexBasisTypeConverter")), typeof(FlexBasisTypeConverter) }, + }; + + // State used by SetPropertiesVisitor + public int DataTemplateCount { get; set; } + public int TypedBindingCount { get; set; } +} diff --git a/src/Controls/src/Build.Tasks/XamlTask.cs b/src/Controls/src/Build.Tasks/XamlTask.cs index cdde1c7213b6..31b3f7073709 100644 --- a/src/Controls/src/Build.Tasks/XamlTask.cs +++ b/src/Controls/src/Build.Tasks/XamlTask.cs @@ -14,7 +14,6 @@ namespace Microsoft.Maui.Controls.Build.Tasks { - [LoadInSeparateAppDomain] public abstract class XamlTask : MarshalByRefObject, ITask { [Required] @@ -68,7 +67,7 @@ internal static ILRootNode ParseXaml(Stream stream, TypeReference typeReference) static class CecilExtensions { - public static bool IsXaml(this EmbeddedResource resource, ModuleDefinition module, out string classname) + public static bool IsXaml(this EmbeddedResource resource, XamlCache cache, ModuleDefinition module, out string classname) { classname = null; if (!resource.Name.EndsWith(".xaml", StringComparison.InvariantCulture)) @@ -91,7 +90,7 @@ public static bool IsXaml(this EmbeddedResource resource, ModuleDefinition modul //no x:Class, but it might be a RD without x:Class and with //in that case, it has a XamlResourceIdAttribute - var typeRef = GetTypeForResourceId(module, resource.Name); + var typeRef = GetTypeForResourceId(cache, module, resource.Name); if (typeRef != null) { classname = typeRef.FullName; @@ -102,11 +101,11 @@ public static bool IsXaml(this EmbeddedResource resource, ModuleDefinition modul } } - static TypeReference GetTypeForResourceId(ModuleDefinition module, string resourceId) + static TypeReference GetTypeForResourceId(XamlCache cache, ModuleDefinition module, string resourceId) { foreach (var ca in module.GetCustomAttributes()) { - if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) + if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference(cache, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "XamlResourceIdAttribute")))) continue; if (ca.ConstructorArguments[0].Value as string != resourceId) continue; diff --git a/src/Controls/src/Build.Tasks/XmlTypeExtensions.cs b/src/Controls/src/Build.Tasks/XmlTypeExtensions.cs index 2de0d1819acd..f7e661d3d453 100644 --- a/src/Controls/src/Build.Tasks/XmlTypeExtensions.cs +++ b/src/Controls/src/Build.Tasks/XmlTypeExtensions.cs @@ -10,10 +10,6 @@ namespace Microsoft.Maui.Controls.Build.Tasks { static class XmlTypeExtensions { - static Dictionary> s_xmlnsDefinitions = - new Dictionary>(); - static object _nsLock = new object(); - static IList GatherXmlnsDefinitionAttributes(ModuleDefinition module) { var xmlnsDefinitions = new List(); @@ -51,11 +47,10 @@ static IList GatherXmlnsDefinitionAttributes(ModuleDef } } - s_xmlnsDefinitions[module] = xmlnsDefinitions; return xmlnsDefinitions; } - public static TypeReference GetTypeReference(string xmlType, ModuleDefinition module, BaseNode node) + public static TypeReference GetTypeReference(XamlCache cache, string xmlType, ModuleDefinition module, BaseNode node) { var split = xmlType.Split(':'); if (split.Length > 2) @@ -73,40 +68,35 @@ public static TypeReference GetTypeReference(string xmlType, ModuleDefinition mo name = split[0]; } var namespaceuri = node.NamespaceResolver.LookupNamespace(prefix) ?? ""; - return GetTypeReference(new XmlType(namespaceuri, name, null), module, node as IXmlLineInfo); + return GetTypeReference(new XmlType(namespaceuri, name, null), cache, module, node as IXmlLineInfo); } - public static TypeReference GetTypeReference(string namespaceURI, string typename, ModuleDefinition module, IXmlLineInfo xmlInfo) + public static TypeReference GetTypeReference(XamlCache cache, string namespaceURI, string typename, ModuleDefinition module, IXmlLineInfo xmlInfo) { - return new XmlType(namespaceURI, typename, null).GetTypeReference(module, xmlInfo); + return new XmlType(namespaceURI, typename, null).GetTypeReference(cache, module, xmlInfo); } - public static bool TryGetTypeReference(this XmlType xmlType, ModuleDefinition module, IXmlLineInfo xmlInfo, out TypeReference typeReference) + public static bool TryGetTypeReference(this XmlType xmlType, XamlCache cache, ModuleDefinition module, IXmlLineInfo xmlInfo, out TypeReference typeReference) { - IList xmlnsDefinitions = null; - lock (_nsLock) - { - if (!s_xmlnsDefinitions.TryGetValue(module, out xmlnsDefinitions)) - xmlnsDefinitions = GatherXmlnsDefinitionAttributes(module); - } + IList xmlnsDefinitions = cache.GetXmlsDefinitions(module, GatherXmlnsDefinitionAttributes); var typeArguments = xmlType.TypeArguments; TypeReference type = xmlType.GetTypeReference(xmlnsDefinitions, module.Assembly.Name.Name, (typeInfo) => { string typeName = typeInfo.typeName.Replace('+', '/'); //Nested types - return module.GetTypeDefinition((typeInfo.assemblyName, typeInfo.clrNamespace, typeName)); + return module.GetTypeDefinition(cache, (typeInfo.assemblyName, typeInfo.clrNamespace, typeName)); }); if (type != null && typeArguments != null && type.HasGenericParameters) - type = module.ImportReference(type).MakeGenericInstanceType(typeArguments.Select(x => GetTypeReference(x, module, xmlInfo)).ToArray()); + type = module.ImportReference(type).MakeGenericInstanceType(typeArguments.Select(x => x.GetTypeReference(cache, module, xmlInfo)).ToArray()); return (typeReference = (type == null) ? null : module.ImportReference(type)) != null; } - public static TypeReference GetTypeReference(this XmlType xmlType, ModuleDefinition module, IXmlLineInfo xmlInfo) + public static TypeReference GetTypeReference(this XmlType xmlType, XamlCache cache, ModuleDefinition module, IXmlLineInfo xmlInfo) { - if (TryGetTypeReference(xmlType, module, xmlInfo, out TypeReference typeReference)) + if (TryGetTypeReference(xmlType, cache, module, xmlInfo, out TypeReference typeReference)) return typeReference; throw new BuildException(BuildExceptionCode.TypeResolution, xmlInfo, null, $"{xmlType.NamespaceUri}:{xmlType.Name}"); diff --git a/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs index 50192c935199..eaa080ebb284 100644 --- a/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/CecilExtensionsTests.cs @@ -78,7 +78,7 @@ EmbeddedResource GetResource(string name) public void IsXamlTrue(string name) { var resource = GetResource(name); - Assert.IsTrue(resource.IsXaml(assembly.MainModule, out string className), $"IsXaml should return true for '{name}'."); + Assert.IsTrue(resource.IsXaml(new XamlCache(), assembly.MainModule, out string className), $"IsXaml should return true for '{name}'."); Assert.AreEqual(className, $"{testNamespace}.{name}"); // Test cases x:Class matches the file name } @@ -92,7 +92,7 @@ public void IsXamlTrue(string name) public void IsXamlFalse(string name) { var resource = GetResource(name); - Assert.IsFalse(resource.IsXaml(assembly.MainModule, out _), $"IsXaml should return false for '{name}'."); + Assert.IsFalse(resource.IsXaml(new XamlCache(), assembly.MainModule, out _), $"IsXaml should return false for '{name}'."); } } } diff --git a/src/Controls/tests/Xaml.UnitTests/LoaderTests.cs b/src/Controls/tests/Xaml.UnitTests/LoaderTests.cs index 0d08b81f2a86..4ad6d3d0376f 100644 --- a/src/Controls/tests/Xaml.UnitTests/LoaderTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/LoaderTests.cs @@ -800,7 +800,7 @@ public void BindingIsResolvedAsBindingExtension() AssemblyResolver = new MockAssemblyResolver(), Kind = ModuleKind.Dll, }); - var bindingTypeRef = new XmlType("http://schemas.microsoft.com/dotnet/2021/maui", "Binding", null).GetTypeReference(module, null); + var bindingTypeRef = new XmlType("http://schemas.microsoft.com/dotnet/2021/maui", "Binding", null).GetTypeReference(new XamlCache(), module, null); Assert.That(bindingType.FullName, Is.EqualTo("Microsoft.Maui.Controls.Xaml.BindingExtension")); } } diff --git a/src/Controls/tests/Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs index 89a3aeb213b6..8598d18eba64 100644 --- a/src/Controls/tests/Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/XamlC/FieldReferenceExtensionsTests.cs @@ -49,7 +49,7 @@ public void ResolveGenericsOnNonGenericDoesNotThrow() { var type = module.ImportReference(typeof(NonGenericClass)); TypeReference declaringTypeReference; - FieldDefinition field = type.GetField(fd => fd.Name == "Field", out declaringTypeReference); + FieldDefinition field = type.GetField(new XamlCache(), fd => fd.Name == "Field", out declaringTypeReference); Assert.DoesNotThrow(() => field.ResolveGenericParameters(declaringTypeReference)); } @@ -58,7 +58,7 @@ public void NonGenericFieldOnGenericType() { var type = module.ImportReference(typeof(Inheritor)); TypeReference declaringTypeReference; - FieldDefinition field = type.GetField(fd => fd.Name == "NonGenericField", out declaringTypeReference); + FieldDefinition field = type.GetField(new XamlCache(), fd => fd.Name == "NonGenericField", out declaringTypeReference); Assert.AreEqual("NonGenericField", field.Name); Assert.AreEqual("Microsoft.Maui.Controls.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field.DeclaringType.FullName); Assert.False(field.DeclaringType.IsGenericInstance); @@ -71,10 +71,11 @@ public void NonGenericFieldOnGenericType() [Test] public void GenericFieldOnGenericType() { + var cache = new XamlCache(); var type = module.ImportReference(typeof(Inheritor)); TypeReference declaringTypeReference; - FieldDefinition field1 = type.GetField(fd => fd.Name == "GenericField1", out declaringTypeReference); + FieldDefinition field1 = type.GetField(cache, fd => fd.Name == "GenericField1", out declaringTypeReference); Assert.AreEqual("GenericField1", field1.Name); Assert.AreEqual("Microsoft.Maui.Controls.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field1.DeclaringType.FullName); Assert.False(field1.DeclaringType.IsGenericInstance); @@ -88,7 +89,7 @@ public void GenericFieldOnGenericType() Assert.False(genericField1.FieldType.IsGenericParameter); Assert.AreEqual("System.String", genericField1.FieldType.FullName); - FieldDefinition field2 = type.GetField(fd => fd.Name == "GenericField2", out declaringTypeReference); + FieldDefinition field2 = type.GetField(cache, fd => fd.Name == "GenericField2", out declaringTypeReference); Assert.AreEqual("GenericField2", field2.Name); Assert.AreEqual("Microsoft.Maui.Controls.XamlcUnitTests.FieldReferenceExtensionsTests/GenericClass`2", field2.DeclaringType.FullName); Assert.False(field2.DeclaringType.IsGenericInstance); diff --git a/src/Controls/tests/Xaml.UnitTests/XamlC/MethodDefinitionExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/XamlC/MethodDefinitionExtensionsTests.cs index 234aa9716adf..c639e191ec83 100644 --- a/src/Controls/tests/Xaml.UnitTests/XamlC/MethodDefinitionExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/XamlC/MethodDefinitionExtensionsTests.cs @@ -47,21 +47,22 @@ public void TearDown() [Test] public void ResolveGenericReturnType() { + var cache = new XamlCache(); var type = module.ImportReference(typeof(GenericClass)); - var getter = type.GetMethods(md => md.Name == "NonGeneric", module).Single(); + var getter = type.GetMethods(cache, md => md.Name == "NonGeneric", module).Single(); var returnType = getter.Item1.ResolveGenericReturnType(getter.Item2, module); Assert.AreEqual("System.Object", returnType.FullName); - getter = type.GetMethods(md => md.Name == "GenericT", module).Single(); + getter = type.GetMethods(cache, md => md.Name == "GenericT", module).Single(); returnType = getter.Item1.ResolveGenericReturnType(getter.Item2, module); Assert.AreEqual("System.Boolean", returnType.FullName); - getter = type.GetMethods(md => md.Name == "GenericU", module).Single(); + getter = type.GetMethods(cache, md => md.Name == "GenericU", module).Single(); returnType = getter.Item1.ResolveGenericReturnType(getter.Item2, module); Assert.AreEqual("System.String", returnType.FullName); - getter = type.GetMethods(md => md.Name == "GenericV", module).Single(); + getter = type.GetMethods(cache, md => md.Name == "GenericV", module).Single(); returnType = getter.Item1.ResolveGenericReturnType(getter.Item2, module); Assert.AreEqual("System.Int32", returnType.FullName); } diff --git a/src/Controls/tests/Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs index 500d95ee4d46..9bb3cea6b1c6 100644 --- a/src/Controls/tests/Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/XamlC/MethodReferenceExtensionsTests.cs @@ -39,7 +39,7 @@ public void TearDown() public void ResolveRowDefAdder() { var propertyType = module.ImportReference(typeof(RowDefinitionCollection)); - var adderT = propertyType.GetMethods((md, tr) => md.Name == "Add", module).Single(); + var adderT = propertyType.GetMethods(new XamlCache(), (md, tr) => md.Name == "Add", module).Single(); var adder = adderT.Item1; var ptype = adderT.Item2; Assert.AreEqual("System.Void Microsoft.Maui.Controls.DefinitionCollection`1::Add(T)", adder.FullName); @@ -55,7 +55,7 @@ public void GenericGetter() { TypeReference declaringTypeReference; var type = module.ImportReference(typeof(Compatibility.StackLayout)); - var property = type.GetProperty(pd => pd.Name == "Children", out declaringTypeReference); + var property = type.GetProperty(new XamlCache(), pd => pd.Name == "Children", out declaringTypeReference); Assert.AreEqual("System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Compatibility.Layout`1::Children()", property.FullName); Assert.AreEqual("Microsoft.Maui.Controls.Compatibility.Layout`1", declaringTypeReference.FullName); var propertyGetter = property.GetMethod; @@ -74,7 +74,7 @@ public void GetterWithGenericReturnType() { TypeReference declaringTypeReference; var type = module.ImportReference(typeof(Style)); - var property = type.GetProperty(pd => pd.Name == "Setters", out declaringTypeReference); + var property = type.GetProperty(new XamlCache(), pd => pd.Name == "Setters", out declaringTypeReference); Assert.AreEqual("System.Collections.Generic.IList`1 Microsoft.Maui.Controls.Style::Setters()", property.FullName); Assert.AreEqual("Microsoft.Maui.Controls.Style", declaringTypeReference.FullName); var propertyGetter = property.GetMethod; @@ -92,7 +92,7 @@ public void GetterWithGenericReturnType() public void ResolveChildren() { var propertyType = module.ImportReference(typeof(IList)); - var adderT = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).Single(); + var adderT = propertyType.GetMethods(new XamlCache(), md => md.Name == "Add" && md.Parameters.Count == 1, module).Single(); var adder = adderT.Item1; var ptype = adderT.Item2; Assert.AreEqual("System.Void System.Collections.Generic.ICollection`1::Add(T)", adder.FullName); diff --git a/src/Controls/tests/Xaml.UnitTests/XamlC/ModuleDefinitionExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/XamlC/ModuleDefinitionExtensionsTests.cs index 4f43ed1c4ac8..62811f699a52 100644 --- a/src/Controls/tests/Xaml.UnitTests/XamlC/ModuleDefinitionExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/XamlC/ModuleDefinitionExtensionsTests.cs @@ -2,6 +2,7 @@ using Microsoft.Maui.Controls.Build.Tasks; using Mono.Cecil; using NUnit.Framework; +using NUnit.Framework.Constraints; namespace Microsoft.Maui.Controls.XamlcUnitTests { @@ -46,11 +47,12 @@ public void TearDown() [Test] public void TestImportCtorReferenceWithGenericInstanceCtorParameter() { + var cache = new XamlCache(); var type = module.ImportReference(typeof(WithGenericInstanceCtorParameter)); var byteTuple = module.ImportReference(typeof(Tuple)); - var byteTupleCtor = module.ImportCtorReference(type, new[] { byteTuple }); + var byteTupleCtor = module.ImportCtorReference(cache, type, new[] { byteTuple }); var int16Tuple = module.ImportReference(typeof(Tuple)); - var int16TupleCtor = module.ImportCtorReference(type, new[] { int16Tuple }); + var int16TupleCtor = module.ImportCtorReference(cache, type, new[] { int16Tuple }); Assert.AreEqual("System.Tuple`1", byteTupleCtor.Parameters[0].ParameterType.FullName); Assert.AreEqual("System.Tuple`1", int16TupleCtor.Parameters[0].ParameterType.FullName); @@ -59,10 +61,11 @@ public void TestImportCtorReferenceWithGenericInstanceCtorParameter() [Test] public void TestImportCtorReferenceWithGenericInstanceTypeParameter() { + var cache = new XamlCache(); var byteTuple = module.ImportReference(typeof(Tuple)); - var byteTupleCtor = module.ImportCtorReference(("mscorlib", "System", "Tuple`1"), 1, new[] { byteTuple }); + var byteTupleCtor = module.ImportCtorReference(cache, ("mscorlib", "System", "Tuple`1"), 1, new[] { byteTuple }); var in16Tuple = module.ImportReference(typeof(Tuple)); - var int16TupleCtor = module.ImportCtorReference(("mscorlib", "System", "Tuple`1"), 1, new[] { in16Tuple }); + var int16TupleCtor = module.ImportCtorReference(cache, ("mscorlib", "System", "Tuple`1"), 1, new[] { in16Tuple }); Assert.AreEqual("System.Tuple`1", ((GenericInstanceType)byteTupleCtor.DeclaringType).GenericArguments[0].FullName); Assert.AreEqual("System.Tuple`1", ((GenericInstanceType)int16TupleCtor.DeclaringType).GenericArguments[0].FullName); diff --git a/src/Controls/tests/Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs b/src/Controls/tests/Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs index e861e67e7b92..a6ed1e9f0d1b 100644 --- a/src/Controls/tests/Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs +++ b/src/Controls/tests/Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs @@ -175,7 +175,7 @@ public void OneTimeTearDown() [TestCase(typeof(Covariant), typeof(ICovariant), ExpectedResult = true)] public bool TestInheritsFromOrImplements(Type typeRef, Type baseClass) { - return TypeReferenceExtensions.InheritsFromOrImplements(module.ImportReference(typeRef), module.ImportReference(baseClass)); + return TypeReferenceExtensions.InheritsFromOrImplements(module.ImportReference(typeRef), new XamlCache(), module.ImportReference(baseClass)); } [Test] @@ -242,7 +242,7 @@ public void TestImplementsGenericInterface() IList arguments; var garply = module.ImportReference(typeof(Garply)); - Assert.That(garply.ImplementsGenericInterface("Microsoft.Maui.Controls.XamlcUnitTests.TypeReferenceExtensionsTests/IGrault`1", out igrault, out arguments)); + Assert.That(garply.ImplementsGenericInterface(new XamlCache(), "Microsoft.Maui.Controls.XamlcUnitTests.TypeReferenceExtensionsTests/IGrault`1", out igrault, out arguments)); Assert.AreEqual("System", igrault.GenericArguments[0].Namespace); Assert.AreEqual("Byte", igrault.GenericArguments[0].Name);