From 6b0619f1d976279774f049e5fc9bba8da866f1c5 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Sat, 28 Jan 2023 11:19:48 +0200 Subject: [PATCH] Upgrade to YamlDotNet version 12.3.1 --- .../OverwriteDocumentModelCreater.cs | 6 +-- .../TocHelper.cs | 2 +- ...crosoft.DocAsCode.YamlSerialization.csproj | 2 +- .../SerializationOptions.cs | 42 +++++++++++++++++++ .../TypeInspectors/EmitTypeInspector.cs | 15 ++++--- .../YamlDeserializer.cs | 42 +++++++++---------- .../YamlSerializer.cs | 4 +- .../TocDocumentProcessorTest.cs | 2 +- 8 files changed, 80 insertions(+), 35 deletions(-) create mode 100644 src/Microsoft.DocAsCode.YamlSerialization/SerializationOptions.cs diff --git a/src/Microsoft.DocAsCode.Build.OverwriteDocuments/OverwriteDocumentModelCreater.cs b/src/Microsoft.DocAsCode.Build.OverwriteDocuments/OverwriteDocumentModelCreater.cs index d3b8854805f..c17e3e49686 100644 --- a/src/Microsoft.DocAsCode.Build.OverwriteDocuments/OverwriteDocumentModelCreater.cs +++ b/src/Microsoft.DocAsCode.Build.OverwriteDocuments/OverwriteDocumentModelCreater.cs @@ -52,7 +52,7 @@ internal static Dictionary 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); } @@ -116,8 +116,8 @@ private void FindOrCreateObject(Dictionary currentObject, Block { object value; var goodItems = (from item in listObject - where item is Dictionary - && ((Dictionary)item).TryGetValue(segment.Key, out value) + where item is Dictionary + && ((Dictionary)item).TryGetValue(segment.Key, out value) && ((string)value).Equals(segment.Value) select (Dictionary)item).ToList(); if (goodItems.Count > 0) diff --git a/src/Microsoft.DocAsCode.Build.TableOfContents/TocHelper.cs b/src/Microsoft.DocAsCode.Build.TableOfContents/TocHelper.cs index acbc9c3b820..903a1f9ab99 100644 --- a/src/Microsoft.DocAsCode.Build.TableOfContents/TocHelper.cs +++ b/src/Microsoft.DocAsCode.Build.TableOfContents/TocHelper.cs @@ -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) { diff --git a/src/Microsoft.DocAsCode.YamlSerialization/Microsoft.DocAsCode.YamlSerialization.csproj b/src/Microsoft.DocAsCode.YamlSerialization/Microsoft.DocAsCode.YamlSerialization.csproj index df6645cfa97..d5e9dbd99a0 100644 --- a/src/Microsoft.DocAsCode.YamlSerialization/Microsoft.DocAsCode.YamlSerialization.csproj +++ b/src/Microsoft.DocAsCode.YamlSerialization/Microsoft.DocAsCode.YamlSerialization.csproj @@ -1,5 +1,5 @@  - + diff --git a/src/Microsoft.DocAsCode.YamlSerialization/SerializationOptions.cs b/src/Microsoft.DocAsCode.YamlSerialization/SerializationOptions.cs new file mode 100644 index 00000000000..9e840ee27c9 --- /dev/null +++ b/src/Microsoft.DocAsCode.YamlSerialization/SerializationOptions.cs @@ -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; + + /// Options that control the serialization process. + [Flags] + public enum SerializationOptions + { + /// Serializes using the default options + None = 0, + /// + /// Ensures that it will be possible to deserialize the serialized objects. + /// + Roundtrip = 1, + /// + /// 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. + /// + /// + /// 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. + /// + DisableAliases = 2, + /// + /// Forces every value to be serialized, even if it is the default value for that type. + /// + EmitDefaults = 4, + /// + /// Ensures that the result of the serialization is valid JSON. + /// + JsonCompatible = 8, + /// + /// Use the static type of values instead of their actual type. + /// + DefaultToStaticType = 16, // 0x00000010 + } +} diff --git a/src/Microsoft.DocAsCode.YamlSerialization/TypeInspectors/EmitTypeInspector.cs b/src/Microsoft.DocAsCode.YamlSerialization/TypeInspectors/EmitTypeInspector.cs index b4f14322459..cd01594b2d3 100644 --- a/src/Microsoft.DocAsCode.YamlSerialization/TypeInspectors/EmitTypeInspector.cs +++ b/src/Microsoft.DocAsCode.YamlSerialization/TypeInspectors/EmitTypeInspector.cs @@ -18,8 +18,8 @@ namespace Microsoft.DocAsCode.YamlSerialization.TypeInspectors public class EmitTypeInspector : ExtensibleTypeInspectorSkeleton { - private static readonly ConcurrentDictionary _cache = - new ConcurrentDictionary(); + private static readonly ConcurrentDictionary _cache = new(); + private static readonly ConcurrentDictionary> _propertyDescriptorCache = new(); private readonly ITypeResolver _resolver; public EmitTypeInspector(ITypeResolver resolver) @@ -34,17 +34,22 @@ public override IEnumerable 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() select new ExtensiblePropertyDescriptor(ep, ep.Prefix + key, _resolver)); } + private IEnumerable 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); diff --git a/src/Microsoft.DocAsCode.YamlSerialization/YamlDeserializer.cs b/src/Microsoft.DocAsCode.YamlSerialization/YamlDeserializer.cs index cea35d59896..538fe807031 100644 --- a/src/Microsoft.DocAsCode.YamlSerialization/YamlDeserializer.cs +++ b/src/Microsoft.DocAsCode.YamlSerialization/YamlDeserializer.cs @@ -28,21 +28,19 @@ namespace Microsoft.DocAsCode.YamlSerialization /// public sealed class YamlDeserializer { - private static Dictionary PredefinedTagMappings { get; } = - new Dictionary - { - { "tag:yaml.org,2002:map", typeof(Dictionary) }, - { "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 _tagMappings; + private static Dictionary PredefinedTagMappings { get; } = new Dictionary + { + { "tag:yaml.org,2002:map", typeof(Dictionary) }, + { "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 _tagMappings; private readonly List _converters; - private readonly TypeDescriptorProxy _typeDescriptor = - new TypeDescriptorProxy(); + private readonly TypeDescriptorProxy _typeDescriptor = new TypeDescriptorProxy(); private readonly IValueDeserializer _valueDeserializer; public IList NodeDeserializers { get; private set; } @@ -103,7 +101,7 @@ public YamlDeserializer( new EnumerableNodeDeserializer(), new ExtensibleObjectNodeDeserializer(objectFactory, _typeDescriptor, ignoreUnmatched) }; - _tagMappings = new Dictionary(PredefinedTagMappings); + _tagMappings = new Dictionary(PredefinedTagMappings); TypeResolvers = new List { new TagNodeTypeResolver(_tagMappings), @@ -219,7 +217,7 @@ public LooseAliasValueDeserializer(IValueDeserializer innerDeserializer) _innerDeserializer = innerDeserializer ?? throw new ArgumentNullException("innerDeserializer"); } - private sealed class AliasState : Dictionary, IPostDeserializationCallback + private sealed class AliasState : Dictionary, IPostDeserializationCallback { public void OnDeserialization() { @@ -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(); - if (nodeEvent != null && !string.IsNullOrEmpty(nodeEvent.Anchor)) + if (nodeEvent != null && !nodeEvent.Anchor.IsEmpty) { anchor = nodeEvent.Anchor; } @@ -309,9 +307,9 @@ public object DeserializeValue(IParser reader, Type expectedType, SerializerStat { var aliasState = state.Get(); - 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) { @@ -319,7 +317,7 @@ public object DeserializeValue(IParser reader, Type expectedType, SerializerStat } else { - aliasState[anchor] = new ValuePromise(value); + aliasState[anchor.Value] = new ValuePromise(value); } } @@ -327,4 +325,4 @@ public object DeserializeValue(IParser reader, Type expectedType, SerializerStat } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DocAsCode.YamlSerialization/YamlSerializer.cs b/src/Microsoft.DocAsCode.YamlSerialization/YamlSerializer.cs index 3189f5a4111..1727318a13c 100644 --- a/src/Microsoft.DocAsCode.YamlSerialization/YamlSerializer.cs +++ b/src/Microsoft.DocAsCode.YamlSerialization/YamlSerializer.cs @@ -90,7 +90,7 @@ private IObjectGraphVisitor CreateEmittingVisitor(IEmitter emitter, IO if (!IsOptionSet(SerializationOptions.DisableAliases)) { var anchorAssigner = new AnchorAssigner(Converters); - traversalStrategy.Traverse(graph, anchorAssigner, null); + traversalStrategy.Traverse(graph, anchorAssigner, default); emittingVisitor = new AnchorAssigningObjectGraphVisitor(emittingVisitor, eventEmitter, anchorAssigner); } @@ -130,7 +130,7 @@ private IEventEmitter CreateEventEmitter() } else { - return new TypeAssigningEventEmitter(writer, IsOptionSet(SerializationOptions.Roundtrip), new Dictionary()); + return new TypeAssigningEventEmitter(writer, IsOptionSet(SerializationOptions.Roundtrip), new Dictionary()); } } diff --git a/test/Microsoft.DocAsCode.Build.TableOfContents.Tests/TocDocumentProcessorTest.cs b/test/Microsoft.DocAsCode.Build.TableOfContents.Tests/TocDocumentProcessorTest.cs index 7ef39645b91..1e7ed264533 100644 --- a/test/Microsoft.DocAsCode.Build.TableOfContents.Tests/TocDocumentProcessorTest.cs +++ b/test/Microsoft.DocAsCode.Build.TableOfContents.Tests/TocDocumentProcessorTest.cs @@ -771,7 +771,7 @@ public void LoadBadTocYamlFileShouldGiveLineNumber() href: x2.md"; var toc = _fileCreator.CreateFile(content, FileType.YamlToc); var ex = Assert.Throws(() => 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]