Browse Source

Remove `PropertyPath`. (#19133)

* Remove PropertyPath.

It was added as part of #2734 with the intention of it being used for animation setters, but this was never implemented. There's no point carrying this old unused code around - if we want to implement this feature we can add it back in.

* Update API suppressions.
pull/19147/head
Steven Kirk 7 months ago
committed by GitHub
parent
commit
fdf939a27f
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 42
      api/Avalonia.nupkg.xml
  2. 91
      src/Avalonia.Base/Data/Core/PropertyPath.cs
  3. 1
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  4. 262
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs
  5. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlSetterTransformer.cs
  6. 4
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  7. 14
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/XamlPropertyPathException.cs

42
api/Avalonia.nupkg.xml

@ -7,6 +7,48 @@
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.CastTypePropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.ChildTraversalPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.EnsureTypePropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.IPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPath</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPathBuilder</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Utilities.CharacterReader</Target>

91
src/Avalonia.Base/Data/Core/PropertyPath.cs

@ -1,91 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Avalonia.Data.Core
{
public class PropertyPath
{
public IReadOnlyList<IPropertyPathElement> Elements { get; }
public PropertyPath(IEnumerable<IPropertyPathElement> elements)
{
Elements = elements.ToArray();
}
}
public class PropertyPathBuilder
{
readonly List<IPropertyPathElement> _elements = new List<IPropertyPathElement>();
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; }
}
}

1
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(),

262
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlPropertyPathTransformer.cs

@ -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<AvaloniaXamlIlTargetTypeMetadataNode>()
.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<PropertyPathGrammar.ISyntax> 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<IXamlIlPropertyPathElementNode>();
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<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen);
IXamlType? Type { get; }
}
class XamlIlChildTraversalPropertyPathElementNode : IXamlIlPropertyPathElementNode
{
public void Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> 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<IXamlILEmitter, XamlILNodeEmitResult> 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<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
{
context.Configuration.GetExtra<XamlIlClrPropertyInfoEmitter>()
.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<IXamlILEmitter, XamlILNodeEmitResult> 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<IXamlILEmitter, XamlILNodeEmitResult>
{
private readonly List<IXamlIlPropertyPathElementNode> _elements;
private readonly AvaloniaXamlIlWellKnownTypes _types;
public XamlIlPropertyPathNode(IXamlLineInfo lineInfo,
List<IXamlIlPropertyPathElementNode> 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<IXamlILEmitter, XamlILNodeEmitResult> 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; }
}
}

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

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

14
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)
{
}
}
}
Loading…
Cancel
Save