Skip to content

Commit

Permalink
Upgrade to YamlDotNet version 12.3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Jan 29, 2023
1 parent 6d1bdfe commit cbcecfe
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 39 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ docs/api
*.cache
.settings
.DS_Store
.idea
launchSettings.json
package-lock.json
*.sublime-workspace
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.DocAsCode.Build.Common/MarkdownReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ private static Dictionary<string, object> RemoveRequiredProperties(ImmutableDict
private static bool CheckRequiredProperties(ImmutableDictionary<string, object> properties, IEnumerable<string> requiredKeys, out string message)
{
var notExistsKeys = (from key in requiredKeys
where !properties.Keys.Contains(key)
where !properties.ContainsKey(key)
select key).ToList();
if (notExistsKeys.Count > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ private static ApiBuildOutput FromModel(ItemViewModel model, Dictionary<string,
Conceptual = model.Conceptual,
Platform = model.Platform,
Attributes = model.Attributes,
Metadata = model.Metadata.Concat(metadata.Where(p => !model.Metadata.Keys.Contains(p.Key))).ToDictionary(p => p.Key, p => p.Value),
Metadata = model.Metadata.Concat(metadata.Where(p => !model.Metadata.ContainsKey(p.Key))).ToDictionary(p => p.Key, p => p.Value),
};
output.DerivedClasses = GetReferenceList(model.DerivedClasses, references, model.SupportedLanguages, true, output.Level + 1);
return output;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal static Dictionary<object, object> ConvertYamlCodeBlock(string yamlCodeB
catch (Exception ex)
{
throw new MarkdownFragmentsException(
$"Encountered an invalid YAML code block: {ex.Message}",
$"Encountered an invalid YAML code block: {ex.ToString()}",
yamlCodeBlockSource.Line,
ex);
}
Expand Down Expand Up @@ -116,8 +116,8 @@ private void FindOrCreateObject(Dictionary<object, object> currentObject, Block
{
object value;
var goodItems = (from item in listObject
where item is Dictionary<object, object>
&& ((Dictionary<object, object>)item).TryGetValue(segment.Key, out value)
where item is Dictionary<object, object>
&& ((Dictionary<object, object>)item).TryGetValue(segment.Key, out value)
&& ((string)value).Equals(segment.Value)
select (Dictionary<object, object>)item).ToList();
if (goodItems.Count > 0)
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.DocAsCode.Build.TableOfContents/TocHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public static TocItemViewModel LoadYamlToc(string file)
}
catch (Exception ex)
{
throw new NotSupportedException($"{file} is not a valid TOC file, detail: {ex.Message}.", ex);
throw new NotSupportedException($"{file} is not a valid TOC file, detail: {ex.ToString()}.", ex);
}
if (obj is TocViewModel vm)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ ApiBuildOutput ToItemApiBuildOutput(ItemViewModel src)
Conceptual = src.Conceptual,

Platform = ToApiListInDevLangs(src.Platform, src.PlatformInDevLangs, supportedLanguages),
Metadata = model.Metadata?.Concat(src.Metadata.Where(p => !model.Metadata.Keys.Contains(p.Key))).ToDictionary(p => p.Key, p => p.Value) ?? src.Metadata,
Metadata = model.Metadata?.Concat(src.Metadata.Where(p => !model.Metadata.ContainsKey(p.Key))).ToDictionary(p => p.Key, p => p.Value) ?? src.Metadata,
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="YamlDotNet" Version="6.0.0" />
<PackageReference Include="YamlDotNet" Version="12.3.1" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DocAsCode.YamlSerialization.ObjectGraphVisitors
{
using System;
using System.ComponentModel;
using YamlDotNet.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.ObjectGraphVisitors;

/// <summary>
/// YamlDotNet behavior has changed since 6.x so a custom version which doesn't check on EnterMapping.
/// </summary>
internal sealed class ExclusiveObjectGraphVisitor : ChainedObjectGraphVisitor
{
public ExclusiveObjectGraphVisitor(IObjectGraphVisitor<IEmitter> nextVisitor)
: base(nextVisitor)
{
}

private static object GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}

public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value, IEmitter context)
{
var defaultValueAttribute = key.GetCustomAttribute<DefaultValueAttribute>();
object defaultValue = defaultValueAttribute != null
? defaultValueAttribute.Value
: GetDefault(key.Type);

return !Equals(value.Value, defaultValue) && base.EnterMapping(key, value, context);
}
}
}
42 changes: 42 additions & 0 deletions src/Microsoft.DocAsCode.YamlSerialization/SerializationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.DocAsCode.YamlSerialization
{
using System;

/// <summary>Options that control the serialization process.</summary>
[Flags]
public enum SerializationOptions
{
/// <summary>Serializes using the default options</summary>
None = 0,
/// <summary>
/// Ensures that it will be possible to deserialize the serialized objects.
/// </summary>
Roundtrip = 1,
/// <summary>
/// If this flag is specified, if the same object appears more than once in the
/// serialization graph, it will be serialized each time instead of just once.
/// </summary>
/// <remarks>
/// If the serialization graph contains circular references and this flag is set,
/// a StackOverflowException will be thrown.
/// If this flag is not set, there is a performance penalty because the entire
/// object graph must be walked twice.
/// </remarks>
DisableAliases = 2,
/// <summary>
/// Forces every value to be serialized, even if it is the default value for that type.
/// </summary>
EmitDefaults = 4,
/// <summary>
/// Ensures that the result of the serialization is valid JSON.
/// </summary>
JsonCompatible = 8,
/// <summary>
/// Use the static type of values instead of their actual type.
/// </summary>
DefaultToStaticType = 16, // 0x00000010
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ namespace Microsoft.DocAsCode.YamlSerialization.TypeInspectors

public class EmitTypeInspector : ExtensibleTypeInspectorSkeleton
{
private static readonly ConcurrentDictionary<Type, CachingItem> _cache =
new ConcurrentDictionary<Type, CachingItem>();
private static readonly ConcurrentDictionary<Type, CachingItem> _cache = new();
private static readonly ConcurrentDictionary<Type, List<IPropertyDescriptor>> _propertyDescriptorCache = new();
private readonly ITypeResolver _resolver;

public EmitTypeInspector(ITypeResolver resolver)
Expand All @@ -34,17 +34,22 @@ public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object
{
throw item.Error;
}
var result = from p in item.Properies select (IPropertyDescriptor)new EmitPropertyDescriptor(p, _resolver);
if (container == null || item.ExtensibleProperies.Count == 0)
{
return result;
// all static information
return _propertyDescriptorCache.GetOrAdd(type, GetPropertyDescriptors(item).ToList());
}
return result.Concat(
return GetPropertyDescriptors(item).Concat(
from ep in item.ExtensibleProperies
from key in ep.GetAllKeys(container) ?? Enumerable.Empty<string>()
select new ExtensiblePropertyDescriptor(ep, ep.Prefix + key, _resolver));
}

private IEnumerable<IPropertyDescriptor> GetPropertyDescriptors(CachingItem item)
{
return from p in item.Properies select new EmitPropertyDescriptor(p, _resolver);
}

public override IPropertyDescriptor GetProperty(Type type, object container, string name)
{
var item = _cache.GetOrAdd(type, CachingItem.Create);
Expand Down
42 changes: 20 additions & 22 deletions src/Microsoft.DocAsCode.YamlSerialization/YamlDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,19 @@ namespace Microsoft.DocAsCode.YamlSerialization
/// </summary>
public sealed class YamlDeserializer
{
private static Dictionary<string, Type> PredefinedTagMappings { get; } =
new Dictionary<string, Type>
{
{ "tag:yaml.org,2002:map", typeof(Dictionary<object, object>) },
{ "tag:yaml.org,2002:bool", typeof(bool) },
{ "tag:yaml.org,2002:float", typeof(double) },
{ "tag:yaml.org,2002:int", typeof(int) },
{ "tag:yaml.org,2002:str", typeof(string) },
{ "tag:yaml.org,2002:timestamp", typeof(DateTime) },
};

private readonly Dictionary<string, Type> _tagMappings;
private static Dictionary<TagName, Type> PredefinedTagMappings { get; } = new Dictionary<TagName, Type>
{
{ "tag:yaml.org,2002:map", typeof(Dictionary<object, object>) },
{ "tag:yaml.org,2002:bool", typeof(bool) },
{ "tag:yaml.org,2002:float", typeof(double) },
{ "tag:yaml.org,2002:int", typeof(int) },
{ "tag:yaml.org,2002:str", typeof(string) },
{ "tag:yaml.org,2002:timestamp", typeof(DateTime) },
};

private readonly Dictionary<TagName, Type> _tagMappings;
private readonly List<IYamlTypeConverter> _converters;
private readonly TypeDescriptorProxy _typeDescriptor =
new TypeDescriptorProxy();
private readonly TypeDescriptorProxy _typeDescriptor = new TypeDescriptorProxy();
private readonly IValueDeserializer _valueDeserializer;

public IList<INodeDeserializer> NodeDeserializers { get; private set; }
Expand Down Expand Up @@ -103,7 +101,7 @@ public YamlDeserializer(
new EnumerableNodeDeserializer(),
new ExtensibleObjectNodeDeserializer(objectFactory, _typeDescriptor, ignoreUnmatched)
};
_tagMappings = new Dictionary<string, Type>(PredefinedTagMappings);
_tagMappings = new Dictionary<TagName, Type>(PredefinedTagMappings);
TypeResolvers = new List<INodeTypeResolver>
{
new TagNodeTypeResolver(_tagMappings),
Expand Down Expand Up @@ -219,7 +217,7 @@ public LooseAliasValueDeserializer(IValueDeserializer innerDeserializer)
_innerDeserializer = innerDeserializer ?? throw new ArgumentNullException("innerDeserializer");
}

private sealed class AliasState : Dictionary<string, ValuePromise>, IPostDeserializationCallback
private sealed class AliasState : Dictionary<AnchorName, ValuePromise>, IPostDeserializationCallback
{
public void OnDeserialization()
{
Expand Down Expand Up @@ -295,10 +293,10 @@ public object DeserializeValue(IParser reader, Type expectedType, SerializerStat
return valuePromise.HasValue ? valuePromise.Value : valuePromise;
}

string anchor = null;
AnchorName? anchor = null;

var nodeEvent = reader.Peek<NodeEvent>();
if (nodeEvent != null && !string.IsNullOrEmpty(nodeEvent.Anchor))
if (nodeEvent != null && !nodeEvent.Anchor.IsEmpty)
{
anchor = nodeEvent.Anchor;
}
Expand All @@ -309,22 +307,22 @@ public object DeserializeValue(IParser reader, Type expectedType, SerializerStat
{
var aliasState = state.Get<AliasState>();

if (!aliasState.TryGetValue(anchor, out ValuePromise valuePromise))
if (!aliasState.TryGetValue(anchor.Value, out ValuePromise valuePromise))
{
aliasState.Add(anchor, new ValuePromise(value));
aliasState.Add(anchor.Value, new ValuePromise(value));
}
else if (!valuePromise.HasValue)
{
valuePromise.Value = value;
}
else
{
aliasState[anchor] = new ValuePromise(value);
aliasState[anchor.Value] = new ValuePromise(value);
}
}

return value;
}
}
}
}
}
9 changes: 6 additions & 3 deletions src/Microsoft.DocAsCode.YamlSerialization/YamlSerializer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.DocAsCode.YamlSerialization.ObjectGraphVisitors;

namespace Microsoft.DocAsCode.YamlSerialization
{
using System;
Expand Down Expand Up @@ -90,14 +92,14 @@ private IObjectGraphVisitor<IEmitter> CreateEmittingVisitor(IEmitter emitter, IO
if (!IsOptionSet(SerializationOptions.DisableAliases))
{
var anchorAssigner = new AnchorAssigner(Converters);
traversalStrategy.Traverse<Nothing>(graph, anchorAssigner, null);
traversalStrategy.Traverse<Nothing>(graph, anchorAssigner, default);

emittingVisitor = new AnchorAssigningObjectGraphVisitor(emittingVisitor, eventEmitter, anchorAssigner);
}

if (!IsOptionSet(SerializationOptions.EmitDefaults))
{
emittingVisitor = new DefaultExclusiveObjectGraphVisitor(emittingVisitor);
emittingVisitor = new ExclusiveObjectGraphVisitor(emittingVisitor);
}

return emittingVisitor;
Expand Down Expand Up @@ -130,7 +132,7 @@ private IEventEmitter CreateEventEmitter()
}
else
{
return new TypeAssigningEventEmitter(writer, IsOptionSet(SerializationOptions.Roundtrip), new Dictionary<Type, string>());
return new TypeAssigningEventEmitter(writer, IsOptionSet(SerializationOptions.Roundtrip), new Dictionary<Type, TagName>());
}
}

Expand All @@ -156,3 +158,4 @@ private IObjectGraphTraversalStrategy CreateTraversalStrategy()
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ public void LoadBadTocYamlFileShouldGiveLineNumber()
href: x2.md";
var toc = _fileCreator.CreateFile(content, FileType.YamlToc);
var ex = Assert.Throws<DocumentException>(() => TocHelper.LoadSingleToc(toc));
Assert.Equal("toc.yml is not a valid TOC File: toc.yml is not a valid TOC file, detail: (Line: 3, Col: 10, Idx: 22) - (Line: 3, Col: 10, Idx: 22): Mapping values are not allowed in this context..", ex.Message);
Assert.Equal("toc.yml is not a valid TOC File: toc.yml is not a valid TOC file, detail: (Line: 3, Col: 10, Idx: 22) - (Line: 3, Col: 10, Idx: 22): While scanning a plain scalar value, found invalid mapping..", ex.Message);
}

[Fact]
Expand Down

0 comments on commit cbcecfe

Please sign in to comment.