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);