diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml index be134deadc..347e6b3b08 100644 --- a/api/Avalonia.nupkg.xml +++ b/api/Avalonia.nupkg.xml @@ -7,6 +7,48 @@ baseline/netstandard2.0/Avalonia.Base.dll target/netstandard2.0/Avalonia.Base.dll + + CP0001 + T:Avalonia.Data.Core.CastTypePropertyPathElement + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.ChildTraversalPropertyPathElement + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.EnsureTypePropertyPathElement + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.IPropertyPathElement + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.PropertyPath + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.PropertyPathBuilder + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + + + CP0001 + T:Avalonia.Data.Core.PropertyPropertyPathElement + baseline/netstandard2.0/Avalonia.Base.dll + target/netstandard2.0/Avalonia.Base.dll + CP0001 T:Avalonia.Utilities.CharacterReader diff --git a/src/Avalonia.Base/Data/Core/PropertyPath.cs b/src/Avalonia.Base/Data/Core/PropertyPath.cs deleted file mode 100644 index f5b3f92353..0000000000 --- a/src/Avalonia.Base/Data/Core/PropertyPath.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Avalonia.Data.Core -{ - public class PropertyPath - { - public IReadOnlyList Elements { get; } - - public PropertyPath(IEnumerable elements) - { - Elements = elements.ToArray(); - } - } - - public class PropertyPathBuilder - { - readonly List _elements = new List(); - - public PropertyPathBuilder Property(IPropertyInfo property) - { - _elements.Add(new PropertyPropertyPathElement(property)); - return this; - } - - - public PropertyPathBuilder ChildTraversal() - { - _elements.Add(new ChildTraversalPropertyPathElement()); - return this; - } - - public PropertyPathBuilder EnsureType(Type type) - { - _elements.Add(new EnsureTypePropertyPathElement(type)); - return this; - } - - public PropertyPathBuilder Cast(Type type) - { - _elements.Add(new CastTypePropertyPathElement(type)); - return this; - } - - public PropertyPath Build() - { - return new PropertyPath(_elements); - } - } - - public interface IPropertyPathElement - { - - } - - public class PropertyPropertyPathElement : IPropertyPathElement - { - public IPropertyInfo Property { get; } - - public PropertyPropertyPathElement(IPropertyInfo property) - { - Property = property; - } - } - - public class ChildTraversalPropertyPathElement : IPropertyPathElement - { - - } - - public class EnsureTypePropertyPathElement : IPropertyPathElement - { - public Type Type { get; } - - public EnsureTypePropertyPathElement(Type type) - { - Type = type; - } - } - - public class CastTypePropertyPathElement : IPropertyPathElement - { - public CastTypePropertyPathElement(Type type) - { - Type = type; - } - - public Type Type { get; } - } -} diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs index 4fec398c95..e0225a24f7 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs @@ -60,7 +60,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions new AvaloniaXamlIlDuplicateSettersChecker(), new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(), new AvaloniaXamlIlBindingPathParser(), - new AvaloniaXamlIlPropertyPathTransformer(), new AvaloniaXamlIlSetterTargetTypeMetadataTransformer(), new AvaloniaXamlIlSetterTransformer(), new AvaloniaXamlIlStyleValidatorTransformer(), diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs deleted file mode 100644 index 27413b386a..0000000000 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs +++ /dev/null @@ -1,262 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Avalonia.Markup.Parsers; -using XamlX; -using XamlX.Ast; -using XamlX.Transform; -using XamlX.Transform.Transformers; -using XamlX.TypeSystem; -using XamlX.Emit; -using XamlX.IL; - -namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers -{ - class XamlPropertyPathException : XamlTransformException - { - public XamlPropertyPathException(string message, IXamlLineInfo lineInfo, Exception? innerException = null) - : base(message, lineInfo, innerException) - { - } - } - - class AvaloniaXamlIlPropertyPathTransformer : IXamlAstTransformer - { - public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node) - { - if (node is XamlAstXamlPropertyValueNode pv - && pv.Values.Count == 1 - && pv.Values[0] is XamlAstTextNode text - && pv.Property.GetClrProperty().Getter?.ReturnType - .Equals(context.GetAvaloniaTypes().PropertyPath) == true - ) - { - var parentScope = context.ParentNodes().OfType() - .FirstOrDefault(); - if(parentScope == null) - throw new XamlPropertyPathException("No target type scope found for property path", text); - if (parentScope.ScopeType != AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style) - throw new XamlPropertyPathException("PropertyPath is currently only valid for styles", pv); - - - IEnumerable parsed; - try - { - parsed = PropertyPathGrammar.Parse(text.Text); - } - catch (Exception e) - { - throw new XamlPropertyPathException("Unable to parse PropertyPath: " + e.Message, text, innerException: e); - } - - var elements = new List(); - var currentType = parentScope.TargetType.GetClrType(); - - - var expectProperty = true; - var expectCast = true; - var expectTraversal = false; - var types = context.GetAvaloniaTypes(); - - IXamlType GetType(string? ns, string name) - { - return TypeReferenceResolver.ResolveType(context, $"{ns}:{name}", false, - text, true).GetClrType(); - } - - void HandleProperty(string name, string? typeNamespace, string? typeName) - { - if(!expectProperty || currentType == null) - throw new XamlPropertyPathException("Unexpected property node", text); - - var propertySearchType = - typeName != null ? GetType(typeNamespace, typeName) : currentType; - - IXamlIlPropertyPathElementNode? prop = null; - var avaloniaPropertyFieldName = name + "Property"; - var avaloniaPropertyField = propertySearchType.GetAllFields().FirstOrDefault(f => - f.IsStatic && f.IsPublic && f.Name == avaloniaPropertyFieldName); - if (avaloniaPropertyField != null) - { - prop = new XamlIlAvaloniaPropertyPropertyPathElementNode(avaloniaPropertyField, - XamlIlAvaloniaPropertyHelper.GetAvaloniaPropertyType(avaloniaPropertyField, types, text)); - } - else - { - var clrProperty = propertySearchType.GetAllProperties().FirstOrDefault(p => p.Name == name); - if (clrProperty is not null) - prop = new XamlIClrPropertyPathElementNode(clrProperty); - } - - if (prop == null) - throw new XamlPropertyPathException( - $"Unable to resolve property {name} on type {propertySearchType.GetFqn()}", - text); - - currentType = prop.Type; - elements.Add(prop); - expectProperty = false; - expectTraversal = expectCast = true; - } - - foreach (var ge in parsed) - { - if (ge is PropertyPathGrammar.ChildTraversalSyntax) - { - if (!expectTraversal) - throw new XamlPropertyPathException("Unexpected child traversal .", text); - elements.Add(new XamlIlChildTraversalPropertyPathElementNode()); - expectTraversal = expectCast = false; - expectProperty = true; - } - else if (ge is PropertyPathGrammar.EnsureTypeSyntax ets) - { - if(!expectCast) - throw new XamlPropertyPathException("Unexpected cast node", text); - currentType = GetType(ets.TypeNamespace, ets.TypeName); - elements.Add(new XamlIlCastPropertyPathElementNode(currentType, true)); - expectProperty = false; - expectCast = expectTraversal = true; - } - else if (ge is PropertyPathGrammar.CastTypeSyntax cts) - { - if(!expectCast) - throw new XamlPropertyPathException("Unexpected cast node", text); - //TODO: Check if cast can be done - currentType = GetType(cts.TypeNamespace, cts.TypeName); - elements.Add(new XamlIlCastPropertyPathElementNode(currentType, false)); - expectProperty = false; - expectCast = expectTraversal = true; - } - else if (ge is PropertyPathGrammar.PropertySyntax ps) - { - HandleProperty(ps.Name, null, null); - } - else if (ge is PropertyPathGrammar.TypeQualifiedPropertySyntax tqps) - { - HandleProperty(tqps.Name, tqps.TypeNamespace, tqps.TypeName); - } - else - throw new XamlPropertyPathException("Unexpected node " + ge, text); - - } - var propertyPathNode = new XamlIlPropertyPathNode(text, elements, types); - if (propertyPathNode.Type == null) - throw new XamlPropertyPathException("Unexpected end of the property path", text); - pv.Values[0] = propertyPathNode; - } - - return node; - } - - interface IXamlIlPropertyPathElementNode - { - void Emit(XamlEmitContext context, IXamlILEmitter codeGen); - IXamlType? Type { get; } - } - - class XamlIlChildTraversalPropertyPathElementNode : IXamlIlPropertyPathElementNode - { - public void Emit(XamlEmitContext context, IXamlILEmitter codeGen) - => codeGen.EmitCall( - context.GetAvaloniaTypes() - .PropertyPathBuilder.GetMethod(m => m.Name == "ChildTraversal")); - - public IXamlType? Type => null; - } - - class XamlIlAvaloniaPropertyPropertyPathElementNode : IXamlIlPropertyPathElementNode - { - private readonly IXamlField _field; - - public XamlIlAvaloniaPropertyPropertyPathElementNode(IXamlField field, IXamlType propertyType) - { - _field = field; - Type = propertyType; - } - - public void Emit(XamlEmitContext context, IXamlILEmitter codeGen) - => codeGen - .Ldsfld(_field) - .EmitCall(context.GetAvaloniaTypes() - .PropertyPathBuilder.GetMethod(m => m.Name == "Property")); - - public IXamlType Type { get; } - } - - class XamlIClrPropertyPathElementNode : IXamlIlPropertyPathElementNode - { - private readonly IXamlProperty _property; - - public XamlIClrPropertyPathElementNode(IXamlProperty property) - { - _property = property; - } - - public void Emit(XamlEmitContext context, IXamlILEmitter codeGen) - { - context.Configuration.GetExtra() - .Emit(context, codeGen, _property); - - codeGen.EmitCall(context.GetAvaloniaTypes() - .PropertyPathBuilder.GetMethod(m => m.Name == "Property")); - } - - public IXamlType Type => _property.PropertyType; - } - - class XamlIlCastPropertyPathElementNode : IXamlIlPropertyPathElementNode - { - private readonly IXamlType _type; - private readonly bool _ensureType; - - public XamlIlCastPropertyPathElementNode(IXamlType type, bool ensureType) - { - _type = type; - _ensureType = ensureType; - } - - public void Emit(XamlEmitContext context, IXamlILEmitter codeGen) - { - codeGen - .Ldtype(_type) - .EmitCall(context.GetAvaloniaTypes() - .PropertyPathBuilder.GetMethod(m => m.Name == (_ensureType ? "EnsureType" : "Cast"))); - } - - public IXamlType Type => _type; - } - - class XamlIlPropertyPathNode : XamlAstNode, IXamlIlPropertyPathNode, IXamlAstEmitableNode - { - private readonly List _elements; - private readonly AvaloniaXamlIlWellKnownTypes _types; - - public XamlIlPropertyPathNode(IXamlLineInfo lineInfo, - List elements, - AvaloniaXamlIlWellKnownTypes types) : base(lineInfo) - { - _elements = elements; - _types = types; - Type = new XamlAstClrTypeReference(this, types.PropertyPath, false); - } - - public IXamlAstTypeReference Type { get; } - public IXamlType? PropertyType => _elements.LastOrDefault()?.Type; - public XamlILNodeEmitResult Emit(XamlEmitContext context, IXamlILEmitter codeGen) - { - codeGen - .Newobj(_types.PropertyPathBuilder.GetConstructor()); - foreach(var e in _elements) - e.Emit(context, codeGen); - codeGen.EmitCall(_types.PropertyPathBuilder.GetMethod(m => m.Name == "Build")); - return XamlILNodeEmitResult.Type(0, _types.PropertyPath); - } - } - } - - interface IXamlIlPropertyPathNode : IXamlAstValueNode - { - IXamlType? PropertyType { get; } - } -} diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs index 68a5321bf2..86812240df 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs @@ -77,9 +77,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers .FirstOrDefault(x => x.Property.GetClrProperty().Name == "PropertyPath"); if (propertyPath == null) throw new XamlStyleTransformException("Setter without a property or property path is not valid", node); - if (propertyPath.Values[0] is IXamlIlPropertyPathNode ppn - && ppn.PropertyType != null) - propType = ppn.PropertyType; else throw new XamlStyleTransformException("Unable to get the property path property type", node); } diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs index 32c09b5cc7..cab4716aa3 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs @@ -49,8 +49,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers public IXamlMethod INameScopeComplete { get; } public IXamlType IPropertyInfo { get; } public IXamlType ClrPropertyInfo { get; } - public IXamlType PropertyPath { get; } - public IXamlType PropertyPathBuilder { get; } public IXamlType IPropertyAccessor { get; } public IXamlType PropertyInfoAccessorFactory { get; } public IXamlType CompiledBindingPathBuilder { get; } @@ -240,8 +238,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority); IPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.IPropertyInfo"); ClrPropertyInfo = cfg.TypeSystem.GetType("Avalonia.Data.Core.ClrPropertyInfo"); - PropertyPath = cfg.TypeSystem.GetType("Avalonia.Data.Core.PropertyPath"); - PropertyPathBuilder = cfg.TypeSystem.GetType("Avalonia.Data.Core.PropertyPathBuilder"); IPropertyAccessor = cfg.TypeSystem.GetType("Avalonia.Data.Core.Plugins.IPropertyAccessor"); PropertyInfoAccessorFactory = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings.PropertyInfoAccessorFactory"); CompiledBindingPathBuilder = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings.CompiledBindingPathBuilder"); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XamlPropertyPathException.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XamlPropertyPathException.cs new file mode 100644 index 0000000000..52e10aa4cc --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XamlPropertyPathException.cs @@ -0,0 +1,14 @@ +using System; +using XamlX; +using XamlX.Ast; + +namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers +{ + internal class XamlPropertyPathException : XamlTransformException + { + public XamlPropertyPathException(string message, IXamlLineInfo lineInfo, Exception? innerException = null) + : base(message, lineInfo, innerException) + { + } + } +}