Skip to content

Commit

Permalink
Fixed reference + attribute-based deserialization issues (#503)
Browse files Browse the repository at this point in the history
The XmlReader was setting an improper state when reading attribute values.  Now the current attribute index is maintained when accessing another attribute value.
  • Loading branch information
Mike-E-angelo authored Mar 9, 2021
1 parent 7563d44 commit e2c435a
Show file tree
Hide file tree
Showing 68 changed files with 3,346 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .build/Install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function Exec
& $cmd
if ($LastExitCode -ne 0) {
$host.SetShouldExit($LastExitCode)
throw ("Exec: " + $errorMessage)
throw ("Error With Exec: $cmd" + $errorMessage)
}
}

Expand Down
19 changes: 17 additions & 2 deletions ExtendedXmlSerializer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtendedXmlSerializer.Tests
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".build", ".build", "{DE813CE8-58FB-473D-A10E-CDDFF2A58FBF}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
.build\appveyor.yml = .build\appveyor.yml
.build\Common.ps1 = .build\Common.ps1
documentation\docfx.json = documentation\docfx.json
.build\Install.ps1 = .build\Install.ps1
.build\Success.ps1 = .build\Success.ps1
EndProjectSection
Expand All @@ -28,6 +27,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtendedXmlSerializer.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtendedXmlSerializer.Samples", "samples\ExtendedXmlSerializer.Samples\ExtendedXmlSerializer.Samples.csproj", "{935EB8FE-A9E5-4DC7-8CBB-7A32E2A56C9E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtendedXmlSerializer.Tests.ReportedIssues.Issue502", "test\ExtendedXmlSerializer.Tests.ReportedIssues.Issue502\ExtendedXmlSerializer.Tests.ReportedIssues.Issue502.csproj", "{358A888A-5FAD-47CA-BD72-F919DB3ED267}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".references", ".references", "{36FD3644-F29C-4AD9-A533-ECB1802D476E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VweCore", "test\.External\VweCore\VweCore.csproj", "{E3D212A5-E82B-4823-AEF3-DF58B898F669}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -54,12 +59,22 @@ Global
{935EB8FE-A9E5-4DC7-8CBB-7A32E2A56C9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{935EB8FE-A9E5-4DC7-8CBB-7A32E2A56C9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{935EB8FE-A9E5-4DC7-8CBB-7A32E2A56C9E}.Release|Any CPU.Build.0 = Release|Any CPU
{358A888A-5FAD-47CA-BD72-F919DB3ED267}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{358A888A-5FAD-47CA-BD72-F919DB3ED267}.Debug|Any CPU.Build.0 = Debug|Any CPU
{358A888A-5FAD-47CA-BD72-F919DB3ED267}.Release|Any CPU.ActiveCfg = Release|Any CPU
{358A888A-5FAD-47CA-BD72-F919DB3ED267}.Release|Any CPU.Build.0 = Release|Any CPU
{E3D212A5-E82B-4823-AEF3-DF58B898F669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3D212A5-E82B-4823-AEF3-DF58B898F669}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3D212A5-E82B-4823-AEF3-DF58B898F669}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3D212A5-E82B-4823-AEF3-DF58B898F669}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DE813CE8-58FB-473D-A10E-CDDFF2A58FBF} = {2859812B-6D27-4A85-AC4A-8D3A55D9E3CD}
{36FD3644-F29C-4AD9-A533-ECB1802D476E} = {2859812B-6D27-4A85-AC4A-8D3A55D9E3CD}
{E3D212A5-E82B-4823-AEF3-DF58B898F669} = {36FD3644-F29C-4AD9-A533-ECB1802D476E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0980EF53-85ED-482A-8798-690538C3F7A4}
Expand Down
29 changes: 29 additions & 0 deletions src/ExtendedXmlSerializer/ContentModel/Content/Contains.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using ExtendedXmlSerializer.ContentModel.Format;
using ExtendedXmlSerializer.ContentModel.Identification;
using ExtendedXmlSerializer.Core.Specifications;
using System.Xml;

namespace ExtendedXmlSerializer.ContentModel.Content
{
sealed class Contains : ISpecification<(IFormatReader Reader, IIdentity Identity)>
{
public static Contains Default { get; } = new Contains();

Contains() {}

public bool IsSatisfiedBy((IFormatReader Reader, IIdentity Identity) parameter)
{
var (format, identity) = parameter;

var reader = format.Get().To<XmlReader>();
var name = reader.NodeType == XmlNodeType.Attribute ? format.Name : null;
var result = format.IsSatisfiedBy(identity);
if (name != null)
{
reader.MoveToAttribute(name);
}

return result;
}
}
}
37 changes: 37 additions & 0 deletions src/ExtendedXmlSerializer/ContentModel/Content/IsElement.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using ExtendedXmlSerializer.ContentModel.Format;
using ExtendedXmlSerializer.Core.Specifications;
using System;
using System.Xml;

namespace ExtendedXmlSerializer.ContentModel.Content
{
sealed class IsElement : ISpecification<IFormatReader>
{
public static IsElement Default { get; } = new IsElement();

IsElement() : this(MemberProperty.Default.Get) {}

readonly Func<IFormatReader, bool> _member;

public IsElement(Func<IFormatReader, bool> member) => _member = member;

public bool IsSatisfiedBy(IFormatReader parameter)
{
var reader = parameter.Get().To<XmlReader>();
switch (reader.NodeType)
{
case XmlNodeType.Attribute:
var name = parameter.Name;
var result = _member(parameter);
if (result)
{
reader.MoveToAttribute(name);
}

return result;
}

return true;
}
}
}
3 changes: 3 additions & 0 deletions src/ExtendedXmlSerializer/ContentModel/Members/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public static T GetIfAssigned<T>(this IReader<T> @this, IFormatReader reader)
public static object GetIfAssigned(this IReader @this, IFormatReader reader)
=> reader.IsAssigned() ? @this.Get(reader) : null;

public static bool Contains(this IFormatReader @this, IIdentity identity)
=> Content.Contains.Default.IsSatisfiedBy((@this, identity));

public static bool IsAssigned(this IFormatReader @this)
=> !IdentityComparer.Default.Equals(@this, NullElementIdentity.Default) &&
!@this.IsSatisfiedBy(NullValueIdentity.Default);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ExtendedXmlSerializer.ContentModel.Content;
using ExtendedXmlSerializer.ContentModel.Format;
using ExtendedXmlSerializer.ContentModel.Identification;
using ExtendedXmlSerializer.ContentModel.Members;
using ExtendedXmlSerializer.ContentModel.Properties;
using System;
using System.Collections.Immutable;
Expand Down Expand Up @@ -28,10 +29,9 @@ public Classification(IFormattedContentSpecification specification, IIdentitySto
}

public TypeInfo Get(IFormatReader parameter)
=> FromAttributes(parameter) ?? (!parameter.IsSatisfiedBy(MemberIdentity.Default)
? _types.Get(_identities.Get(parameter.Name, parameter.Identifier))
: null);

=> FromAttributes(parameter) ?? (parameter.Contains(MemberIdentity.Default)
? null
: _types.Get(_identities.Get(parameter.Name, parameter.Identifier)));
TypeInfo FromAttributes(IFormatReader parameter)
=> _specification.IsSatisfiedBy(parameter)
? ExplicitTypeProperty.Default.Get(parameter) ??
Expand Down
13 changes: 12 additions & 1 deletion src/ExtendedXmlSerializer/ContentModel/TrackingReader.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ExtendedXmlSerializer.ContentModel.Format;
using System.Xml;

namespace ExtendedXmlSerializer.ContentModel
{
Expand All @@ -10,8 +11,18 @@ sealed class TrackingReader<T> : IReader<T>

public T Get(IFormatReader parameter)
{
var reader = parameter.Get().To<XmlReader>();
var name = reader.NodeType == XmlNodeType.Attribute ? parameter.Name : null;
var result = _reader.Get(parameter);
parameter.Set();
if (name != null)
{
reader.MoveToAttribute(name);
}
else
{
parameter.Set();
}

return result;
}
}
Expand Down
1 change: 1 addition & 0 deletions src/ExtendedXmlSerializer/ExtendedXmlSerializer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@ https://github.com/ExtendedXmlSerializer/home/blob/master/CHANGELOG.md
<PackageReference Include="System.Interactive" Version="4.1.1" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.1" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using JetBrains.Annotations;
using System;
using System.Reflection;
using System.Xml;

namespace ExtendedXmlSerializer.ExtensionModel.References
{
Expand All @@ -15,7 +14,7 @@ sealed class ReferenceActivation : IActivation
readonly Func<TypeInfo, IReader> _activation;
readonly IEntities _entities;
readonly IReferenceMaps _maps;

[UsedImplicitly]
public ReferenceActivation(IActivation activation, IEntities entities)
: this(activation.Get, entities) {}
Expand Down Expand Up @@ -68,7 +67,7 @@ public Activator(IReader activator, IEntities entities, IReferenceMaps maps)

public object Get(IFormatReader parameter)
{
var element = parameter.Get().To<XmlReader>().NodeType != XmlNodeType.Attribute || MemberProperty.Default.Get(parameter);
var element = IsElement.Default.IsSatisfiedBy(parameter);

var declared = element ? Identity(parameter) : null;
var result = _activator.Get(parameter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
using ExtendedXmlSerializer.ContentModel.Properties;
using ExtendedXmlSerializer.ContentModel.Reflection;
using System.Reflection;
using System.Xml;

namespace ExtendedXmlSerializer.ExtensionModel.References
{
sealed class ReferenceReader : DecoratedReader
{
readonly static ContentModel.Properties.ReferenceIdentity ReferenceIdentity =
ContentModel.Properties.ReferenceIdentity.Default;

readonly IReferenceMaps _maps;
readonly IEntities _entities;
readonly TypeInfo _definition;
Expand All @@ -30,38 +28,36 @@ public ReferenceReader(IReader reader, IReferenceMaps maps, IEntities entities,

ReferenceIdentity? GetReference(IFormatReader parameter)
{
if (parameter.Get().To<XmlReader>().NodeType != XmlNodeType.Attribute ||
MemberProperty.Default.Get(parameter))
var identity = ReferenceIdentity.Get(parameter);
if (identity.HasValue)
{
var identity = ReferenceIdentity.Get(parameter);
if (identity.HasValue)
{
return new ReferenceIdentity(identity.Value);
}
return new ReferenceIdentity(identity.Value);
}

var type = _classification.GetClassification(parameter, _definition);
var entity = _entities.Get(type)?.Reference(parameter);
if (entity != null)
{
return new ReferenceIdentity(type, entity);
}
var type = _classification.GetClassification(parameter, _definition);
var entity = _entities.Get(type)?.Reference(parameter);
if (entity != null)
{
return new ReferenceIdentity(type, entity);
}

return null;
}

public override object Get(IFormatReader parameter)
{
var reference = GetReference(parameter);
if (reference != null)
var element = IsElement.Default.IsSatisfiedBy(parameter);
if (element)
{
var result = _maps.Get(parameter).Get(reference.Value);
return result;
var reference = GetReference(parameter);
if (reference != null)
{
var result = _maps.Get(parameter).Get(reference.Value);
return result;
}
}

{
var element = parameter.Get().To<XmlReader>().NodeType != XmlNodeType.Attribute ||
MemberProperty.Default.Get(parameter);
var declared = element ? Identity(parameter) : null;
var result = base.Get(parameter);
var identity = declared ?? (element && result != null ? Entity(parameter, result) : null);
Expand All @@ -87,12 +83,10 @@ public override object Get(IFormatReader parameter)

ReferenceIdentity? Entity(IFormatReader reader, object instance)
{
var typeInfo = instance.GetType()
.GetTypeInfo();
var entity = _entities.Get(typeInfo)
?.Get(reader);
var typeInfo = instance.GetType();
var entity = _entities.Get(typeInfo)?.Get(reader);
var result = entity != null
? (ReferenceIdentity?)new ReferenceIdentity(typeInfo, entity)
? (ReferenceIdentity?)new ReferenceIdentity(typeInfo.GetTypeInfo(), entity)
: null;
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public IFormatReader Get(IFormatReader parameter)
throw new XmlException($"Unknown varsion number {version} for type {typeInfo}.");
}

parameter.Set();

var reader = parameter.Get().AsValid<System.Xml.XmlReader>();
var element = XElement.Load(reader.ReadSubtree());
for (var i = version; i < _version; i++)
Expand Down
9 changes: 9 additions & 0 deletions test/.External/VweCore/Abstractions/ICustomDelete.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace VweCore.Abstractions
{
public interface ICustomDelete
{
void DeleteFromMap(Map map);

void RestoreBackToMap(Map map);
}
}
30 changes: 30 additions & 0 deletions test/.External/VweCore/Abstractions/IEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Diagnostics.CodeAnalysis;
using VweCore.Geometry;

namespace VweCore.Abstractions
{
public interface IEntity : IEquatable<IEntity>, IComparable<IEntity>
{
int Id { get; set; }

Guid InternalId { get; set; }

string DisplayString { get; }

void SetAssociatedDiagramItem(object diagramItem);

EntityOrderIndex OrderIndex { get; }

bool TryGetAssociatedDiagramItem<TDiagramItem>([NotNullWhen(true)] out TDiagramItem? diagramItem)
where TDiagramItem : class;

TDiagramItem GetAssociatedDiagramItem<TDiagramItem>()
where TDiagramItem : class;

TDiagramItem DisconnectDiagramItem<TDiagramItem>()
where TDiagramItem : class;

LeveledRectangle GetBounds();
}
}
11 changes: 11 additions & 0 deletions test/.External/VweCore/Abstractions/ILineSegment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using VweCore.Geometry;

namespace VweCore.Abstractions
{
public interface ILineSegment : IEntity
{
Point2D Point1 { get; set; }

Point2D Point2 { get; set; }
}
}
9 changes: 9 additions & 0 deletions test/.External/VweCore/Abstractions/IMovable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using VweCore.Geometry;

namespace VweCore.Abstractions
{
public interface IMovable : IEntity
{
void Move(Point2D moveVector);
}
}
9 changes: 9 additions & 0 deletions test/.External/VweCore/Abstractions/IPositionable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using VweCore.Geometry;

namespace VweCore.Abstractions
{
public interface IPositionable : IMovable
{
Point2D Position { get; set; }
}
}
Loading

0 comments on commit e2c435a

Please sign in to comment.