diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/BinaryConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/BinaryConverter.cs index 4fe611a3..a0466db5 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/BinaryConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/BinaryConverter.cs @@ -126,7 +126,7 @@ private static void EnsureReflectionObject(Type t) { // current token is already at base64 string // unable to call ReadAsBytes so do it the old fashion way - string encodedData = reader.Value!.ToString(); + string encodedData = reader.Value!.ToString()!; data = Convert.FromBase64String(encodedData); } else @@ -135,7 +135,7 @@ private static void EnsureReflectionObject(Type t) } Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; #if HAVE_LINQ diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/DataSetConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/DataSetConverter.cs index c6ce5a80..a6e6ccba 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/DataSetConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/DataSetConverter.cs @@ -84,7 +84,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer // handle typed datasets DataSet ds = (objectType == typeof(DataSet)) ? new DataSet() - : (DataSet)Activator.CreateInstance(objectType); + : (DataSet)Activator.CreateInstance(objectType)!; DataTableConverter converter = new DataTableConverter(); @@ -92,7 +92,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer while (reader.TokenType == JsonToken.PropertyName) { - DataTable dt = ds.Tables[(string)reader.Value!]; + DataTable? dt = ds.Tables[(string)reader.Value!]; bool exists = (dt != null); dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer)!; diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/DataTableConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/DataTableConverter.cs index 0eb32261..4a91e9ae 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/DataTableConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/DataTableConverter.cs @@ -99,7 +99,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer // handle typed datasets dt = (objectType == typeof(DataTable)) ? new DataTable() - : (DataTable)Activator.CreateInstance(objectType); + : (DataTable)Activator.CreateInstance(objectType)!; } // DataTable is inside a DataSet @@ -144,7 +144,7 @@ private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer se reader.ReadAndAssert(); - DataColumn column = dt.Columns[columnName]; + DataColumn? column = dt.Columns[columnName]; if (column == null) { Type columnType = GetColumnDataType(reader); @@ -185,7 +185,7 @@ private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer se reader.ReadAndAssert(); } - Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count); + Array destinationArray = Array.CreateInstance(column.DataType.GetElementType()!, o.Count); ((IList)o).CopyTo(destinationArray, 0); dr[columnName] = destinationArray; diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs index 9fb0f5b9..a693a2d1 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs @@ -182,7 +182,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer while (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (string.Equals(propertyName, CasePropertyName, StringComparison.OrdinalIgnoreCase)) { reader.ReadAndAssert(); diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs index 65d275ce..b797a853 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs @@ -129,7 +129,7 @@ private static void ReadAndAssertProperty(JsonReader reader, string propertyName reader.ReadAndAssert(); string? type = reader.Value?.ToString(); - Type t = Type.GetType(type); + Type t = Type.GetType(type!)!; ReadAndAssertProperty(reader, ValuePropertyName); reader.ReadAndAssert(); diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs index 580343c1..3dc1896d 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs @@ -119,7 +119,7 @@ private object ReadObject(JsonReader reader) switch (reader.TokenType) { case JsonToken.PropertyName: - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (!reader.Read()) { diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs index 8e1475a0..da32cbf3 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs @@ -133,7 +133,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer #if HAVE_DATE_TIME_OFFSET Type t = (nullable) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; #endif @@ -167,6 +167,8 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer return null; } + MiscellaneousUtils.Assert(dateText != null); + #if HAVE_DATE_TIME_OFFSET if (t == typeof(DateTimeOffset)) { diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs index ee0639a6..9a0ca319 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs @@ -98,7 +98,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer #if HAVE_DATE_TIME_OFFSET Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; if (t == typeof(DateTimeOffset)) { diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/KeyValuePairConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/KeyValuePairConverter.cs index e4dfa867..a38c8a1b 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/KeyValuePairConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/KeyValuePairConverter.cs @@ -102,7 +102,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer reader.ReadAndAssert(); Type t = ReflectionUtils.IsNullableType(objectType) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; ReflectionObject reflectionObject = ReflectionObjectPerType.Get(t); @@ -111,7 +111,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer while (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(keyContract, false); @@ -145,7 +145,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer public override bool CanConvert(Type objectType) { Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; if (t.IsValueType() && t.IsGenericType()) diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/RegexConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/RegexConverter.cs index 981f3660..444adf2c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/RegexConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/RegexConverter.cs @@ -179,7 +179,7 @@ private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) switch (reader.TokenType) { case JsonToken.PropertyName: - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (!reader.Read()) { diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/StringEnumConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/StringEnumConverter.cs index da1af695..500b99dc 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/StringEnumConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/StringEnumConverter.cs @@ -222,7 +222,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer } bool isNullable = ReflectionUtils.IsNullableType(objectType); - Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType; + Type t = isNullable ? Nullable.GetUnderlyingType(objectType)! : objectType; try { @@ -267,7 +267,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer public override bool CanConvert(Type objectType) { Type t = (ReflectionUtils.IsNullableType(objectType)) - ? Nullable.GetUnderlyingType(objectType) + ? Nullable.GetUnderlyingType(objectType)! : objectType; return t.IsEnum(); diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs index eda72c0b..0e82101b 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/UnixDateTimeConverter.cs @@ -36,6 +36,37 @@ internal class UnixDateTimeConverter : DateTimeConverterBase { internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + /// + /// Gets or sets a value indicating whether the dates before Unix epoch + /// should converted to and from JSON. + /// + /// + /// true to allow converting dates before Unix epoch to and from JSON; + /// false to throw an exception when a date being converted to or from JSON + /// occurred before Unix epoch. The default value is false. + /// + public bool AllowPreEpoch { get; set; } + + /// + /// Initializes a new instance of the class. + /// + public UnixDateTimeConverter() : this(false) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// true to allow converting dates before Unix epoch to and from JSON; + /// false to throw an exception when a date being converted to or from JSON + /// occurred before Unix epoch. The default value is false. + /// + public UnixDateTimeConverter(bool allowPreEpoch) + { + AllowPreEpoch = allowPreEpoch; + } + /// /// Writes the JSON representation of the object. /// @@ -61,7 +92,7 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer throw new JsonSerializationException("Expected date object value."); } - if (seconds < 0) + if (!AllowPreEpoch && seconds < 0) { throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970."); } @@ -108,12 +139,12 @@ public override void WriteJson(JsonWriter writer, object? value, JsonSerializer throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer or String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } - if (seconds >= 0) + if (AllowPreEpoch || seconds >= 0) { DateTime d = UnixEpoch.AddSeconds(seconds); #if HAVE_DATE_TIME_OFFSET - Type t = (nullable) + Type? t = (nullable) ? Nullable.GetUnderlyingType(objectType) : objectType; if (t == typeof(DateTimeOffset)) diff --git a/src/Exceptionless/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/src/Exceptionless/Newtonsoft.Json/Converters/XmlNodeConverter.cs index eef45d0a..7d6678dc 100644 --- a/src/Exceptionless/Newtonsoft.Json/Converters/XmlNodeConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Converters/XmlNodeConverter.cs @@ -79,19 +79,19 @@ public IXmlNode CreateSignificantWhitespace(string? text) return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); } - public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) + public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); } #if HAVE_XML_DOCUMENT_TYPE - public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) + public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); } #endif - public IXmlNode CreateProcessingInstruction(string target, string? data) + public IXmlNode CreateProcessingInstruction(string target, string data) { return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); } @@ -114,7 +114,7 @@ public IXmlNode CreateAttribute(string name, string? value) return attribute; } - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) + public IXmlNode CreateAttribute(string qualifiedName, string? namespaceUri, string? value) { XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)); attribute.Value = value; @@ -153,7 +153,7 @@ public void SetAttributeNode(IXmlNode attribute) _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode!); } - public string GetPrefixOfNamespace(string namespaceUri) + public string? GetPrefixOfNamespace(string namespaceUri) { return _element.GetPrefixOfNamespace(namespaceUri); } @@ -171,15 +171,15 @@ public XmlDeclarationWrapper(XmlDeclaration declaration) _declaration = declaration; } - public string Version => _declaration.Version; + public string? Version => _declaration.Version; - public string Encoding + public string? Encoding { get => _declaration.Encoding; set => _declaration.Encoding = value; } - public string Standalone + public string? Standalone { get => _declaration.Standalone; set => _declaration.Standalone = value; @@ -199,11 +199,11 @@ public XmlDocumentTypeWrapper(XmlDocumentType documentType) public string Name => _documentType.Name; - public string System => _documentType.SystemId; + public string? System => _documentType.SystemId; - public string Public => _documentType.PublicId; + public string? Public => _documentType.PublicId; - public string InternalSubset => _documentType.InternalSubset; + public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; } @@ -285,7 +285,7 @@ public List Attributes } else { - _attributes = new List(_node.Attributes.Count); + _attributes = new List(_node.Attributes!.Count); foreach (XmlAttribute attribute in _node.Attributes) { _attributes.Add(WrapNode(attribute)); @@ -314,7 +314,7 @@ public IXmlNode? ParentNode { get { - XmlNode node = _node is XmlAttribute attribute ? attribute.OwnerElement : _node.ParentNode; + XmlNode? node = _node is XmlAttribute attribute ? attribute.OwnerElement : _node.ParentNode; if (node == null) { @@ -354,38 +354,38 @@ internal interface IXmlDocument : IXmlNode IXmlNode CreateCDataSection(string? data); IXmlNode CreateWhitespace(string? text); IXmlNode CreateSignificantWhitespace(string? text); - IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone); + IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone); #if HAVE_XML_DOCUMENT_TYPE - IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset); + IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset); #endif - IXmlNode CreateProcessingInstruction(string target, string? data); + IXmlNode CreateProcessingInstruction(string target, string data); IXmlElement CreateElement(string elementName); IXmlElement CreateElement(string qualifiedName, string namespaceUri); - IXmlNode CreateAttribute(string name, string? value); - IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value); + IXmlNode CreateAttribute(string name, string value); + IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value); IXmlElement? DocumentElement { get; } } internal interface IXmlDeclaration : IXmlNode { - string Version { get; } - string Encoding { get; set; } - string Standalone { get; set; } + string? Version { get; } + string? Encoding { get; set; } + string? Standalone { get; set; } } internal interface IXmlDocumentType : IXmlNode { string Name { get; } - string System { get; } - string Public { get; } - string InternalSubset { get; } + string? System { get; } + string? Public { get; } + string? InternalSubset { get; } } internal interface IXmlElement : IXmlNode { void SetAttributeNode(IXmlNode attribute); - string GetPrefixOfNamespace(string namespaceUri); + string? GetPrefixOfNamespace(string namespaceUri); bool IsEmpty { get; } } @@ -417,15 +417,15 @@ public XDeclarationWrapper(XDeclaration declaration) public override XmlNodeType NodeType => XmlNodeType.XmlDeclaration; - public string Version => Declaration.Version; + public string? Version => Declaration.Version; - public string Encoding + public string? Encoding { get => Declaration.Encoding; set => Declaration.Encoding = value; } - public string Standalone + public string? Standalone { get => Declaration.Standalone; set => Declaration.Standalone = value; @@ -444,11 +444,11 @@ public XDocumentTypeWrapper(XDocumentType documentType) public string Name => _documentType.Name; - public string System => _documentType.SystemId; + public string? System => _documentType.SystemId; - public string Public => _documentType.PublicId; + public string? Public => _documentType.PublicId; - public string InternalSubset => _documentType.InternalSubset; + public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; } @@ -491,40 +491,40 @@ protected override bool HasChildNodes public IXmlNode CreateComment(string? text) { - return new XObjectWrapper(new XComment(text)); + return new XObjectWrapper(new XComment(text!)); } public IXmlNode CreateTextNode(string? text) { - return new XObjectWrapper(new XText(text)); + return new XObjectWrapper(new XText(text!)); } public IXmlNode CreateCDataSection(string? data) { - return new XObjectWrapper(new XCData(data)); + return new XObjectWrapper(new XCData(data!)); } public IXmlNode CreateWhitespace(string? text) { - return new XObjectWrapper(new XText(text)); + return new XObjectWrapper(new XText(text!)); } public IXmlNode CreateSignificantWhitespace(string? text) { - return new XObjectWrapper(new XText(text)); + return new XObjectWrapper(new XText(text!)); } - public IXmlNode CreateXmlDeclaration(string? version, string? encoding, string? standalone) + public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); } - public IXmlNode CreateXmlDocumentType(string? name, string? publicId, string? systemId, string? internalSubset) + public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); } - public IXmlNode CreateProcessingInstruction(string target, string? data) + public IXmlNode CreateProcessingInstruction(string target, string data) { return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); } @@ -540,12 +540,12 @@ public IXmlElement CreateElement(string qualifiedName, string namespaceUri) return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri))); } - public IXmlNode CreateAttribute(string name, string? value) + public IXmlNode CreateAttribute(string name, string value) { return new XAttributeWrapper(new XAttribute(name, value)); } - public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string? value) + public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value) { string localName = MiscellaneousUtils.GetLocalName(qualifiedName); return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value)); @@ -590,7 +590,7 @@ public XTextWrapper(XText text) public override string? Value { get => Text.Value; - set => Text.Value = value; + set => Text.Value = value ?? string.Empty; } public override IXmlNode? ParentNode @@ -619,7 +619,7 @@ public XCommentWrapper(XComment text) public override string? Value { get => Text.Value; - set => Text.Value = value; + set => Text.Value = value ?? string.Empty; } public override IXmlNode? ParentNode @@ -650,7 +650,7 @@ public XProcessingInstructionWrapper(XProcessingInstruction processingInstructio public override string? Value { get => ProcessingInstruction.Data; - set => ProcessingInstruction.Data = value; + set => ProcessingInstruction.Data = value ?? string.Empty; } } @@ -807,7 +807,7 @@ public XAttributeWrapper(XAttribute attribute) public override string? Value { get => Attribute.Value; - set => Attribute.Value = value; + set => Attribute.Value = value ?? string.Empty; } public override string? LocalName => Attribute.Name.LocalName; @@ -919,14 +919,14 @@ public override IXmlNode AppendChild(IXmlNode newChild) public override string? Value { get => Element.Value; - set => Element.Value = value; + set => Element.Value = value ?? string.Empty; } public override string? LocalName => Element.Name.LocalName; public override string? NamespaceUri => Element.Name.NamespaceName; - public string GetPrefixOfNamespace(string namespaceUri) + public string? GetPrefixOfNamespace(string namespaceUri) { return Element.GetPrefixOfNamespace(namespaceUri); } @@ -1059,7 +1059,7 @@ private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) { if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns") { - manager.AddNamespace(attribute.LocalName, attribute.Value); + manager.AddNamespace(attribute.LocalName!, attribute.Value!); } } } @@ -1078,7 +1078,7 @@ private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) } else { - return XmlConvert.DecodeName(node.LocalName); + return XmlConvert.DecodeName(node.LocalName)!; } } @@ -1131,7 +1131,7 @@ private bool IsArray(IXmlNode node) { if (attribute.LocalName == "Array" && attribute.NamespaceUri == JsonNamespaceUri) { - return XmlConvert.ToBoolean(attribute.Value); + return XmlConvert.ToBoolean(attribute.Value!); } } @@ -1201,7 +1201,7 @@ private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespac } else { - if (!nodesGroupedByName.TryGetValue(currentNodeName, out object value)) + if (!nodesGroupedByName.TryGetValue(currentNodeName, out object? value)) { nodesGroupedByName.Add(currentNodeName, childNode); } @@ -1314,7 +1314,7 @@ private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/") { string namespacePrefix = (attribute.LocalName != "xmlns") - ? XmlConvert.DecodeName(attribute.LocalName) + ? XmlConvert.DecodeName(attribute.LocalName)! : string.Empty; string? namespaceUri = attribute.Value; if (namespaceUri == null) @@ -1654,7 +1654,7 @@ private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode curr case JsonTypeReflector.TypePropertyName: case JsonTypeReflector.ValuePropertyName: string attributeName = propertyName.Substring(1); - string attributePrefix = manager.LookupPrefix(JsonNamespaceUri); + string? attributePrefix = manager.LookupPrefix(JsonNamespaceUri); AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); return; } @@ -1685,7 +1685,9 @@ private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode cu string encodedName = XmlConvert.EncodeName(nameValue.Key); string? attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key); - IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value) : document.CreateAttribute(encodedName, nameValue.Value); + IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) + ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix) ?? string.Empty, nameValue.Value!) + : document.CreateAttribute(encodedName, nameValue.Value!); element.SetAttributeNode(attribute); } @@ -1731,10 +1733,10 @@ private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlN } string encodedName = XmlConvert.EncodeName(attributeName); - string? attributeValue = ConvertTokenToXmlValue(reader); + string attributeValue = ConvertTokenToXmlValue(reader)!; IXmlNode attribute = (!StringUtils.IsNullOrEmpty(attributePrefix)) - ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix), attributeValue) + ? document.CreateAttribute(encodedName, manager.LookupNamespace(attributePrefix)!, attributeValue) : document.CreateAttribute(encodedName, attributeValue); ((IXmlElement)currentNode).SetAttributeNode(attribute); @@ -1874,7 +1876,7 @@ private bool ShouldReadInto(JsonReader reader) switch (reader.TokenType) { case JsonToken.PropertyName: - string attributeName = reader.Value!.ToString(); + string attributeName = reader.Value!.ToString()!; if (!StringUtils.IsNullOrEmpty(attributeName)) { @@ -1896,7 +1898,7 @@ private bool ShouldReadInto(JsonReader reader) if (IsNamespaceAttribute(attributeName, out string? namespacePrefix)) { - manager.AddNamespace(namespacePrefix, attributeValue); + manager.AddNamespace(namespacePrefix, attributeValue!); } break; case '$': @@ -1909,7 +1911,7 @@ private bool ShouldReadInto(JsonReader reader) case JsonTypeReflector.ValuePropertyName: // check that JsonNamespaceUri is in scope // if it isn't then add it to document and namespace manager - string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri); + string? jsonPrefix = manager.LookupPrefix(JsonNamespaceUri); if (jsonPrefix == null) { if (attributeNameValues == null) @@ -2008,12 +2010,17 @@ private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNod } } + if (version == null) + { + throw JsonSerializationException.Create(reader, "Version not specified for XML declaration."); + } + IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone); currentNode.AppendChild(declaration); } else { - IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)); + IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)!); currentNode.AppendChild(instruction); } } @@ -2050,6 +2057,11 @@ private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNo } } + if (name == null) + { + throw JsonSerializationException.Create(reader, "Name not specified for XML document type."); + } + IXmlNode documentType = document.CreateXmlDocumentType(name, publicId, systemId, internalSubset); currentNode.AppendChild(documentType); } @@ -2058,7 +2070,7 @@ private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNo private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) { string encodeName = EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName); - string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); + string? ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); IXmlElement element = (!StringUtils.IsNullOrEmpty(ns)) ? document.CreateElement(encodeName, ns) : document.CreateElement(encodeName); @@ -2077,7 +2089,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); } - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartArray) @@ -2092,7 +2104,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp if (count == 1 && WriteArrayAttribute) { MiscellaneousUtils.GetQualifiedNameParts(propertyName, out string? elementPrefix, out string localName); - string ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); + string? ns = StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix); foreach (IXmlNode childNode in currentNode.ChildNodes) { @@ -2110,7 +2122,7 @@ private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamesp } continue; case JsonToken.StartConstructor: - string constructorName = reader.Value!.ToString(); + string constructorName = reader.Value!.ToString()!; while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) { diff --git a/src/Exceptionless/Newtonsoft.Json/DefaultJsonNameTable.cs b/src/Exceptionless/Newtonsoft.Json/DefaultJsonNameTable.cs index ab239787..9b7d44e3 100644 --- a/src/Exceptionless/Newtonsoft.Json/DefaultJsonNameTable.cs +++ b/src/Exceptionless/Newtonsoft.Json/DefaultJsonNameTable.cs @@ -24,6 +24,7 @@ #endregion using System; +using System.Threading; namespace Exceptionless.Json { @@ -78,7 +79,12 @@ public DefaultJsonNameTable() hashCode -= hashCode >> 5; // make sure index is evaluated before accessing _entries, otherwise potential race condition causing IndexOutOfRangeException - var index = hashCode & _mask; +#if NET20 || NET35 || NET40 + int mask = Thread.VolatileRead(ref _mask); +#else + int mask = Volatile.Read(ref _mask); +#endif + var index = hashCode & mask; var entries = _entries; for (Entry entry = entries[index]; entry != null; entry = entry.Next) @@ -160,7 +166,12 @@ private void Grow() } } _entries = newEntries; - _mask = newMask; + +#if NET20 || NET35 || NET40 + Thread.VolatileWrite(ref _mask, newMask); +#else + Volatile.Write(ref _mask, newMask); +#endif } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) diff --git a/src/Exceptionless/Newtonsoft.Json/JsonConvert.cs b/src/Exceptionless/Newtonsoft.Json/JsonConvert.cs index 919c4b86..02dcc86a 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonConvert.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonConvert.cs @@ -302,7 +302,7 @@ internal static string ToString(double value, FloatFormatHandling floatFormatHan private static string EnsureDecimalPlace(double value, string text) { - if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) + if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } @@ -312,7 +312,7 @@ private static string EnsureDecimalPlace(double value, string text) private static string EnsureDecimalPlace(string text) { - if (text.IndexOf('.') != -1) + if (StringUtils.IndexOf(text, '.') != -1) { return text; } @@ -587,7 +587,7 @@ public static string SerializeObject(object? value, Formatting formatting, param /// A JSON string representation of the object. /// [DebuggerStepThrough] - public static string SerializeObject(object? value, JsonSerializerSettings settings) + public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } @@ -715,7 +715,7 @@ private static string SerializeObjectInternal(object? value, Type? type, JsonSer /// The JSON to deserialize. /// The deserialized object from the JSON string. [DebuggerStepThrough] - public static T DeserializeObject(string value) + public static T? DeserializeObject(string value) { return DeserializeObject(value, (JsonSerializerSettings?)null); } @@ -732,7 +732,7 @@ public static T DeserializeObject(string value) /// The anonymous type object. /// The deserialized anonymous type from the JSON string. [DebuggerStepThrough] - public static T DeserializeAnonymousType(string value, T anonymousTypeObject) + public static T? DeserializeAnonymousType(string value, T anonymousTypeObject) { return DeserializeObject(value); } @@ -753,7 +753,7 @@ public static T DeserializeAnonymousType(string value, T anonymousTypeObject) /// /// The deserialized anonymous type from the JSON string. [DebuggerStepThrough] - public static T DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings) + public static T? DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject(value, settings); } @@ -766,12 +766,9 @@ public static T DeserializeAnonymousType(string value, T anonymousTypeObject, /// Converters to use while deserializing. /// The deserialized object from the JSON string. [DebuggerStepThrough] - [return: MaybeNull] - public static T DeserializeObject(string value, params JsonConverter[] converters) + public static T? DeserializeObject(string value, params JsonConverter[] converters) { -#pragma warning disable CS8601 // Possible null reference assignment. - return (T)DeserializeObject(value, typeof(T), converters); -#pragma warning restore CS8601 // Possible null reference assignment. + return (T?)DeserializeObject(value, typeof(T), converters); } /// @@ -785,12 +782,9 @@ public static T DeserializeObject(string value, params JsonConverter[] conver /// /// The deserialized object from the JSON string. [DebuggerStepThrough] - [return: MaybeNull] - public static T DeserializeObject(string value, JsonSerializerSettings? settings) + public static T? DeserializeObject(string value, JsonSerializerSettings? settings) { -#pragma warning disable CS8601 // Possible null reference assignment. - return (T)DeserializeObject(value, typeof(T), settings); -#pragma warning restore CS8601 // Possible null reference assignment. + return (T?)DeserializeObject(value, typeof(T), settings); } /// diff --git a/src/Exceptionless/Newtonsoft.Json/JsonConverter.cs b/src/Exceptionless/Newtonsoft.Json/JsonConverter.cs index 3a334f79..6b370e6e 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonConverter.cs @@ -94,9 +94,7 @@ public sealed override void WriteJson(JsonWriter writer, object? value, JsonSeri { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } -#pragma warning disable CS8601 // Possible null reference assignment. - WriteJson(writer, (T)value, serializer); -#pragma warning restore CS8601 // Possible null reference assignment. + WriteJson(writer, (T?)value, serializer); } /// @@ -105,7 +103,7 @@ public sealed override void WriteJson(JsonWriter writer, object? value, JsonSeri /// The to write to. /// The value. /// The calling serializer. - public abstract void WriteJson(JsonWriter writer, [AllowNull]T value, JsonSerializer serializer); + public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); /// /// Reads the JSON representation of the object. @@ -122,9 +120,7 @@ public sealed override void WriteJson(JsonWriter writer, object? value, JsonSeri { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } -#pragma warning disable CS8601 // Possible null reference assignment. - return ReadJson(reader, objectType, existingIsNull ? default : (T)existingValue, !existingIsNull, serializer); -#pragma warning restore CS8601 // Possible null reference assignment. + return ReadJson(reader, objectType, existingIsNull ? default : (T?)existingValue, !existingIsNull, serializer); } /// @@ -136,7 +132,7 @@ public sealed override void WriteJson(JsonWriter writer, object? value, JsonSeri /// The existing value has a value. /// The calling serializer. /// The object value. - public abstract T ReadJson(JsonReader reader, Type objectType, [AllowNull]T existingValue, bool hasExistingValue, JsonSerializer serializer); + public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); /// /// Determines whether this instance can convert the specified object type. diff --git a/src/Exceptionless/Newtonsoft.Json/JsonReader.Async.cs b/src/Exceptionless/Newtonsoft.Json/JsonReader.Async.cs index 8bf94899..b67b32e4 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonReader.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonReader.Async.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -34,7 +34,25 @@ namespace Exceptionless.Json { internal abstract partial class JsonReader +#if HAVE_ASYNC_DISPOSABLE + : IAsyncDisposable +#endif { +#if HAVE_ASYNC_DISPOSABLE + ValueTask IAsyncDisposable.DisposeAsync() + { + try + { + Dispose(true); + return default; + } + catch (Exception exc) + { + return ValueTask.FromException(exc); + } + } +#endif + /// /// Asynchronously reads the next JSON token from the source. /// diff --git a/src/Exceptionless/Newtonsoft.Json/JsonReader.cs b/src/Exceptionless/Newtonsoft.Json/JsonReader.cs index b3e38b17..4622cd69 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonReader.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonReader.cs @@ -227,6 +227,8 @@ public string? DateFormatString /// /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + /// A null value means there is no maximum. + /// The default value is 64. /// public int? MaxDepth { @@ -327,6 +329,7 @@ protected JsonReader() _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; + _maxDepth = 64; CloseInput = true; } @@ -493,7 +496,7 @@ private JsonContainerType Peek() } else { - s = v is Uri uri ? uri.OriginalString : v.ToString(); + s = v is Uri uri ? uri.OriginalString : v.ToString()!; } SetToken(JsonToken.String, s, false); @@ -937,7 +940,7 @@ internal void ReadIntoWrappedTypeObject() if (Value != null && Value.ToString() == JsonTypeReflector.TypePropertyName) { ReaderReadAndAssert(); - if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) + if (Value != null && Value.ToString()!.StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == JsonTypeReflector.ValuePropertyName) diff --git a/src/Exceptionless/Newtonsoft.Json/JsonSerializer.cs b/src/Exceptionless/Newtonsoft.Json/JsonSerializer.cs index 8fc19b66..ebd8c53d 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonSerializer.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonSerializer.cs @@ -514,7 +514,7 @@ public virtual CultureInfo Culture /// /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . /// A null value means there is no maximum. - /// The default value is null. + /// The default value is 64. /// public virtual int? MaxDepth { @@ -865,12 +865,9 @@ internal virtual void PopulateInternal(JsonReader reader, object target) /// The type of the object to deserialize. /// The instance of being deserialized. [DebuggerStepThrough] - [return: MaybeNull] - public T Deserialize(JsonReader reader) + public T? Deserialize(JsonReader reader) { -#pragma warning disable CS8601 // Possible null reference assignment. - return (T)Deserialize(reader, typeof(T)); -#pragma warning restore CS8601 // Possible null reference assignment. + return (T?)Deserialize(reader, typeof(T)); } /// @@ -916,7 +913,7 @@ public T Deserialize(JsonReader reader) return value; } - private void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) + internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { diff --git a/src/Exceptionless/Newtonsoft.Json/JsonSerializerSettings.cs b/src/Exceptionless/Newtonsoft.Json/JsonSerializerSettings.cs index 0c0f0f50..6edc7b58 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonSerializerSettings.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonSerializerSettings.cs @@ -31,6 +31,12 @@ using Exceptionless.Json.Serialization; using System.Runtime.Serialization; using System.Diagnostics; +using System.Runtime; +#if !HAVE_LINQ +using Exceptionless.Json.Utilities.LinqBridge; +#else +using System.Linq; +#endif namespace Exceptionless.Json { @@ -61,6 +67,7 @@ internal class JsonSerializerSettings internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; @@ -325,11 +332,11 @@ public string DateFormatString /// /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . /// A null value means there is no maximum. - /// The default value is null. + /// The default value is 64. /// public int? MaxDepth { - get => _maxDepth; + get => _maxDepthSet ? _maxDepth : DefaultMaxDepth; set { if (value <= 0) @@ -451,5 +458,44 @@ public JsonSerializerSettings() { Converters = new List(); } + + /// + /// Initializes a new instance of the class + /// using values copied from the passed in . + /// + public JsonSerializerSettings(JsonSerializerSettings original) + { + _floatParseHandling = original._floatParseHandling; + _floatFormatHandling = original._floatFormatHandling; + _dateParseHandling = original._dateParseHandling; + _dateTimeZoneHandling = original._dateTimeZoneHandling; + _dateFormatHandling = original._dateFormatHandling; + _formatting = original._formatting; + _maxDepth = original._maxDepth; + _maxDepthSet = original._maxDepthSet; + _dateFormatString = original._dateFormatString; + _dateFormatStringSet = original._dateFormatStringSet; + _context = original._context; + Error = original.Error; + SerializationBinder = original.SerializationBinder; + TraceWriter = original.TraceWriter; + _culture = original._culture; + ReferenceResolverProvider = original.ReferenceResolverProvider; + EqualityComparer = original.EqualityComparer; + ContractResolver = original.ContractResolver; + _constructorHandling = original._constructorHandling; + _typeNameAssemblyFormatHandling = original._typeNameAssemblyFormatHandling; + _metadataPropertyHandling = original._metadataPropertyHandling; + _typeNameHandling = original._typeNameHandling; + _preserveReferencesHandling = original._preserveReferencesHandling; + Converters = original.Converters.ToList(); + _defaultValueHandling = original._defaultValueHandling; + _nullValueHandling = original._nullValueHandling; + _objectCreationHandling = original._objectCreationHandling; + _missingMemberHandling = original._missingMemberHandling; + _referenceLoopHandling = original._referenceLoopHandling; + _checkAdditionalContent = original._checkAdditionalContent; + _stringEscapeHandling = original._stringEscapeHandling; + } } } diff --git a/src/Exceptionless/Newtonsoft.Json/JsonTextReader.Async.cs b/src/Exceptionless/Newtonsoft.Json/JsonTextReader.Async.cs index 05a9620e..ca0623be 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonTextReader.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonTextReader.Async.cs @@ -79,7 +79,7 @@ internal Task DoReadAsync(CancellationToken cancellationToken) return ParseObjectAsync(cancellationToken); case State.PostValue: Task task = ParsePostValueAsync(false, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { if (task.Result) { @@ -542,7 +542,7 @@ private Task ProcessCarriageReturnAsync(bool append, CancellationToken cancellat _charPos++; Task task = EnsureCharsAsync(1, append, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { SetNewLine(task.Result); return AsyncUtils.CompletedTask; @@ -1680,7 +1680,7 @@ private async Task ReadIntoWrappedTypeObjectAsync(CancellationToken cancellation if (Value != null && Value.ToString() == JsonTypeReflector.TypePropertyName) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); - if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) + if (Value != null && Value.ToString()!.StartsWith("System.Byte[]", StringComparison.Ordinal)) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(false); if (Value.ToString() == JsonTypeReflector.ValuePropertyName) diff --git a/src/Exceptionless/Newtonsoft.Json/JsonTextReader.cs b/src/Exceptionless/Newtonsoft.Json/JsonTextReader.cs index ba7f5c72..57486722 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonTextReader.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonTextReader.cs @@ -841,7 +841,7 @@ private JsonReaderException CreateUnexpectedCharacterException(char c) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } - SetToken(JsonToken.Boolean, isTrue); + SetToken(JsonToken.Boolean, BoxedPrimitives.Get(isTrue)); return isTrue; case '/': ParseComment(false); @@ -2030,7 +2030,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (singleDigit) { // digit char values start at 48 - numberValue = firstChar - 48; + numberValue = BoxedPrimitives.Get(firstChar - 48); } else if (nonBase10) { @@ -2040,7 +2040,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit { int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(number, 16) : Convert.ToInt32(number, 8); - numberValue = integer; + numberValue = BoxedPrimitives.Get(integer); } catch (Exception ex) { @@ -2052,7 +2052,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out int value); if (parseResult == ParseResult.Success) { - numberValue = value; + numberValue = BoxedPrimitives.Get(value); } else if (parseResult == ParseResult.Overflow) { @@ -2072,7 +2072,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (singleDigit) { // digit char values start at 48 - numberValue = (decimal)firstChar - 48; + numberValue = BoxedPrimitives.Get((decimal)firstChar - 48); } else if (nonBase10) { @@ -2083,7 +2083,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit // decimal.Parse doesn't support parsing hexadecimal values long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8); - numberValue = Convert.ToDecimal(integer); + numberValue = BoxedPrimitives.Get(Convert.ToDecimal(integer)); } catch (Exception ex) { @@ -2095,7 +2095,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit ParseResult parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal value); if (parseResult == ParseResult.Success) { - numberValue = value; + numberValue = BoxedPrimitives.Get(value); } else { @@ -2111,7 +2111,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (singleDigit) { // digit char values start at 48 - numberValue = (double)firstChar - 48; + numberValue = BoxedPrimitives.Get((double)firstChar - 48); } else if (nonBase10) { @@ -2122,7 +2122,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit // double.Parse doesn't support parsing hexadecimal values long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8); - numberValue = Convert.ToDouble(integer); + numberValue = BoxedPrimitives.Get(Convert.ToDouble(integer)); } catch (Exception ex) { @@ -2135,7 +2135,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double value)) { - numberValue = value; + numberValue = BoxedPrimitives.Get(value); } else { @@ -2152,7 +2152,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (singleDigit) { // digit char values start at 48 - numberValue = (long)firstChar - 48; + numberValue = BoxedPrimitives.Get((long)firstChar - 48); numberType = JsonToken.Integer; } else if (nonBase10) @@ -2161,7 +2161,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit try { - numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8); + numberValue = BoxedPrimitives.Get(number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8)); } catch (Exception ex) { @@ -2175,7 +2175,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out long value); if (parseResult == ParseResult.Success) { - numberValue = value; + numberValue = BoxedPrimitives.Get(value); numberType = JsonToken.Integer; } else if (parseResult == ParseResult.Overflow) @@ -2201,7 +2201,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out decimal d); if (parseResult == ParseResult.Success) { - numberValue = d; + numberValue = BoxedPrimitives.Get(d); } else { @@ -2214,7 +2214,7 @@ private void ParseReadNumber(ReadType readType, char firstChar, int initialPosit if (double.TryParse(number, NumberStyles.Float, CultureInfo.InvariantCulture, out double d)) { - numberValue = d; + numberValue = BoxedPrimitives.Get(d); } else { @@ -2353,6 +2353,7 @@ private void EndComment(bool setToken, int initialPosition, int endPosition) { if (setToken) { + MiscellaneousUtils.Assert(_chars != null); SetToken(JsonToken.Comment, new string(_chars, initialPosition, endPosition - initialPosition)); } } @@ -2455,7 +2456,7 @@ private void ParseTrue() // or the text ends if (MatchValueWithTrailingSeparator(JsonConvert.True)) { - SetToken(JsonToken.Boolean, true); + SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanTrue); } else { @@ -2491,7 +2492,7 @@ private void ParseFalse() { if (MatchValueWithTrailingSeparator(JsonConvert.False)) { - SetToken(JsonToken.Boolean, false); + SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanFalse); } else { @@ -2514,7 +2515,7 @@ private object ParseNumberNegativeInfinity(ReadType readType, bool matched) case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { - SetToken(JsonToken.Float, double.NegativeInfinity); + SetToken(JsonToken.Float, BoxedPrimitives.DoubleNegativeInfinity); return double.NegativeInfinity; } break; @@ -2543,7 +2544,7 @@ private object ParseNumberPositiveInfinity(ReadType readType, bool matched) case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { - SetToken(JsonToken.Float, double.PositiveInfinity); + SetToken(JsonToken.Float, BoxedPrimitives.DoublePositiveInfinity); return double.PositiveInfinity; } break; @@ -2573,7 +2574,7 @@ private object ParseNumberNaN(ReadType readType, bool matched) case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { - SetToken(JsonToken.Float, double.NaN); + SetToken(JsonToken.Float, BoxedPrimitives.DoubleNaN); return double.NaN; } break; diff --git a/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.Async.cs b/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.Async.cs index 80d4906c..cae058ba 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.Async.cs @@ -132,7 +132,34 @@ internal async Task DoCloseAsync(CancellationToken cancellationToken) await WriteEndAsync(cancellationToken).ConfigureAwait(false); } - CloseBufferAndWriter(); + await CloseBufferAndWriterAsync().ConfigureAwait(false); + } + + private async Task CloseBufferAndWriterAsync() + { + if (_writeBuffer != null) + { + BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); + _writeBuffer = null; + } + + if (CloseOutput && _writer != null) + { +#if HAVE_ASYNC_DISPOSABLE + await _writer.DisposeAsync().ConfigureAwait(false); +#else + // DisposeAsync isn't available. Instead, flush any remaining content with FlushAsync + // to prevent Close/Dispose from making a blocking flush. + // + // No cancellation token on TextWriter.FlushAsync?! + await _writer.FlushAsync().ConfigureAwait(false); +#if HAVE_STREAM_READER_WRITER_CLOSE + _writer.Close(); +#else + _writer.Dispose(); +#endif +#endif + } } /// @@ -190,7 +217,7 @@ private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, Canc private Task WriteValueInternalAsync(JsonToken token, string value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(token, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(value, cancellationToken); } @@ -270,7 +297,7 @@ private Task WriteDigitsAsync(ulong uvalue, bool negative, CancellationToken can private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Integer, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return WriteDigitsAsync(uvalue, negative, cancellationToken); } @@ -321,13 +348,13 @@ public override Task WritePropertyNameAsync(string name, CancellationToken cance internal Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) { Task task = InternalWritePropertyNameAsync(name, cancellationToken); - if (!task.IsCompletedSucessfully()) + if (!task.IsCompletedSuccessfully()) { return DoWritePropertyNameAsync(task, name, cancellationToken); } task = WriteEscapedStringAsync(name, _quoteName, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(':', cancellationToken); } @@ -399,7 +426,7 @@ public override Task WriteStartArrayAsync(CancellationToken cancellationToken = internal Task DoWriteStartArrayAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartArray, JsonContainerType.Array, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('[', cancellationToken); } @@ -429,7 +456,7 @@ public override Task WriteStartObjectAsync(CancellationToken cancellationToken = internal Task DoWriteStartObjectAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartObject, JsonContainerType.Object, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('{', cancellationToken); } @@ -481,7 +508,7 @@ public override Task WriteUndefinedAsync(CancellationToken cancellationToken = d internal Task DoWriteUndefinedAsync(CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Undefined, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(JsonConvert.Undefined, cancellationToken); } @@ -1058,7 +1085,7 @@ public override Task WriteValueAsync(string? value, CancellationToken cancellati internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return value == null ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, true, cancellationToken); } @@ -1193,7 +1220,7 @@ public override Task WriteValueAsync(Uri? value, CancellationToken cancellationT internal Task WriteValueNotNullAsync(Uri value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return WriteEscapedStringAsync(value.OriginalString, true, cancellationToken); } @@ -1314,7 +1341,7 @@ internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationT { UpdateScopeWithFinishedValue(); Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return WriteRawAsync(json, cancellationToken); } diff --git a/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.cs b/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.cs index aaac27d9..cb0f9365 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonTextWriter.cs @@ -325,6 +325,7 @@ protected override void WriteIndent() int newLineLen = SetIndentChars(); + MiscellaneousUtils.Assert(_indentChars != null); _writer.Write(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, IndentCharBufferSize)); while ((currentIndentCount -= IndentCharBufferSize) > 0) @@ -637,6 +638,7 @@ public override void WriteValue(DateTime value) { int length = WriteValueToBuffer(value); + MiscellaneousUtils.Assert(_writeBuffer != null); _writer.Write(_writeBuffer, 0, length); } else @@ -692,6 +694,7 @@ public override void WriteValue(DateTimeOffset value) { int length = WriteValueToBuffer(value); + MiscellaneousUtils.Assert(_writeBuffer != null); _writer.Write(_writeBuffer, 0, length); } else @@ -829,6 +832,8 @@ private void WriteIntegerValue(ulong value, bool negative) else { int length = WriteNumberToBuffer(value, negative); + + MiscellaneousUtils.Assert(_writeBuffer != null); _writer.Write(_writeBuffer, 0, length); } } @@ -887,6 +892,8 @@ private void WriteIntegerValue(uint value, bool negative) else { int length = WriteNumberToBuffer(value, negative); + + MiscellaneousUtils.Assert(_writeBuffer != null); _writer.Write(_writeBuffer, 0, length); } } diff --git a/src/Exceptionless/Newtonsoft.Json/JsonWriter.Async.cs b/src/Exceptionless/Newtonsoft.Json/JsonWriter.Async.cs index 523f6809..d93344ce 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonWriter.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonWriter.Async.cs @@ -37,7 +37,20 @@ namespace Exceptionless.Json { internal abstract partial class JsonWriter +#if HAVE_ASYNC_DISPOSABLE + : IAsyncDisposable +#endif { +#if HAVE_ASYNC_DISPOSABLE + async ValueTask IAsyncDisposable.DisposeAsync() + { + if (_currentState != State.Closed) + { + await CloseAsync().ConfigureAwait(false); + } + } +#endif + internal Task AutoCompleteAsync(JsonToken tokenBeingWritten, CancellationToken cancellationToken) { State oldState = _currentState; @@ -291,7 +304,7 @@ internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken ca if (_currentState == State.Property) { t = WriteNullAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) + if (!t.IsCompletedSuccessfully()) { return AwaitProperty(t, levelsToComplete, token, cancellationToken); } @@ -302,7 +315,7 @@ internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken ca if (_currentState != State.ObjectStart && _currentState != State.ArrayStart) { t = WriteIndentAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) + if (!t.IsCompletedSuccessfully()) { return AwaitIndent(t, levelsToComplete, token, cancellationToken); } @@ -310,7 +323,7 @@ internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken ca } t = WriteEndAsync(token, cancellationToken); - if (!t.IsCompletedSucessfully()) + if (!t.IsCompletedSuccessfully()) { return AwaitEnd(t, levelsToComplete, cancellationToken); } @@ -691,10 +704,10 @@ public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken ca return WriteStartArrayAsync(cancellationToken); case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WriteStartConstructorAsync(value.ToString(), cancellationToken); + return WriteStartConstructorAsync(value.ToString()!, cancellationToken); case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, nameof(value)); - return WritePropertyNameAsync(value.ToString(), cancellationToken); + return WritePropertyNameAsync(value.ToString()!, cancellationToken); case JsonToken.Comment: return WriteCommentAsync(value?.ToString(), cancellationToken); case JsonToken.Integer: diff --git a/src/Exceptionless/Newtonsoft.Json/JsonWriter.cs b/src/Exceptionless/Newtonsoft.Json/JsonWriter.cs index bf151145..acb26cf2 100644 --- a/src/Exceptionless/Newtonsoft.Json/JsonWriter.cs +++ b/src/Exceptionless/Newtonsoft.Json/JsonWriter.cs @@ -62,7 +62,7 @@ internal enum State // array that gives a new state based on the current state an the token being written private static readonly State[][] StateArray; - internal static readonly State[][] StateArrayTempate = new[] + internal static readonly State[][] StateArrayTemplate = new[] { // Start PropertyName ObjectStart Object ArrayStart Array ConstructorStart Constructor Closed Error // @@ -78,9 +78,9 @@ internal enum State internal static State[][] BuildStateArray() { - List allStates = StateArrayTempate.ToList(); - State[] errorStates = StateArrayTempate[0]; - State[] valueStates = StateArrayTempate[7]; + List allStates = StateArrayTemplate.ToList(); + State[] errorStates = StateArrayTemplate[0]; + State[] valueStates = StateArrayTemplate[7]; EnumInfo enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken)); @@ -545,11 +545,11 @@ public void WriteToken(JsonToken token, object? value) break; case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, nameof(value)); - WriteStartConstructor(value.ToString()); + WriteStartConstructor(value.ToString()!); break; case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, nameof(value)); - WritePropertyName(value.ToString()); + WritePropertyName(value.ToString()!); break; case JsonToken.Comment: WriteComment(value?.ToString()); @@ -587,8 +587,9 @@ public void WriteToken(JsonToken token, object? value) } break; case JsonToken.String: - ValidationUtils.ArgumentNotNull(value, nameof(value)); - WriteValue(value.ToString()); + // Allow for a null string. This matches JTokenReader behavior which can read + // a JsonToken.String with a null value. + WriteValue(value?.ToString()); break; case JsonToken.Boolean: ValidationUtils.ArgumentNotNull(value, nameof(value)); diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/Extensions.cs b/src/Exceptionless/Newtonsoft.Json/Linq/Extensions.cs index 8fc00645..57a602fc 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/Extensions.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/Extensions.cs @@ -115,7 +115,7 @@ public static IJEnumerable Properties(this IEnumerable sourc /// An of that contains the values of every token in the source collection with the given key. public static IJEnumerable Values(this IEnumerable source, object? key) { - return Values(source, key).AsJEnumerable(); + return Values(source, key)!.AsJEnumerable(); } /// @@ -135,7 +135,7 @@ public static IJEnumerable Values(this IEnumerable source) /// An of that contains the source collection. /// The token key. /// An that contains the converted values of every token in the source collection with the given key. - public static IEnumerable Values(this IEnumerable source, object key) + public static IEnumerable Values(this IEnumerable source, object key) { return Values(source, key); } @@ -146,7 +146,7 @@ public static IEnumerable Values(this IEnumerable source, object k /// The type to convert the values to. /// An of that contains the source collection. /// An that contains the converted values of every token in the source collection. - public static IEnumerable Values(this IEnumerable source) + public static IEnumerable Values(this IEnumerable source) { return Values(source, null); } @@ -157,7 +157,7 @@ public static IEnumerable Values(this IEnumerable source) /// The type to convert the value to. /// A cast as a of . /// A converted value. - public static U Value(this IEnumerable value) + public static U? Value(this IEnumerable value) { return value.Value(); } @@ -169,7 +169,7 @@ public static U Value(this IEnumerable value) /// The type to convert the value to. /// A cast as a of . /// A converted value. - public static U Value(this IEnumerable value) where T : JToken + public static U? Value(this IEnumerable value) where T : JToken { ValidationUtils.ArgumentNotNull(value, nameof(value)); @@ -181,7 +181,7 @@ public static U Value(this IEnumerable value) where T : JToken return token.Convert(); } - internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken + internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken { ValidationUtils.ArgumentNotNull(source, nameof(source)); @@ -226,7 +226,7 @@ internal static IEnumerable Values(this IEnumerable source, object? /// An of that contains the values of every token in the source collection. public static IJEnumerable Children(this IEnumerable source) where T : JToken { - return Children(source).AsJEnumerable(); + return Children(source)!.AsJEnumerable(); } /// @@ -236,14 +236,14 @@ public static IJEnumerable Children(this IEnumerable source) where /// The type to convert the values to. /// The source collection type. /// An that contains the converted values of every token in the source collection. - public static IEnumerable Children(this IEnumerable source) where T : JToken + public static IEnumerable Children(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, nameof(source)); return source.SelectMany(c => c.Children()).Convert(); } - internal static IEnumerable Convert(this IEnumerable source) where T : JToken + internal static IEnumerable Convert(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, nameof(source)); @@ -253,8 +253,7 @@ internal static IEnumerable Convert(this IEnumerable source) where T } } - [return: MaybeNull] - internal static U Convert(this T token) where T : JToken? + internal static U? Convert(this T token) where T : JToken? { if (token == null) { @@ -292,10 +291,10 @@ internal static U Convert(this T token) where T : JToken? #pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. } - targetType = Nullable.GetUnderlyingType(targetType); + targetType = Nullable.GetUnderlyingType(targetType)!; } - return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture); + return (U?)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture); } } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JArray.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JArray.cs index f12e20aa..5b42204c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JArray.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JArray.cs @@ -66,7 +66,12 @@ public JArray() /// /// A object to copy from. public JArray(JArray other) - : base(other) + : base(other, settings: null) + { + } + + internal JArray(JArray other, JsonCloneSettings? settings) + : base(other, settings) { } @@ -93,9 +98,9 @@ internal override bool DeepEquals(JToken node) return (node is JArray t && ContentsEqual(t)); } - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings = null) { - return new JArray(this); + return new JArray(this, settings); } /// @@ -309,7 +314,7 @@ public int IndexOf(JToken item) /// public void Insert(int index, JToken item) { - InsertItem(index, item, false); + InsertItem(index, item, false, copyAnnotations: true); } /// diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JConstructor.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JConstructor.cs index fb684973..cf66ed7b 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JConstructor.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JConstructor.cs @@ -97,7 +97,13 @@ public JConstructor() /// /// A object to copy from. public JConstructor(JConstructor other) - : base(other) + : base(other, settings: null) + { + _name = other.Name; + } + + internal JConstructor(JConstructor other, JsonCloneSettings? settings) + : base(other, settings) { _name = other.Name; } @@ -147,9 +153,9 @@ internal override bool DeepEquals(JToken node) return (node is JConstructor c && _name == c.Name && ContentsEqual(c)); } - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings = null) { - return new JConstructor(this); + return new JConstructor(this, settings); } /// @@ -202,7 +208,13 @@ public override JToken? this[object key] internal override int GetDeepHashCode() { - return (_name?.GetHashCode() ?? 0) ^ ContentsHashCode(); + int hash; +#if HAVE_GETHASHCODE_STRING_COMPARISON + hash = _name?.GetHashCode(StringComparison.Ordinal) ?? 0; +#else + hash = _name?.GetHashCode() ?? 0; +#endif + return hash ^ ContentsHashCode(); } /// diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.Async.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.Async.cs index 64446b0f..a1992628 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.Async.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -109,7 +109,7 @@ private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? set parent = parent.Parent; break; case JsonToken.StartConstructor: - JConstructor constructor = new JConstructor(reader.Value!.ToString()); + JConstructor constructor = new JConstructor(reader.Value!.ToString()!); constructor.SetLineInfo(lineInfo, settings); parent.Add(constructor); parent = constructor; diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.cs index c35a38f5..0329de60 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JContainer.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -47,7 +47,7 @@ namespace Exceptionless.Json.Linq /// /// Represents a token that can contain other tokens. /// - internal abstract partial class JContainer : JToken, IList +    internal abstract partial class JContainer : JToken, IList #if HAVE_COMPONENT_MODEL , ITypedList, IBindingList #endif @@ -84,7 +84,7 @@ public event AddingNewEventHandler AddingNew /// /// Occurs when the items list of the collection has changed, or the collection is reset. /// - public event NotifyCollectionChangedEventHandler CollectionChanged + public event NotifyCollectionChangedEventHandler? CollectionChanged { add { _collectionChanged += value; } remove { _collectionChanged -= value; } @@ -106,15 +106,22 @@ internal JContainer() { } - internal JContainer(JContainer other) + internal JContainer(JContainer other, JsonCloneSettings? settings) : this() { ValidationUtils.ArgumentNotNull(other, nameof(other)); + bool copyAnnotations = settings?.CopyAnnotations ?? true; + + if (copyAnnotations) + { + CopyAnnotations(this, other); + } + int i = 0; foreach (JToken child in other) { - AddInternal(i, child, false); + TryAddInternal(i, child, false, copyAnnotations); i++; } } @@ -273,7 +280,7 @@ public override JEnumerable Children() /// /// A containing the child values of this , in document order. /// - public override IEnumerable Values() + public override IEnumerable Values() where T : default { return ChildrenTokens.Convert(); } @@ -316,12 +323,12 @@ internal IEnumerable GetDescendants(bool self) } } - internal bool IsMultiContent([NotNull]object? content) + internal bool IsMultiContent([NotNullWhen(true)]object? content) { return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[])); } - internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) + internal JToken EnsureParentToken(JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item == null) { @@ -339,7 +346,12 @@ internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) // the item is being added to the root parent of itself if (item.Parent != null || item == this || (item.HasValues && Root == item)) { - item = item.CloneToken(); + // Avoid allocating settings when copy annotations is false. + JsonCloneSettings? settings = copyAnnotations + ? null + : JsonCloneSettings.SkipCopyAnnotations; + + item = item.CloneToken(settings); } return item; @@ -347,7 +359,7 @@ internal JToken EnsureParentToken(JToken? item, bool skipParentCheck) internal abstract int IndexOfItem(JToken? item); - internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck) + internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { IList children = ChildrenTokens; @@ -358,7 +370,7 @@ internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck) CheckReentrancy(); - item = EnsureParentToken(item, skipParentCheck); + item = EnsureParentToken(item, skipParentCheck, copyAnnotations); JToken? previous = (index == 0) ? null : children[index - 1]; // haven't inserted new token yet so next token is still at the inserting index @@ -394,6 +406,8 @@ internal virtual void InsertItem(int index, JToken? item, bool skipParentCheck) OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); } #endif + + return true; } internal virtual void RemoveItemAt(int index) @@ -486,7 +500,7 @@ internal virtual void SetItem(int index, JToken? item) CheckReentrancy(); - item = EnsureParentToken(item, false); + item = EnsureParentToken(item, false, copyAnnotations: true); ValidateToken(item, existing); @@ -631,12 +645,17 @@ internal virtual void ValidateToken(JToken o, JToken? existing) /// The content to be added. public virtual void Add(object? content) { - AddInternal(ChildrenTokens.Count, content, false); + TryAddInternal(ChildrenTokens.Count, content, false, copyAnnotations: true); + } + + internal bool TryAdd(object? content) + { + return TryAddInternal(ChildrenTokens.Count, content, false, copyAnnotations: true); } internal void AddAndSkipParentCheck(JToken token) { - AddInternal(ChildrenTokens.Count, token, true); + TryAddInternal(ChildrenTokens.Count, token, true, copyAnnotations: true); } /// @@ -645,10 +664,10 @@ internal void AddAndSkipParentCheck(JToken token) /// The content to be added. public void AddFirst(object? content) { - AddInternal(0, content, false); + TryAddInternal(0, content, false, copyAnnotations: true); } - internal void AddInternal(int index, object? content, bool skipParentCheck) + internal bool TryAddInternal(int index, object? content, bool skipParentCheck, bool copyAnnotations) { if (IsMultiContent(content)) { @@ -657,15 +676,17 @@ internal void AddInternal(int index, object? content, bool skipParentCheck) int multiIndex = index; foreach (object c in enumerable) { - AddInternal(multiIndex, c, skipParentCheck); + TryAddInternal(multiIndex, c, skipParentCheck, copyAnnotations); multiIndex++; } + + return true; } else { JToken item = CreateFromContent(content); - InsertItem(index, item, skipParentCheck); + return InsertItem(index, item, skipParentCheck, copyAnnotations); } } @@ -712,8 +733,14 @@ public void RemoveAll() /// Merge the specified content into this . /// /// The content to be merged. - public void Merge(object content) + public void Merge(object? content) { + if (content == null) + { + return; + } + + ValidateContent(content); MergeItem(content, null); } @@ -722,11 +749,31 @@ public void Merge(object content) /// /// The content to be merged. /// The used to merge the content. - public void Merge(object content, JsonMergeSettings? settings) + public void Merge(object? content, JsonMergeSettings? settings) { + if (content == null) + { + return; + } + + ValidateContent(content); MergeItem(content, settings); } + private void ValidateContent(object content) + { + if (content.GetType().IsSubclassOf(typeof(JToken))) + { + return; + } + if (IsMultiContent(content)) + { + return; + } + + throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, content.GetType()), nameof(content)); + } + internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) { int startDepth = reader.Depth; @@ -802,7 +849,7 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) parent = parent.Parent; break; case JsonToken.StartConstructor: - JConstructor constructor = new JConstructor(r.Value!.ToString()); + JConstructor constructor = new JConstructor(r.Value!.ToString()!); constructor.SetLineInfo(lineInfo, settings); parent.Add(constructor); parent = constructor; @@ -865,7 +912,7 @@ internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; JObject parentObject = (JObject)parent; - string propertyName = r.Value!.ToString(); + string propertyName = r.Value!.ToString()!; JProperty? existingPropertyWithName = parentObject.Property(propertyName, StringComparison.Ordinal); if (existingPropertyWithName != null) { @@ -910,10 +957,11 @@ string ITypedList.GetListName(PropertyDescriptor[] listAccessors) return string.Empty; } - PropertyDescriptorCollection? ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) + PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { ICustomTypeDescriptor? d = First as ICustomTypeDescriptor; - return d?.GetProperties(); + + return d?.GetProperties() ?? new PropertyDescriptorCollection(CollectionUtils.ArrayEmpty()); } #endif @@ -925,7 +973,7 @@ int IList.IndexOf(JToken item) void IList.Insert(int index, JToken item) { - InsertItem(index, item, false); + InsertItem(index, item, false, copyAnnotations: true); } void IList.RemoveAt(int index) @@ -969,7 +1017,7 @@ bool ICollection.Remove(JToken item) } #endregion - private JToken? EnsureValue(object value) + private JToken? EnsureValue(object? value) { if (value == null) { @@ -985,7 +1033,7 @@ bool ICollection.Remove(JToken item) } #region IList Members - int IList.Add(object value) + int IList.Add(object? value) { Add(EnsureValue(value)); return Count - 1; @@ -996,26 +1044,26 @@ void IList.Clear() ClearItems(); } - bool IList.Contains(object value) + bool IList.Contains(object? value) { return ContainsItem(EnsureValue(value)); } - int IList.IndexOf(object value) + int IList.IndexOf(object? value) { return IndexOfItem(EnsureValue(value)); } - void IList.Insert(int index, object value) + void IList.Insert(int index, object? value) { - InsertItem(index, EnsureValue(value), false); + InsertItem(index, EnsureValue(value), false, copyAnnotations: false); } bool IList.IsFixedSize => false; bool IList.IsReadOnly => false; - void IList.Remove(object value) + void IList.Remove(object? value) { RemoveItem(EnsureValue(value)); } @@ -1025,7 +1073,7 @@ void IList.RemoveAt(int index) RemoveItemAt(index); } - object IList.this[int index] + object? IList.this[int index] { get => GetItem(index); set => SetItem(index, EnsureValue(value)); @@ -1130,20 +1178,22 @@ internal static void MergeEnumerableContent(JContainer target, IEnumerable conte switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: - foreach (JToken item in content) + foreach (object item in content) { - target.Add(item); + target.Add(CreateFromContent(item)); } break; case MergeArrayHandling.Union: #if HAVE_HASH_SET HashSet items = new HashSet(target, EqualityComparer); - foreach (JToken item in content) + foreach (object item in content) { - if (items.Add(item)) + JToken contentItem = CreateFromContent(item); + + if (items.Add(contentItem)) { - target.Add(item); + target.Add(contentItem); } } #else @@ -1153,12 +1203,14 @@ internal static void MergeEnumerableContent(JContainer target, IEnumerable conte items[t] = true; } - foreach (JToken item in content) + foreach (object item in content) { - if (!items.ContainsKey(item)) + JToken contentItem = CreateFromContent(item); + + if (!items.ContainsKey(contentItem)) { - items[item] = true; - target.Add(item); + items[contentItem] = true; + target.Add(contentItem); } } #endif @@ -1169,9 +1221,9 @@ internal static void MergeEnumerableContent(JContainer target, IEnumerable conte break; } target.ClearItems(); - foreach (JToken item in content) + foreach (object item in content) { - target.Add(item); + target.Add(CreateFromContent(item)); } break; case MergeArrayHandling.Merge: @@ -1200,7 +1252,7 @@ internal static void MergeEnumerableContent(JContainer target, IEnumerable conte } else { - target.Add(targetItem); + target.Add(CreateFromContent(targetItem)); } i++; diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JEnumerable.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JEnumerable.cs index 66f235c5..e741376b 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JEnumerable.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JEnumerable.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -88,7 +88,7 @@ public IJEnumerable this[object key] return JEnumerable.Empty; } - return new JEnumerable(_enumerable.Values(key)); + return new JEnumerable(_enumerable.Values(key)!); } } @@ -111,7 +111,7 @@ public bool Equals(JEnumerable other) /// /// true if the specified is equal to this instance; otherwise, false. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is JEnumerable enumerable) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JObject.Async.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JObject.Async.cs index 50e2f98b..eef5b653 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JObject.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JObject.Async.cs @@ -45,7 +45,7 @@ internal partial class JObject public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task t = writer.WriteStartObjectAsync(cancellationToken); - if (!t.IsCompletedSucessfully()) + if (!t.IsCompletedSuccessfully()) { return AwaitProperties(t, 0, writer, cancellationToken, converters); } @@ -53,7 +53,7 @@ public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellat for (int i = 0; i < _properties.Count; i++) { t = _properties[i].WriteToAsync(writer, cancellationToken, converters); - if (!t.IsCompletedSucessfully()) + if (!t.IsCompletedSuccessfully()) { return AwaitProperties(t, i + 1, writer, cancellationToken, converters); } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JObject.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JObject.cs index 5887783e..16efac5d 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JObject.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JObject.cs @@ -93,7 +93,12 @@ public JObject() /// /// A object to copy from. public JObject(JObject other) - : base(other) + : base(other, settings: null) + { + } + + internal JObject(JObject other, JsonCloneSettings? settings) + : base(other, settings) { } @@ -135,15 +140,15 @@ internal override int IndexOfItem(JToken? item) return _properties.IndexOfReference(item); } - internal override void InsertItem(int index, JToken? item, bool skipParentCheck) + internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { // don't add comments to JObject, no name to reference comment by if (item != null && item.Type == JTokenType.Comment) { - return; + return false; } - base.InsertItem(index, item, skipParentCheck); + return base.InsertItem(index, item, skipParentCheck, copyAnnotations); } internal override void ValidateToken(JToken o, JToken? existing) @@ -244,9 +249,9 @@ internal void InternalPropertyChanging(JProperty childProperty) #endif } - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings) { - return new JObject(this); + return new JObject(this, settings); } /// @@ -742,7 +747,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() return ((ICustomTypeDescriptor)this).GetProperties(null); } - PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) + PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[]? attributes) { PropertyDescriptor[] propertiesArray = new PropertyDescriptor[Count]; int i = 0; @@ -790,7 +795,7 @@ TypeConverter ICustomTypeDescriptor.GetConverter() return null; } - EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) + EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[]? attributes) { return EventDescriptorCollection.Empty; } @@ -800,7 +805,7 @@ EventDescriptorCollection ICustomTypeDescriptor.GetEvents() return EventDescriptorCollection.Empty; } - object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) + object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor? pd) { if (pd is JPropertyDescriptor) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.Async.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.Async.cs index 55dda422..ad6fd02d 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.Async.cs @@ -44,7 +44,7 @@ internal partial class JProperty public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task task = writer.WritePropertyNameAsync(_name, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return WriteValueAsync(writer, cancellationToken, converters); } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.cs index 1c0e1797..c5f20763 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JProperty.cs @@ -173,7 +173,7 @@ public JToken Value if (_content._token == null) { - InsertItem(0, newValue, false); + InsertItem(0, newValue, false, copyAnnotations: true); } else { @@ -187,7 +187,13 @@ public JToken Value /// /// A object to copy from. public JProperty(JProperty other) - : base(other) + : base(other, settings: null) + { + _name = other.Name; + } + + internal JProperty(JProperty other, JsonCloneSettings? settings) + : base(other, settings) { _name = other.Name; } @@ -241,12 +247,12 @@ internal override int IndexOfItem(JToken? item) return _content.IndexOf(item); } - internal override void InsertItem(int index, JToken? item, bool skipParentCheck) + internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { // don't add comments to JProperty if (item != null && item.Type == JTokenType.Comment) { - return; + return false; } if (Value != null) @@ -254,7 +260,7 @@ internal override void InsertItem(int index, JToken? item, bool skipParentCheck) throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } - base.InsertItem(0, item, false); + return base.InsertItem(0, item, false, copyAnnotations); } internal override bool ContainsItem(JToken? item) @@ -282,9 +288,9 @@ internal override bool DeepEquals(JToken node) return (node is JProperty t && _name == t.Name && ContentsEqual(t)); } - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings) { - return new JProperty(this); + return new JProperty(this, settings); } /// @@ -353,7 +359,13 @@ public override void WriteTo(JsonWriter writer, params JsonConverter[] converter internal override int GetDeepHashCode() { - return _name.GetHashCode() ^ (Value?.GetDeepHashCode() ?? 0); + int hash; +#if HAVE_GETHASHCODE_STRING_COMPARISON + hash = _name.GetHashCode(StringComparison.Ordinal); +#else + hash = _name.GetHashCode(); +#endif + return hash ^ (Value?.GetDeepHashCode() ?? 0); } /// diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyDescriptor.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyDescriptor.cs index 4c9450b9..57d5a0a1 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyDescriptor.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyDescriptor.cs @@ -67,7 +67,7 @@ public override bool CanResetValue(object component) /// The value of a property for a given component. /// /// The component with the property for which to retrieve the value. - public override object? GetValue(object component) + public override object? GetValue(object? component) { return (component as JObject)?[Name]; } @@ -85,7 +85,7 @@ public override void ResetValue(object component) /// /// The component with the property value that is to be set. /// The new value. - public override void SetValue(object component, object value) + public override void SetValue(object? component, object? value) { if (component is JObject o) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs index dd594ff6..08ef86ee 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs @@ -131,7 +131,7 @@ public bool Remove(string key) if (_dictionary != null) { - return _dictionary.TryGetValue(key, out JToken value) && Remove(value); + return _dictionary.TryGetValue(key, out JToken? value) && Remove(value); } return false; @@ -259,7 +259,7 @@ public bool Compare(JPropertyKeyedCollection other) foreach (KeyValuePair keyAndProperty in d1) { - if (!d2.TryGetValue(keyAndProperty.Key, out JToken secondValue)) + if (!d2.TryGetValue(keyAndProperty.Key, out JToken? secondValue)) { return false; } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JRaw.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JRaw.cs index 5a4e89ee..945f10af 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JRaw.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JRaw.cs @@ -38,7 +38,12 @@ internal partial class JRaw : JValue /// /// A object to copy from. public JRaw(JRaw other) - : base(other) + : base(other, settings: null) + { + } + + internal JRaw(JRaw other, JsonCloneSettings? settings) + : base(other, settings) { } @@ -67,9 +72,9 @@ public static JRaw Create(JsonReader reader) } } - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings) { - return new JRaw(this); + return new JRaw(this, settings); } } } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JToken.Async.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JToken.Async.cs index 0031d415..f3958d52 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JToken.Async.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JToken.Async.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JToken.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JToken.cs index ed0c2cad..0185a3d6 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JToken.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JToken.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -45,6 +45,7 @@ #else using System.Linq; #endif +using Exceptionless.Json.Serialization; namespace Exceptionless.Json.Linq { @@ -130,7 +131,7 @@ public JToken Root } } - internal abstract JToken CloneToken(); + internal abstract JToken CloneToken(JsonCloneSettings? settings); internal abstract bool DeepEquals(JToken node); /// @@ -240,7 +241,7 @@ public void AddAfterSelf(object? content) } int index = _parent.IndexOfItem(this); - _parent.AddInternal(index + 1, content, false); + _parent.TryAddInternal(index + 1, content, false, copyAnnotations: true); } /// @@ -255,7 +256,7 @@ public void AddBeforeSelf(object? content) } int index = _parent.IndexOfItem(this); - _parent.AddInternal(index, content, false); + _parent.TryAddInternal(index, content, false, copyAnnotations: true); } /// @@ -334,7 +335,7 @@ public virtual JToken? this[object key] /// The type to convert the token to. /// The token key. /// The converted token value. - public virtual T Value(object key) + public virtual T? Value(object key) { JToken? token = this[key]; @@ -378,7 +379,7 @@ public JEnumerable Children() where T : JToken /// /// The type to convert the values to. /// A containing the child values of this , in document order. - public virtual IEnumerable Values() + public virtual IEnumerable Values() { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } @@ -485,7 +486,7 @@ private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullab return (Array.IndexOf(validTypes, o.Type) != -1) || (nullable && (o.Type == JTokenType.Null || o.Type == JTokenType.Undefined)); } -#region Cast from operators + #region Cast from operators /// /// Performs an explicit conversion from to . /// @@ -1332,7 +1333,7 @@ public static explicit operator ulong(JToken value) if (v.Value is string) { - return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } #if HAVE_BIG_INTEGER if (v.Value is BigInteger integer) @@ -1367,7 +1368,7 @@ public static explicit operator Guid(JToken value) return new Guid(bytes); } - return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } /// @@ -1398,7 +1399,7 @@ public static explicit operator Guid(JToken value) return new Guid(bytes); } - return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return (v.Value is Guid guid) ? guid : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } /// @@ -1414,7 +1415,7 @@ public static explicit operator TimeSpan(JToken value) throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } - return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } /// @@ -1440,7 +1441,7 @@ public static explicit operator TimeSpan(JToken value) return null; } - return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return (v.Value is TimeSpan span) ? span : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } /// @@ -1466,7 +1467,7 @@ public static explicit operator TimeSpan(JToken value) return null; } - return (v.Value is Uri uri) ? uri : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture)); + return (v.Value is Uri uri) ? uri : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture)!); } #if HAVE_BIG_INTEGER @@ -1497,9 +1498,9 @@ private static BigInteger ToBigInteger(JToken value) return ConvertUtils.ToBigInteger(v.Value); } #endif -#endregion + #endregion -#region Cast to operators + #region Cast to operators /// /// Performs an implicit conversion from to . /// @@ -1863,7 +1864,7 @@ public static implicit operator JToken(Guid? value) { return new JValue(value); } -#endregion + #endregion IEnumerator IEnumerable.GetEnumerator() { @@ -1929,12 +1930,9 @@ public static JToken FromObject(object o, JsonSerializer jsonSerializer) /// /// The object type that the token will be deserialized to. /// The new object created from the JSON value. - [return: MaybeNull] - public T ToObject() + public T? ToObject() { -#pragma warning disable CS8601 // Possible null reference assignment. - return (T)ToObject(typeof(T)); -#pragma warning restore CS8601 // Possible null reference assignment. + return (T?)ToObject(typeof(T)); } /// @@ -1959,15 +1957,15 @@ public T ToObject() } catch (Exception ex) { - Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType); + Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType)!; throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string?)this, enumType.Name), ex); } } if (Type == JTokenType.Integer) { - Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType); - return Enum.ToObject(enumType, ((JValue)this).Value); + Type enumType = objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType)!; + return Enum.ToObject(enumType, ((JValue)this).Value!); } } @@ -2065,12 +2063,9 @@ public T ToObject() /// The object type that the token will be deserialized to. /// The that will be used when creating the object. /// The new object created from the JSON value. - [return: MaybeNull] - public T ToObject(JsonSerializer jsonSerializer) + public T? ToObject(JsonSerializer jsonSerializer) { -#pragma warning disable CS8601 // Possible null reference assignment. - return (T)ToObject(typeof(T), jsonSerializer); -#pragma warning restore CS8601 // Possible null reference assignment. + return (T?)ToObject(typeof(T), jsonSerializer); } /// @@ -2079,12 +2074,19 @@ public T ToObject(JsonSerializer jsonSerializer) /// The object type that the token will be deserialized to. /// The that will be used when creating the object. /// The new object created from the JSON value. - public object? ToObject(Type objectType, JsonSerializer jsonSerializer) + public object? ToObject(Type? objectType, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer)); using (JTokenReader jsonReader = new JTokenReader(this)) { + // Hacky fix to ensure the serializer settings are set onto the new reader. + // This is required because the serializer won't update settings when used inside of a converter. + if (jsonSerializer is JsonSerializerProxy proxy) + { + proxy._serializer.SetupReader(jsonReader, out _, out _, out _, out _, out _, out _); + } + return jsonSerializer.Deserialize(jsonReader, objectType); } } @@ -2313,7 +2315,7 @@ int IJsonLineInfo.LinePosition /// A , or null. public JToken? SelectToken(string path) { - return SelectToken(path, false); + return SelectToken(path, settings: null); } /// @@ -2325,11 +2327,28 @@ int IJsonLineInfo.LinePosition /// A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. /// A . public JToken? SelectToken(string path, bool errorWhenNoMatch) + { + JsonSelectSettings? settings = errorWhenNoMatch + ? new JsonSelectSettings { ErrorWhenNoMatch = true } + : null; + + return SelectToken(path, settings); + } + + /// + /// Selects a using a JSONPath expression. Selects the token that matches the object path. + /// + /// + /// A that contains a JSONPath expression. + /// + /// The used to select tokens. + /// A . + public JToken? SelectToken(string path, JsonSelectSettings? settings) { JPath p = new JPath(path); JToken? token = null; - foreach (JToken t in p.Evaluate(this, this, errorWhenNoMatch)) + foreach (JToken t in p.Evaluate(this, this, settings)) { if (token != null) { @@ -2351,7 +2370,7 @@ int IJsonLineInfo.LinePosition /// An of that contains the selected elements. public IEnumerable SelectTokens(string path) { - return SelectTokens(path, false); + return SelectTokens(path, settings: null); } /// @@ -2364,8 +2383,25 @@ public IEnumerable SelectTokens(string path) /// An of that contains the selected elements. public IEnumerable SelectTokens(string path, bool errorWhenNoMatch) { - JPath p = new JPath(path); - return p.Evaluate(this, this, errorWhenNoMatch); + JsonSelectSettings? settings = errorWhenNoMatch + ? new JsonSelectSettings { ErrorWhenNoMatch = true } + : null; + + return SelectTokens(path, settings); + } + + /// + /// Selects a collection of elements using a JSONPath expression. + /// + /// + /// A that contains a JSONPath expression. + /// + /// The used to select tokens. + /// An of that contains the selected elements. + public IEnumerable SelectTokens(string path, JsonSelectSettings? settings) + { + var p = new JPath(path); + return p.Evaluate(this, this, settings); } #if HAVE_DYNAMIC @@ -2407,7 +2443,17 @@ object ICloneable.Clone() /// A new instance of the . public JToken DeepClone() { - return CloneToken(); + return CloneToken(settings: null); + } + + /// + /// Creates a new instance of the . All child tokens are recursively cloned. + /// + /// A object to configure cloning settings. + /// A new instance of the . + public JToken DeepClone(JsonCloneSettings settings) + { + return CloneToken(settings); } /// @@ -2453,7 +2499,7 @@ public void AddAnnotation(object annotation) /// /// The type of the annotation to retrieve. /// The first annotation object that matches the specified type, or null if no annotation is of the specified type. - public T Annotation() where T : class + public T? Annotation() where T : class { if (_annotations != null) { @@ -2706,5 +2752,17 @@ public void RemoveAnnotations(Type type) } } } + + internal void CopyAnnotations(JToken target, JToken source) + { + if (source._annotations is object[] annotations) + { + target._annotations = annotations.ToArray(); + } + else + { + target._annotations = source._annotations; + } + } } } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs index b2cf4b4c..9db55724 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs @@ -40,7 +40,7 @@ internal class JTokenEqualityComparer : IEqualityComparer /// /// true if the specified objects are equal; otherwise, false. /// - public bool Equals(JToken x, JToken y) + public bool Equals(JToken? x, JToken? y) { return JToken.DeepEquals(x, y); } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JTokenWriter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JTokenWriter.cs index f552648e..582e237a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JTokenWriter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JTokenWriter.cs @@ -187,21 +187,26 @@ public override void WritePropertyName(string name) base.WritePropertyName(name); } - private void AddValue(object? value, JsonToken token) + private void AddRawValue(object? value, JTokenType type, JsonToken token) { - AddValue(new JValue(value), token); + AddJValue(new JValue(value, type), token); } - internal void AddValue(JValue? value, JsonToken token) + internal void AddJValue(JValue? value, JsonToken token) { if (_parent != null) { - _parent.Add(value); - _current = _parent.Last; - - if (_parent.Type == JTokenType.Property) + // TryAdd will return false if an invalid JToken type is added. + // For example, a JComment can't be added to a JObject. + // If there is an invalid JToken type then skip it. + if (_parent.TryAdd(value)) { - _parent = _parent.Parent; + _current = _parent.Last; + + if (_parent.Type == JTokenType.Property) + { + _parent = _parent.Parent; + } } } else @@ -223,7 +228,7 @@ public override void WriteValue(object? value) if (value is BigInteger) { InternalWriteValue(JsonToken.Integer); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } else #endif @@ -238,7 +243,7 @@ public override void WriteValue(object? value) public override void WriteNull() { base.WriteNull(); - AddValue(null, JsonToken.Null); + AddJValue(JValue.CreateNull(), JsonToken.Null); } /// @@ -247,7 +252,7 @@ public override void WriteNull() public override void WriteUndefined() { base.WriteUndefined(); - AddValue(null, JsonToken.Undefined); + AddJValue(JValue.CreateUndefined(), JsonToken.Undefined); } /// @@ -257,7 +262,7 @@ public override void WriteUndefined() public override void WriteRaw(string? json) { base.WriteRaw(json); - AddValue(new JRaw(json), JsonToken.Raw); + AddJValue(new JRaw(json), JsonToken.Raw); } /// @@ -267,7 +272,7 @@ public override void WriteRaw(string? json) public override void WriteComment(string? text) { base.WriteComment(text); - AddValue(JValue.CreateComment(text), JsonToken.Comment); + AddJValue(JValue.CreateComment(text), JsonToken.Comment); } /// @@ -276,8 +281,14 @@ public override void WriteComment(string? text) /// The value to write. public override void WriteValue(string? value) { + if (value == null) + { + WriteNull(); + return; + } + base.WriteValue(value); - AddValue(value, JsonToken.String); + AddJValue(new JValue(value), JsonToken.String); } /// @@ -287,7 +298,7 @@ public override void WriteValue(string? value) public override void WriteValue(int value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -298,7 +309,7 @@ public override void WriteValue(int value) public override void WriteValue(uint value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -308,7 +319,7 @@ public override void WriteValue(uint value) public override void WriteValue(long value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddJValue(new JValue(value), JsonToken.Integer); } /// @@ -319,7 +330,7 @@ public override void WriteValue(long value) public override void WriteValue(ulong value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddJValue(new JValue(value), JsonToken.Integer); } /// @@ -329,7 +340,7 @@ public override void WriteValue(ulong value) public override void WriteValue(float value) { base.WriteValue(value); - AddValue(value, JsonToken.Float); + AddJValue(new JValue(value), JsonToken.Float); } /// @@ -339,7 +350,7 @@ public override void WriteValue(float value) public override void WriteValue(double value) { base.WriteValue(value); - AddValue(value, JsonToken.Float); + AddJValue(new JValue(value), JsonToken.Float); } /// @@ -349,7 +360,7 @@ public override void WriteValue(double value) public override void WriteValue(bool value) { base.WriteValue(value); - AddValue(value, JsonToken.Boolean); + AddJValue(new JValue(value), JsonToken.Boolean); } /// @@ -359,7 +370,7 @@ public override void WriteValue(bool value) public override void WriteValue(short value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -370,7 +381,7 @@ public override void WriteValue(short value) public override void WriteValue(ushort value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -386,7 +397,7 @@ public override void WriteValue(char value) #else s = value.ToString(); #endif - AddValue(s, JsonToken.String); + AddJValue(new JValue(s), JsonToken.String); } /// @@ -396,7 +407,7 @@ public override void WriteValue(char value) public override void WriteValue(byte value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -407,7 +418,7 @@ public override void WriteValue(byte value) public override void WriteValue(sbyte value) { base.WriteValue(value); - AddValue(value, JsonToken.Integer); + AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } /// @@ -417,7 +428,7 @@ public override void WriteValue(sbyte value) public override void WriteValue(decimal value) { base.WriteValue(value); - AddValue(value, JsonToken.Float); + AddJValue(new JValue(value), JsonToken.Float); } /// @@ -428,7 +439,7 @@ public override void WriteValue(DateTime value) { base.WriteValue(value); value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling); - AddValue(value, JsonToken.Date); + AddJValue(new JValue(value), JsonToken.Date); } #if HAVE_DATE_TIME_OFFSET @@ -439,7 +450,7 @@ public override void WriteValue(DateTime value) public override void WriteValue(DateTimeOffset value) { base.WriteValue(value); - AddValue(value, JsonToken.Date); + AddJValue(new JValue(value), JsonToken.Date); } #endif @@ -450,7 +461,7 @@ public override void WriteValue(DateTimeOffset value) public override void WriteValue(byte[]? value) { base.WriteValue(value); - AddValue(value, JsonToken.Bytes); + AddJValue(new JValue(value, JTokenType.Bytes), JsonToken.Bytes); } /// @@ -460,7 +471,7 @@ public override void WriteValue(byte[]? value) public override void WriteValue(TimeSpan value) { base.WriteValue(value); - AddValue(value, JsonToken.String); + AddJValue(new JValue(value), JsonToken.String); } /// @@ -470,7 +481,7 @@ public override void WriteValue(TimeSpan value) public override void WriteValue(Guid value) { base.WriteValue(value); - AddValue(value, JsonToken.String); + AddJValue(new JValue(value), JsonToken.String); } /// @@ -480,7 +491,7 @@ public override void WriteValue(Guid value) public override void WriteValue(Uri? value) { base.WriteValue(value); - AddValue(value, JsonToken.String); + AddJValue(new JValue(value), JsonToken.String); } #endregion @@ -497,7 +508,7 @@ internal override void WriteToken(JsonReader reader, bool writeChildren, bool wr } } - JToken value = tokenReader.CurrentToken!.CloneToken(); + JToken value = tokenReader.CurrentToken!.CloneToken(settings: null); if (_parent != null) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JValue.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JValue.cs index b8ddbd87..9013f239 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JValue.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JValue.cs @@ -57,6 +57,15 @@ internal JValue(object? value, JTokenType type) _valueType = type; } + internal JValue(JValue other, JsonCloneSettings? settings) + : this(other.Value, other.Type) + { + if (settings?.CopyAnnotations ?? true) + { + CopyAnnotations(this, other); + } + } + /// /// Initializes a new instance of the class from another object. /// @@ -71,7 +80,7 @@ public JValue(JValue other) /// /// The value. public JValue(long value) - : this(value, JTokenType.Integer) + : this(BoxedPrimitives.Get(value), JTokenType.Integer) { } @@ -80,7 +89,7 @@ public JValue(long value) /// /// The value. public JValue(decimal value) - : this(value, JTokenType.Float) + : this(BoxedPrimitives.Get(value), JTokenType.Float) { } @@ -108,7 +117,7 @@ public JValue(ulong value) /// /// The value. public JValue(double value) - : this(value, JTokenType.Float) + : this(BoxedPrimitives.Get(value), JTokenType.Float) { } @@ -146,7 +155,7 @@ public JValue(DateTimeOffset value) /// /// The value. public JValue(bool value) - : this(value, JTokenType.Boolean) + : this(BoxedPrimitives.Get(value), JTokenType.Boolean) { } @@ -306,8 +315,8 @@ internal static int Compare(JTokenType valueType, object? objA, object? objB) case JTokenType.Comment: case JTokenType.String: case JTokenType.Raw: - string s1 = Convert.ToString(objA, CultureInfo.InvariantCulture); - string s2 = Convert.ToString(objB, CultureInfo.InvariantCulture); + string? s1 = Convert.ToString(objA, CultureInfo.InvariantCulture); + string? s2 = Convert.ToString(objB, CultureInfo.InvariantCulture); return string.CompareOrdinal(s1, s2); case JTokenType.Boolean: @@ -556,9 +565,9 @@ private static bool Operation(ExpressionType operation, object? objA, object? ob } #endif - internal override JToken CloneToken() + internal override JToken CloneToken(JsonCloneSettings? settings) { - return new JValue(this); + return new JValue(this, settings); } /// @@ -841,7 +850,7 @@ private static bool ValuesEquals(JValue v1, JValue v2) /// true if the current object is equal to the parameter; otherwise, false. /// /// An object to compare with this object. - public bool Equals([AllowNull] JValue other) + public bool Equals(JValue? other) { if (other == null) { @@ -858,7 +867,7 @@ public bool Equals([AllowNull] JValue other) /// /// true if the specified is equal to the current ; otherwise, false. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is JValue v) { @@ -901,7 +910,7 @@ public override string ToString() return string.Empty; } - return _value.ToString(); + return _value.ToString()!; } /// @@ -923,7 +932,7 @@ public string ToString(string format) /// /// A that represents this instance. /// - public string ToString(IFormatProvider formatProvider) + public string ToString(IFormatProvider? formatProvider) { return ToString(null, formatProvider); } @@ -936,7 +945,7 @@ public string ToString(IFormatProvider formatProvider) /// /// A that represents this instance. /// - public string ToString(string? format, IFormatProvider formatProvider) + public string ToString(string? format, IFormatProvider? formatProvider) { if (_value == null) { @@ -949,7 +958,7 @@ public string ToString(string? format, IFormatProvider formatProvider) } else { - return _value.ToString(); + return _value.ToString()!; } } @@ -1034,7 +1043,7 @@ public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder b } #endif - int IComparable.CompareTo(object obj) + int IComparable.CompareTo(object? obj) { if (obj == null) { @@ -1077,7 +1086,7 @@ int IComparable.CompareTo(object obj) /// /// is not of the same type as this instance. /// - public int CompareTo(JValue obj) + public int CompareTo(JValue? obj) { if (obj == null) { @@ -1107,79 +1116,79 @@ TypeCode IConvertible.GetTypeCode() return TypeCode.Object; } - bool IConvertible.ToBoolean(IFormatProvider provider) + bool IConvertible.ToBoolean(IFormatProvider? provider) { return (bool)this; } - char IConvertible.ToChar(IFormatProvider provider) + char IConvertible.ToChar(IFormatProvider? provider) { return (char)this; } - sbyte IConvertible.ToSByte(IFormatProvider provider) + sbyte IConvertible.ToSByte(IFormatProvider? provider) { return (sbyte)this; } - byte IConvertible.ToByte(IFormatProvider provider) + byte IConvertible.ToByte(IFormatProvider? provider) { return (byte)this; } - short IConvertible.ToInt16(IFormatProvider provider) + short IConvertible.ToInt16(IFormatProvider? provider) { return (short)this; } - ushort IConvertible.ToUInt16(IFormatProvider provider) + ushort IConvertible.ToUInt16(IFormatProvider? provider) { return (ushort)this; } - int IConvertible.ToInt32(IFormatProvider provider) + int IConvertible.ToInt32(IFormatProvider? provider) { return (int)this; } - uint IConvertible.ToUInt32(IFormatProvider provider) + uint IConvertible.ToUInt32(IFormatProvider? provider) { return (uint)this; } - long IConvertible.ToInt64(IFormatProvider provider) + long IConvertible.ToInt64(IFormatProvider? provider) { return (long)this; } - ulong IConvertible.ToUInt64(IFormatProvider provider) + ulong IConvertible.ToUInt64(IFormatProvider? provider) { return (ulong)this; } - float IConvertible.ToSingle(IFormatProvider provider) + float IConvertible.ToSingle(IFormatProvider? provider) { return (float)this; } - double IConvertible.ToDouble(IFormatProvider provider) + double IConvertible.ToDouble(IFormatProvider? provider) { return (double)this; } - decimal IConvertible.ToDecimal(IFormatProvider provider) + decimal IConvertible.ToDecimal(IFormatProvider? provider) { return (decimal)this; } - DateTime IConvertible.ToDateTime(IFormatProvider provider) + DateTime IConvertible.ToDateTime(IFormatProvider? provider) { return (DateTime)this; } - object? IConvertible.ToType(Type conversionType, IFormatProvider provider) + object IConvertible.ToType(Type conversionType, IFormatProvider? provider) { - return ToObject(conversionType); + return ToObject(conversionType)!; } #endif } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonCloneSettings.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonCloneSettings.cs new file mode 100644 index 00000000..d7f0107a --- /dev/null +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonCloneSettings.cs @@ -0,0 +1,57 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace Exceptionless.Json.Linq +{ + /// + /// Specifies the settings used when cloning JSON. + /// + internal class JsonCloneSettings + { + internal static readonly JsonCloneSettings SkipCopyAnnotations = new JsonCloneSettings + { + CopyAnnotations = false + }; + + /// + /// Initializes a new instance of the class. + /// + public JsonCloneSettings() + { + CopyAnnotations = true; + } + + /// + /// Gets or sets a flag that indicates whether to copy annotations when cloning a . + /// The default value is true. + /// + /// + /// A flag that indicates whether to copy annotations when cloning a . + /// + public bool CopyAnnotations { get; set; } + } +} diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonLoadSettings.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonLoadSettings.cs index 1db53c89..5be071e5 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonLoadSettings.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonLoadSettings.cs @@ -1,3 +1,28 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + using System; namespace Exceptionless.Json.Linq diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs index aca9dc73..f7567e4d 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs @@ -8,13 +8,13 @@ internal class ArrayIndexFilter : PathFilter { public int? Index { get; set; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { if (Index != null) { - JToken? v = GetTokenIndex(t, errorWhenNoMatch, Index.GetValueOrDefault()); + JToken? v = GetTokenIndex(t, settings, Index.GetValueOrDefault()); if (v != null) { @@ -32,7 +32,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable indexes) Indexes = indexes; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { foreach (int i in Indexes) { - JToken? v = GetTokenIndex(t, errorWhenNoMatch, i); + JToken? v = GetTokenIndex(t, settings, i); if (v != null) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs index 2fd78e84..afaae99a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs @@ -11,7 +11,7 @@ internal class ArraySliceFilter : PathFilter public int? End { get; set; } public int? Step { get; set; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { if (Step == 0) { @@ -56,7 +56,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { @@ -27,7 +27,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable names) Names = names; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { @@ -33,7 +33,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable "'" + n + "'") #if !HAVE_STRING_JOIN_WITH_ENUMERABLE diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/JPath.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/JPath.cs index 74046599..291c9f05 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/JPath.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/JPath.cs @@ -874,17 +874,17 @@ private void EnsureLength(string message) } } - internal IEnumerable Evaluate(JToken root, JToken t, bool errorWhenNoMatch) + internal IEnumerable Evaluate(JToken root, JToken t, JsonSelectSettings? settings) { - return Evaluate(Filters, root, t, errorWhenNoMatch); + return Evaluate(Filters, root, t, settings); } - internal static IEnumerable Evaluate(List filters, JToken root, JToken t, bool errorWhenNoMatch) + internal static IEnumerable Evaluate(List filters, JToken root, JToken t, JsonSelectSettings? settings) { IEnumerable current = new[] { t }; foreach (PathFilter filter in filters) { - current = filter.ExecuteFilter(root, current, errorWhenNoMatch); + current = filter.ExecuteFilter(root, current, settings); } return current; diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs index b7119e0c..e64029f1 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs @@ -6,15 +6,15 @@ namespace Exceptionless.Json.Linq.JsonPath { internal abstract class PathFilter { - public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch); + public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings); - protected static JToken? GetTokenIndex(JToken t, bool errorWhenNoMatch, int index) + protected static JToken? GetTokenIndex(JToken t, JsonSelectSettings? settings, int index) { if (t is JArray a) { if (a.Count <= index) { - if (errorWhenNoMatch) + if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index)); } @@ -28,7 +28,7 @@ internal abstract class PathFilter { if (c.Count <= index) { - if (errorWhenNoMatch) + if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index)); } @@ -40,7 +40,7 @@ internal abstract class PathFilter } else { - if (errorWhenNoMatch) + if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name)); } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs index 727f8a52..b31668e6 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs @@ -39,7 +39,13 @@ public QueryExpression(QueryOperator @operator) Operator = @operator; } - public abstract bool IsMatch(JToken root, JToken t); + // For unit tests + public bool IsMatch(JToken root, JToken t) + { + return IsMatch(root, t, null); + } + + public abstract bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings); } internal class CompositeExpression : QueryExpression @@ -51,14 +57,14 @@ public CompositeExpression(QueryOperator @operator) : base(@operator) Expressions = new List(); } - public override bool IsMatch(JToken root, JToken t) + public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { switch (Operator) { case QueryOperator.And: foreach (QueryExpression e in Expressions) { - if (!e.IsMatch(root, t)) + if (!e.IsMatch(root, t, settings)) { return false; } @@ -67,7 +73,7 @@ public override bool IsMatch(JToken root, JToken t) case QueryOperator.Or: foreach (QueryExpression e in Expressions) { - if (e.IsMatch(root, t)) + if (e.IsMatch(root, t, settings)) { return true; } @@ -99,13 +105,13 @@ private IEnumerable GetResult(JToken root, JToken t, object? o) if (o is List pathFilters) { - return JPath.Evaluate(pathFilters, root, t, false); + return JPath.Evaluate(pathFilters, root, t, null); } return CollectionUtils.ArrayEmpty(); } - public override bool IsMatch(JToken root, JToken t) + public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { if (Operator == QueryOperator.Exists) { @@ -124,7 +130,7 @@ public override bool IsMatch(JToken root, JToken t) JToken leftResult = leftResults.Current; foreach (JToken rightResult in rightResults) { - if (MatchTokens(leftResult, rightResult)) + if (MatchTokens(leftResult, rightResult, settings)) { return true; } @@ -136,14 +142,14 @@ public override bool IsMatch(JToken root, JToken t) return false; } - private bool MatchTokens(JToken leftResult, JToken rightResult) + private bool MatchTokens(JToken leftResult, JToken rightResult, JsonSelectSettings? settings) { if (leftResult is JValue leftValue && rightResult is JValue rightValue) { switch (Operator) { case QueryOperator.RegexEquals: - if (RegexEquals(leftValue, rightValue)) + if (RegexEquals(leftValue, rightValue, settings)) { return true; } @@ -215,7 +221,7 @@ private bool MatchTokens(JToken leftResult, JToken rightResult) return false; } - private static bool RegexEquals(JValue input, JValue pattern) + private static bool RegexEquals(JValue input, JValue pattern, JsonSelectSettings? settings) { if (input.Type != JTokenType.String || pattern.Type != JTokenType.String) { @@ -228,7 +234,12 @@ private static bool RegexEquals(JValue input, JValue pattern) string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1); string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1); +#if HAVE_REGEX_TIMEOUTS + TimeSpan timeout = settings?.RegexMatchTimeout ?? Regex.InfiniteMatchTimeout; + return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText), timeout); +#else return Regex.IsMatch((string)input.Value!, patternText, MiscellaneousUtils.GetRegexOptions(optionsText)); +#endif } internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) @@ -280,7 +291,7 @@ internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) break; case JTokenType.Guid: case JTokenType.TimeSpan: - currentValueString = value.Value!.ToString(); + currentValueString = value.Value!.ToString()!; break; case JTokenType.Uri: currentValueString = ((Uri)value.Value!).OriginalString; diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs index e016a68c..da375f59 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs @@ -12,13 +12,13 @@ public QueryFilter(QueryExpression expression) Expression = expression; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { foreach (JToken v in t) { - if (Expression.IsMatch(root, v)) + if (Expression.IsMatch(root, v, settings)) { yield return v; } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs index 68676aed..c228fbf5 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/QueryScanFilter.cs @@ -12,7 +12,7 @@ public QueryScanFilter(QueryExpression expression) Expression = expression; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { @@ -20,7 +20,7 @@ public override IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { return new[] { root }; } diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs index 38627b40..debd4b3c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs @@ -11,7 +11,7 @@ public ScanFilter(string? name) Name = name; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs index c9bcea0b..743a35bf 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonPath/ScanMultipleFilter.cs @@ -11,7 +11,7 @@ public ScanMultipleFilter(List names) _names = names; } - public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, bool errorWhenNoMatch) + public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/JsonSelectSettings.cs b/src/Exceptionless/Newtonsoft.Json/Linq/JsonSelectSettings.cs new file mode 100644 index 00000000..24039e61 --- /dev/null +++ b/src/Exceptionless/Newtonsoft.Json/Linq/JsonSelectSettings.cs @@ -0,0 +1,53 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; + +namespace Exceptionless.Json.Linq +{ + /// + /// Specifies the settings used when selecting JSON. + /// + internal class JsonSelectSettings + { +#if HAVE_REGEX_TIMEOUTS + /// + /// Gets or sets a timeout that will be used when executing regular expressions. + /// + /// The timeout that will be used when executing regular expressions. + public TimeSpan? RegexMatchTimeout { get; set; } +#endif + + /// + /// Gets or sets a flag that indicates whether an error should be thrown if + /// no tokens are found when evaluating part of the expression. + /// + /// + /// A flag that indicates whether an error should be thrown if + /// no tokens are found when evaluating part of the expression. + /// + public bool ErrorWhenNoMatch { get; set; } + } +} diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/MergeArrayHandling.cs b/src/Exceptionless/Newtonsoft.Json/Linq/MergeArrayHandling.cs index 2eb891f0..da2d49ff 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/MergeArrayHandling.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/MergeArrayHandling.cs @@ -1,3 +1,28 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + namespace Exceptionless.Json.Linq { /// diff --git a/src/Exceptionless/Newtonsoft.Json/Linq/MergeNullValueHandling.cs b/src/Exceptionless/Newtonsoft.Json/Linq/MergeNullValueHandling.cs index 95092c9b..366657a6 100644 --- a/src/Exceptionless/Newtonsoft.Json/Linq/MergeNullValueHandling.cs +++ b/src/Exceptionless/Newtonsoft.Json/Linq/MergeNullValueHandling.cs @@ -1,3 +1,28 @@ +#region License +// Copyright (c) 2007 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + using System; namespace Exceptionless.Json.Linq diff --git a/src/Exceptionless/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs b/src/Exceptionless/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs index d788f9c7..fe9ba211 100644 --- a/src/Exceptionless/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs +++ b/src/Exceptionless/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs @@ -89,7 +89,10 @@ internal JsonSchema Read(JsonReader reader) private string UnescapeReference(string reference) { - return Uri.UnescapeDataString(reference).Replace("~1", "/").Replace("~0", "~"); + string unescapedReference = Uri.UnescapeDataString(reference); + unescapedReference = StringUtils.Replace(unescapedReference, "~1", "/"); + unescapedReference = StringUtils.Replace(unescapedReference, "~0", "~"); + return unescapedReference; } private JsonSchema ResolveReferences(JsonSchema schema) @@ -220,7 +223,11 @@ private JsonSchema BuildSchema(JToken token) return deferredSchema; } - string location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty); + string location = token.Path; + location = StringUtils.Replace(location, ".", "/"); + location = StringUtils.Replace(location, "[", "/"); + location = StringUtils.Replace(location, "]", string.Empty); + if (!StringUtils.IsNullOrEmpty(location)) { location = "/" + location; diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs index 73e8d3de..c10f9bf3 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -31,9 +31,9 @@ namespace Exceptionless.Json.Serialization { internal static class CachedAttributeGetter where T : Attribute { - private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); + private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); - public static T GetAttribute(object type) + public static T? GetAttribute(object type) { return TypeAttributeCache.Get(type); } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs index 4b3a2d7b..4c6ee401 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs @@ -66,7 +66,7 @@ public override JsonContract ResolveContract(Type type) // for backwards compadibility the CamelCasePropertyNamesContractResolver shares contracts between instances StructMultiKey key = new StructMultiKey(GetType(), type); Dictionary, JsonContract>? cache = _contractCache; - if (cache == null || !cache.TryGetValue(key, out JsonContract contract)) + if (cache == null || !cache.TryGetValue(key, out JsonContract? contract)) { contract = CreateContract(type); diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultContractResolver.cs index a35a4095..ade4ec5e 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultContractResolver.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultContractResolver.cs @@ -418,7 +418,7 @@ protected virtual JsonObjectContract CreateObjectContract(Type objectType) } } - MemberInfo extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType); + MemberInfo? extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType); if (extensionDataMember != null) { SetExtensionDataDelegates(contract, extensionDataMember); @@ -439,7 +439,7 @@ private static void ThrowUnableToSerializeError(object o, StreamingContext conte throw new JsonSerializationException("Unable to serialize instance of '{0}'.".FormatWith(CultureInfo.InvariantCulture, o.GetType())); } - private MemberInfo GetExtensionDataMemberForType(Type type) + private MemberInfo? GetExtensionDataMemberForType(Type type) { IEnumerable members = GetClassHierarchyForType(type).SelectMany(baseType => { @@ -450,7 +450,7 @@ private MemberInfo GetExtensionDataMemberForType(Type type) return m; }); - MemberInfo extensionDataMember = members.LastOrDefault(m => + MemberInfo? extensionDataMember = members.LastOrDefault(m => { MemberTypes memberType = m.MemberType(); if (memberType != MemberTypes.Property && memberType != MemberTypes.Field) @@ -466,7 +466,7 @@ private MemberInfo GetExtensionDataMemberForType(Type type) if (!ReflectionUtils.CanReadMemberValue(m, true)) { - throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); + throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType!), m.Name)); } Type t = ReflectionUtils.GetMemberUnderlyingType(m); @@ -482,7 +482,7 @@ private MemberInfo GetExtensionDataMemberForType(Type type) } } - throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); + throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType!), m.Name)); }); return extensionDataMember; @@ -640,7 +640,7 @@ IEnumerator IEnumerable.GetEnumerator() { foreach (ParameterInfo parameterInfo in parameters) { - JsonProperty? memberProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); + JsonProperty? memberProperty = MatchProperty(memberProperties, parameterInfo.Name!, parameterInfo.ParameterType); if (memberProperty == null || memberProperty.Writable) { return null; @@ -688,7 +688,7 @@ protected virtual IList CreateConstructorParameters(ConstructorInf { ParameterInfo[] constructorParameters = constructor.GetParameters(); - JsonPropertyCollection parameterCollection = new JsonPropertyCollection(constructor.DeclaringType); + JsonPropertyCollection parameterCollection = new JsonPropertyCollection(constructor.DeclaringType!); foreach (ParameterInfo parameterInfo in constructorParameters) { @@ -746,7 +746,7 @@ protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProper property.PropertyType = parameterInfo.ParameterType; property.AttributeProvider = new ReflectionAttributeProvider(parameterInfo); - SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out _); + SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name!, parameterInfo.Member.DeclaringType!, MemberSerialization.OptOut, out _); property.Readable = false; property.Writable = true; @@ -989,7 +989,7 @@ private List GetClassHierarchyForType(Type type) { List ret = new List(); - Type current = type; + Type? current = type; while (current != null && current != typeof(object)) { ret.Add(current); @@ -1127,7 +1127,7 @@ protected virtual JsonISerializableContract CreateISerializableContract(Type obj if (contract.IsInstantiable) { - ConstructorInfo constructorInfo = contract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] {typeof(SerializationInfo), typeof(StreamingContext)}, null); + ConstructorInfo? constructorInfo = contract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] {typeof(SerializationInfo), typeof(StreamingContext)}, null); if (constructorInfo != null) { ObjectConstructor creator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructorInfo); @@ -1292,6 +1292,13 @@ internal static bool CanConvertToString(Type type) return true; } +#if HAVE_DATE_ONLY + if (type == typeof(DateOnly) || type == typeof(TimeOnly)) + { + return true; + } +#endif + return false; } @@ -1304,36 +1311,36 @@ private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameter if (currentCallback != null) { - throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType)); + throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType!), attributeType)); } if (prevAttributeType != null) { - throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method)); + throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType!), method)); } if (method.IsVirtual) { - throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType)); + throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType!), attributeType)); } if (method.ReturnType != typeof(void)) { - throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method)); + throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method)); } if (attributeType == typeof(OnErrorAttribute)) { if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext)) { - throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext))); + throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method, typeof(StreamingContext), typeof(ErrorContext))); } } else { if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext)) { - throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext))); + throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType!), method, typeof(StreamingContext))); } } @@ -1346,7 +1353,7 @@ internal static string GetClrTypeFullName(Type type) { if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters()) { - return type.FullName; + return type.FullName!; } return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name); @@ -1405,7 +1412,7 @@ protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) // warning - this method use to cause errors with Intellitrace. Retest in VS Ultimate after changes IValueProvider valueProvider; -#if !(PORTABLE40 || PORTABLE || DOTNET || NETSTANDARD2_0) +#if !(PORTABLE40 || PORTABLE || DOTNET || NETSTANDARD2_0 || NET6_0_OR_GREATER) if (DynamicCodeGeneration) { valueProvider = new DynamicValueProvider(member); @@ -1437,7 +1444,7 @@ protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerializa property.ValueProvider = CreateMemberValueProvider(member); property.AttributeProvider = new ReflectionAttributeProvider(member); - SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out bool allowNonPublicAccess); + SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType!, memberSerialization, out bool allowNonPublicAccess); if (memberSerialization != MemberSerialization.Fields) { @@ -1635,7 +1642,7 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att private Predicate? CreateShouldSerializeTest(MemberInfo member) { - MethodInfo shouldSerializeMethod = member.DeclaringType.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes); + MethodInfo? shouldSerializeMethod = member.DeclaringType!.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes); if (shouldSerializeMethod == null || shouldSerializeMethod.ReturnType != typeof(bool)) { @@ -1650,7 +1657,7 @@ private void SetPropertySettingsFromAttributes(JsonProperty property, object att private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) { - MemberInfo? specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + MemberInfo? specifiedMember = member.DeclaringType!.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (specifiedMember == null) { specifiedMember = member.DeclaringType.GetField(member.Name + JsonTypeReflector.SpecifiedPostfix, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs index 096073f9..9fa99212 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs @@ -52,15 +52,15 @@ private BidirectionalDictionary GetMappings(object context) public object ResolveReference(object context, string reference) { - GetMappings(context).TryGetByFirst(reference, out object value); - return value; + GetMappings(context).TryGetByFirst(reference, out object? value); + return value!; } public string GetReference(object context, object value) { BidirectionalDictionary mappings = GetMappings(context); - if (!mappings.TryGetBySecond(value, out string reference)) + if (!mappings.TryGetBySecond(value, out string? reference)) { _referenceCount++; reference = _referenceCount.ToString(CultureInfo.InvariantCulture); diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs index 71b52e44..52367666 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs @@ -60,7 +60,7 @@ private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) if (assemblyName != null) { - Assembly assembly; + Assembly? assembly; #if !(DOTNET || PORTABLE40 || PORTABLE) // look, I don't like using obsolete methods as much as you do but this is the only way @@ -101,7 +101,7 @@ private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) { // if generic type, try manually parsing the type arguments for the case of dynamically loaded assemblies // example generic typeName format: System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] - if (typeName.IndexOf('`') >= 0) + if (StringUtils.IndexOf(typeName, '`') >= 0) { try { @@ -123,18 +123,18 @@ private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) } else { - return Type.GetType(typeName); + return Type.GetType(typeName)!; } } private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly) { Type? type = null; - int openBracketIndex = typeName.IndexOf('['); + int openBracketIndex = StringUtils.IndexOf(typeName, '['); if (openBracketIndex >= 0) { string genericTypeDefName = typeName.Substring(0, openBracketIndex); - Type genericTypeDef = assembly.GetType(genericTypeDefName); + Type? genericTypeDef = assembly.GetType(genericTypeDefName); if (genericTypeDef != null) { List genericTypeArguments = new List(); diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonArrayContract.cs index 75f4ba4e..8cf0b11c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonArrayContract.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonArrayContract.cs @@ -127,7 +127,7 @@ public JsonArrayContract(Type underlyingType) Type? tempCollectionType; if (IsArray) { - CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType); + CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType)!; IsReadOnlyOrFixedSize = true; _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); @@ -274,6 +274,7 @@ internal IWrappedCollection CreateWrapper(object list) if (_genericWrapperCreator == null) { MiscellaneousUtils.Assert(_genericCollectionDefinitionType != null); + MiscellaneousUtils.Assert(CollectionItemType != null); _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType); @@ -289,7 +290,7 @@ internal IWrappedCollection CreateWrapper(object list) constructorArgument = _genericCollectionDefinitionType; } - ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { constructorArgument }); + ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { constructorArgument })!; _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(genericWrapperConstructor); } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonContract.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonContract.cs index cd0f1001..98898910 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonContract.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonContract.cs @@ -248,7 +248,7 @@ internal JsonContract(Type underlyingType) IsNullable = ReflectionUtils.IsNullable(underlyingType); - NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType; + NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType)! : underlyingType; _createdType = CreatedType = NonNullableUnderlyingType; diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs index 9ab42815..2c29fd51 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs @@ -118,21 +118,21 @@ public JsonDictionaryContract(Type underlyingType) Type? keyType; Type? valueType; - if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType)) + if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; - if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IDictionary<,>))) + if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<,>))) { CreatedType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); } - else if (underlyingType.IsGenericType()) + else if (NonNullableUnderlyingType.IsGenericType()) { // ConcurrentDictionary<,> + IDictionary setter + null value = error // wrap to use generic setter // https://github.com/JamesNK/Exceptionless.Json/issues/1582 - Type typeDefinition = underlyingType.GetGenericTypeDefinition(); + Type typeDefinition = NonNullableUnderlyingType.GetGenericTypeDefinition(); if (typeDefinition.FullName == JsonTypeReflector.ConcurrentDictionaryTypeName) { ShouldCreateWrapper = true; @@ -140,17 +140,17 @@ public JsonDictionaryContract(Type underlyingType) } #if HAVE_READ_ONLY_COLLECTIONS - IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyDictionary<,>)); + IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyDictionary<,>)); #endif } #if HAVE_READ_ONLY_COLLECTIONS - else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyDictionary<,>), out _genericCollectionDefinitionType)) + else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<,>), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; - if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IReadOnlyDictionary<,>))) + if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<,>))) { CreatedType = typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType); } @@ -160,9 +160,9 @@ public JsonDictionaryContract(Type underlyingType) #endif else { - ReflectionUtils.GetDictionaryKeyValueTypes(UnderlyingType, out keyType, out valueType); + ReflectionUtils.GetDictionaryKeyValueTypes(NonNullableUnderlyingType, out keyType, out valueType); - if (UnderlyingType == typeof(IDictionary)) + if (NonNullableUnderlyingType == typeof(IDictionary)) { CreatedType = typeof(Dictionary); } @@ -176,9 +176,9 @@ public JsonDictionaryContract(Type underlyingType) typeof(IDictionary<,>).MakeGenericType(keyType, valueType)); #if HAVE_FSHARP_TYPES - if (!HasParameterizedCreatorInternal && underlyingType.Name == FSharpUtils.FSharpMapTypeName) + if (!HasParameterizedCreatorInternal && NonNullableUnderlyingType.Name == FSharpUtils.FSharpMapTypeName) { - FSharpUtils.EnsureInitialized(underlyingType.Assembly()); + FSharpUtils.EnsureInitialized(NonNullableUnderlyingType.Assembly()); _parameterizedCreator = FSharpUtils.Instance.CreateMap(keyType, valueType); } #endif @@ -207,7 +207,7 @@ public JsonDictionaryContract(Type underlyingType) if (DictionaryKeyType != null && DictionaryValueType != null && ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract( - underlyingType, + NonNullableUnderlyingType, DictionaryKeyType, DictionaryValueType, out Type? immutableCreatedType, @@ -223,9 +223,9 @@ internal IWrappedDictionary CreateWrapper(object dictionary) { if (_genericWrapperCreator == null) { - _genericWrapperType = typeof(DictionaryWrapper<,>).MakeGenericType(DictionaryKeyType, DictionaryValueType); + _genericWrapperType = typeof(DictionaryWrapper<,>).MakeGenericType(DictionaryKeyType!, DictionaryValueType!); - ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType! }); + ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType! })!; _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(genericWrapperConstructor); } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs index fc88ae07..ad6ac10c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs @@ -53,10 +53,10 @@ private T GetTokenValue(object value) ValidationUtils.ArgumentNotNull(value, nameof(value)); JValue v = (JValue)value; - return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture); + return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture)!; } - public object? Convert(object value, Type type) + public object Convert(object value, Type type) { ValidationUtils.ArgumentNotNull(value, nameof(value)); @@ -65,7 +65,7 @@ private T GetTokenValue(object value) throw new ArgumentException("Value is not a JToken.", nameof(value)); } - return _reader.CreateISerializableItem(token, type, _contract, _member); + return _reader.CreateISerializableItem(token, type, _contract, _member)!; } public object Convert(object value, TypeCode typeCode) @@ -74,7 +74,7 @@ public object Convert(object value, TypeCode typeCode) object? resolvedValue = (value is JValue v) ? v.Value : value; - return System.Convert.ChangeType(resolvedValue, typeCode, CultureInfo.InvariantCulture); + return System.Convert.ChangeType(resolvedValue, typeCode, CultureInfo.InvariantCulture)!; } public bool ToBoolean(object value) diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs index 7b6c2995..1b8b29c7 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs @@ -145,7 +145,7 @@ public void AddProperty(JsonProperty property) return property; } - private bool TryGetValue(string key, [NotNullWhen(true)]out JsonProperty? item) + private bool TryGetProperty(string key, [NotNullWhen(true)]out JsonProperty? item) { if (Dictionary == null) { @@ -167,7 +167,7 @@ private bool TryGetValue(string key, [NotNullWhen(true)]out JsonProperty? item) // KeyedCollection has an ordinal comparer if (comparisonType == StringComparison.Ordinal) { - if (TryGetValue(propertyName, out JsonProperty? property)) + if (TryGetProperty(propertyName, out JsonProperty? property)) { return property; } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs index 5cfbe71b..00de40b4 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs @@ -35,7 +35,7 @@ internal abstract class JsonSerializerInternalBase { private class ReferenceEqualsEqualityComparer : IEqualityComparer { - bool IEqualityComparer.Equals(object x, object y) + bool IEqualityComparer.Equals(object? x, object? y) { return ReferenceEquals(x, y); } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs index d9c9b3ec..1cd89cff 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs @@ -238,6 +238,15 @@ private JsonSerializerProxy GetInternalSerializer() token = writer.Token; } + if (contract != null && token != null) + { + if (!contract.UnderlyingType.IsAssignableFrom(token.GetType())) + { + throw JsonSerializationException.Create(reader, "Deserialized JSON type '{0}' is not compatible with expected type '{1}'." + .FormatWith(CultureInfo.InvariantCulture, token.GetType().FullName, contract.UnderlyingType.FullName)); + } + } + return token; } @@ -323,7 +332,7 @@ private JToken CreateJObject(JsonReader reader) return EnsureType(reader, s, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.StartConstructor: - string constructorName = reader.Value!.ToString(); + string constructorName = reader.Value!.ToString()!; return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Null: @@ -589,7 +598,7 @@ internal string GetExpectedDescription(JsonContract contract) throw JsonSerializationException.Create(reader, message); } - private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, [NotNullWhen(true)]out object? newValue, out string? id) + private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; @@ -683,7 +692,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref if (reader.TokenType == JsonToken.PropertyName) { - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (propertyName.Length > 0 && propertyName[0] == '$') { @@ -693,7 +702,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref do { - propertyName = reader.Value!.ToString(); + propertyName = reader.Value!.ToString()!; if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal)) { @@ -731,7 +740,7 @@ private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal)) { reader.ReadAndAssert(); - string qualifiedTypeName = reader.Value!.ToString(); + string qualifiedTypeName = reader.Value!.ToString()!; ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); @@ -889,7 +898,7 @@ private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType } else if (arrayContract.IsArray) { - Array a = Array.CreateInstance(arrayContract.CollectionItemType, list.Count); + Array a = Array.CreateInstance(arrayContract.CollectionItemType!, list.Count); list.CopyTo(a, 0); list = a; } @@ -958,11 +967,15 @@ private bool HasNoDefinedType(JsonContract? contract) { if (value is string s) { - return EnumUtils.ParseEnum(contract.NonNullableUnderlyingType, null, s, false); + return EnumUtils.ParseEnum( + contract.NonNullableUnderlyingType, + null, + s, + false); } if (ConvertUtils.IsInteger(primitiveContract.TypeCode)) { - return Enum.ToObject(contract.NonNullableUnderlyingType, value); + return Enum.ToObject(contract.NonNullableUnderlyingType, value!); } } else if (contract.NonNullableUnderlyingType == typeof(DateTime)) @@ -1100,7 +1113,8 @@ private bool CalculatePropertyDetails( if ((objectCreationHandling != ObjectCreationHandling.Replace) && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject || propertyConverter != null) - && property.Readable) + && property.Readable + && property.PropertyContract?.ContractType != JsonContractType.Linq) { currentValue = property.ValueProvider!.GetValue(target); gottenCurrentValue = true; @@ -1370,7 +1384,7 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso { case JsonToken.PropertyName: object keyValue = reader.Value!; - if (CheckPropertyName(reader, keyValue.ToString())) + if (CheckPropertyName(reader, keyValue.ToString()!)) { continue; } @@ -1385,23 +1399,25 @@ private object PopulateDictionary(IDictionary dictionary, JsonReader reader, Jso case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: { - keyValue = DateTimeUtils.TryParseDateTime(keyValue.ToString(), reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out DateTime dt) + keyValue = DateTimeUtils.TryParseDateTime(keyValue.ToString()!, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out DateTime dt) ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; + : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)!; break; } #if HAVE_DATE_TIME_OFFSET case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: { - keyValue = DateTimeUtils.TryParseDateTimeOffset(keyValue.ToString(), reader.DateFormatString, reader.Culture, out DateTimeOffset dt) + keyValue = DateTimeUtils.TryParseDateTimeOffset(keyValue.ToString()!, reader.DateFormatString, reader.Culture, out DateTimeOffset dt) ? dt - : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; + : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)!; break; } #endif default: - keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract!, contract.DictionaryKeyType)!; + keyValue = contract.KeyContract != null && contract.KeyContract.IsEnum + ? EnumUtils.ParseEnum(contract.KeyContract.NonNullableUnderlyingType, (Serializer._contractResolver as DefaultContractResolver)?.NamingStrategy, keyValue.ToString()!, false) + : EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)!; break; } } @@ -1736,7 +1752,7 @@ private object CreateISerializable(JsonReader reader, JsonISerializableContract switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value!.ToString(); + string memberName = reader.Value!.ToString()!; if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); @@ -1788,6 +1804,7 @@ private object CreateISerializable(JsonReader reader, JsonISerializableContract JsonConverter? itemConverter = GetConverter(itemContract, null, contract, member); JsonReader tokenReader = token.CreateReader(); + tokenReader.MaxDepth = Serializer.MaxDepth; tokenReader.ReadAndAssert(); // Move to first token object? result; @@ -1839,7 +1856,7 @@ private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, Js switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value!.ToString(); + string memberName = reader.Value!.ToString()!; try { @@ -2191,7 +2208,7 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC switch (reader.TokenType) { case JsonToken.PropertyName: - string memberName = reader.Value!.ToString(); + string memberName = reader.Value!.ToString()!; CreatorPropertyContext creatorPropertyContext = new CreatorPropertyContext(memberName) { @@ -2201,30 +2218,40 @@ private List ResolvePropertyAndCreatorValues(JsonObjectC propertyValues.Add(creatorPropertyContext); JsonProperty? property = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; - if (property != null && !property.Ignored) + if (property != null) { - if (property.PropertyContract == null) + if (!property.Ignored) { - property.PropertyContract = GetContractSafe(property.PropertyType); - } + if (property.PropertyContract == null) + { + property.PropertyContract = GetContractSafe(property.PropertyType); + } - JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, containerProperty); + JsonConverter? propertyConverter = GetConverter(property.PropertyContract, property.Converter, contract, containerProperty); - if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) - { - throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); - } + if (!reader.ReadForType(property.PropertyContract, propertyConverter != null)) + { + throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); + } - if (propertyConverter != null && propertyConverter.CanRead) - { - creatorPropertyContext.Value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, null); + if (propertyConverter != null && propertyConverter.CanRead) + { + creatorPropertyContext.Value = DeserializeConvertable(propertyConverter, reader, property.PropertyType!, null); + } + else + { + creatorPropertyContext.Value = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null); + } + + continue; } else { - creatorPropertyContext.Value = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null); + if (!reader.Read()) + { + throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName)); + } } - - continue; } else { @@ -2337,7 +2364,7 @@ private object PopulateObject(object newObject, JsonReader reader, JsonObjectCon { case JsonToken.PropertyName: { - string propertyName = reader.Value!.ToString(); + string propertyName = reader.Value!.ToString()!; if (CheckPropertyName(reader, propertyName)) { diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs index 6448a6e6..fbb7cfb5 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs @@ -396,10 +396,23 @@ private string GetReference(JsonWriter writer, object value) internal static bool TryConvertToString(object value, Type type, [NotNullWhen(true)]out string? s) { +#if HAVE_DATE_ONLY + if (value is DateOnly dateOnly) + { + s = dateOnly.ToString("yyyy'-'MM'-'dd", CultureInfo.InvariantCulture); + return true; + } + if (value is TimeOnly timeOnly) + { + s = timeOnly.ToString("HH':'mm':'ss.FFFFFFF", CultureInfo.InvariantCulture); + return true; + } +#endif + #if HAVE_TYPE_DESCRIPTOR if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter converter)) { - s = converter.ConvertToInvariantString(value); + s = converter.ConvertToInvariantString(value)!; return true; } #endif @@ -414,7 +427,7 @@ internal static bool TryConvertToString(object value, Type type, [NotNullWhen(tr if (value is Type t) { - s = t.AssemblyQualifiedName; + s = t.AssemblyQualifiedName!; return true; } @@ -532,7 +545,7 @@ private void SerializeObject(JsonWriter writer, object value, JsonObjectContract OnSerialized(writer, contract, value); } - private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, JsonProperty property, [NotNullWhen(true)]out JsonContract? memberContract, [NotNullWhen(true)]out object? memberValue) + private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, JsonProperty property, [NotNullWhen(true)]out JsonContract? memberContract, out object? memberValue) { if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) { @@ -546,14 +559,14 @@ private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContai if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) { - if (ShouldWriteReference(memberValue, property, memberContract!, contract, member)) + if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) { property.WritePropertyName(writer); WriteReference(writer, memberValue!); return false; } - if (!CheckForCircularReference(writer, memberValue, property, memberContract!, contract, member)) + if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) { return false; } @@ -572,7 +585,9 @@ private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContai } } +#pragma warning disable CS8762 // Parameter must have a non-null value when exiting in some condition. return true; +#pragma warning restore CS8762 // Parameter must have a non-null value when exiting in some condition. } } @@ -780,7 +795,7 @@ private void SerializeMultidimensionalArray(JsonWriter writer, Array values, Jso if (isTopLevel) { - object value = values.GetValue(newIndices); + object value = values.GetValue(newIndices)!; try { @@ -881,7 +896,7 @@ private void SerializeISerializable(JsonWriter writer, ISerializable value, Json if (ShouldWriteReference(serializationEntry.Value, null, valueContract, contract, member)) { writer.WritePropertyName(serializationEntry.Name); - WriteReference(writer, serializationEntry.Value); + WriteReference(writer, serializationEntry.Value!); } else if (CheckForCircularReference(writer, serializationEntry.Value, null, valueContract, contract, member)) { @@ -1182,7 +1197,7 @@ private string GetPropertyName(JsonWriter writer, object name, JsonContract cont return enumName; } - return Convert.ToString(name, CultureInfo.InvariantCulture); + return Convert.ToString(name, CultureInfo.InvariantCulture)!; } } } @@ -1194,7 +1209,7 @@ private string GetPropertyName(JsonWriter writer, object name, JsonContract cont else { escape = true; - return name.ToString(); + return name.ToString()!; } } diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs index 8953907a..685a9429 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs @@ -36,7 +36,7 @@ internal class JsonSerializerProxy : JsonSerializer { private readonly JsonSerializerInternalReader? _serializerReader; private readonly JsonSerializerInternalWriter? _serializerWriter; - private readonly JsonSerializer _serializer; + internal readonly JsonSerializer _serializer; public override event EventHandler? Error { diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonTypeReflector.cs index 693599f8..4b82c33d 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/JsonTypeReflector.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/JsonTypeReflector.cs @@ -1,4 +1,4 @@ -#region License +#region License // Copyright (c) 2007 James Newton-King // // Permission is hereby granted, free of charge, to any person @@ -33,6 +33,7 @@ using System.Security.Permissions; #endif using Exceptionless.Json.Utilities; +using System.Runtime.CompilerServices; #if !HAVE_LINQ using Exceptionless.Json.Utilities.LinqBridge; #else @@ -66,7 +67,7 @@ internal static class JsonTypeReflector private static ReflectionObject? _metadataTypeAttributeReflectionObject; #endif - public static T GetCachedAttribute(object attributeProvider) where T : Attribute + public static T? GetCachedAttribute(object attributeProvider) where T : Attribute { return CachedAttributeGetter.GetAttribute(attributeProvider); } @@ -99,7 +100,7 @@ public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter t public static DataContractAttribute? GetDataContractAttribute(Type type) { // DataContractAttribute does not have inheritance - Type currentType = type; + Type? currentType = type; while (currentType != null) { @@ -132,11 +133,11 @@ public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter t { if (propertyInfo.IsVirtual()) { - Type currentType = propertyInfo.DeclaringType; + Type? currentType = propertyInfo.DeclaringType; while (result == null && currentType != null) { - PropertyInfo baseProperty = (PropertyInfo)ReflectionUtils.GetMemberInfoFromType(currentType, propertyInfo); + PropertyInfo? baseProperty = (PropertyInfo?)ReflectionUtils.GetMemberInfoFromType(currentType, propertyInfo); if (baseProperty != null && baseProperty.IsVirtual()) { result = CachedAttributeGetter.GetAttribute(baseProperty); @@ -248,7 +249,7 @@ public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyTyp return param.GetType(); }).ToArray(); - ConstructorInfo parameterizedConstructorInfo = type.GetConstructor(paramTypes); + ConstructorInfo? parameterizedConstructorInfo = type.GetConstructor(paramTypes); if (parameterizedConstructorInfo != null) { @@ -308,9 +309,9 @@ public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyTyp } #endif - private static T GetAttribute(Type type) where T : Attribute + private static T? GetAttribute(Type type) where T : Attribute { - T attribute; + T? attribute; #if !(NET20 || DOTNET) Type? metadataType = GetAssociatedMetadataType(type); @@ -342,15 +343,15 @@ private static T GetAttribute(Type type) where T : Attribute return null; } - private static T GetAttribute(MemberInfo memberInfo) where T : Attribute + private static T? GetAttribute(MemberInfo memberInfo) where T : Attribute { - T attribute; + T? attribute; #if !(NET20 || DOTNET) - Type? metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); + Type? metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType!); if (metadataType != null) { - MemberInfo metadataTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(metadataType, memberInfo); + MemberInfo? metadataTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(metadataType, memberInfo); if (metadataTypeMemberInfo != null) { @@ -373,7 +374,7 @@ private static T GetAttribute(MemberInfo memberInfo) where T : Attribute { foreach (Type typeInterface in memberInfo.DeclaringType.GetInterfaces()) { - MemberInfo interfaceTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(typeInterface, memberInfo); + MemberInfo? interfaceTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(typeInterface, memberInfo); if (interfaceTypeMemberInfo != null) { @@ -423,7 +424,7 @@ public static bool IsSerializable(object provider) } #endif - public static T GetAttribute(object provider) where T : Attribute + public static T? GetAttribute(object provider) where T : Attribute { if (provider is Type type) { @@ -459,7 +460,9 @@ public static bool DynamicCodeGeneration { if (_dynamicCodeGeneration == null) { -#if HAVE_CAS +#if HAVE_DYNAMIC_CODE_COMPILED + _dynamicCodeGeneration = RuntimeFeature.IsDynamicCodeCompiled; +#elif HAVE_CAS try { new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand(); diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/NamingStrategy.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/NamingStrategy.cs index 1812f889..bea60c4a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/NamingStrategy.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/NamingStrategy.cs @@ -123,7 +123,7 @@ public override int GetHashCode() /// /// /// - public override bool Equals(object obj) => Equals(obj as NamingStrategy); + public override bool Equals(object? obj) => Equals(obj as NamingStrategy); /// /// Compare to another NamingStrategy diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs index cd1960b8..0f73e3c2 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/SerializationBinderAdapter.cs @@ -43,7 +43,7 @@ public SerializationBinderAdapter(SerializationBinder serializationBinder) public Type BindToType(string? assemblyName, string typeName) { - return SerializationBinder.BindToType(assemblyName, typeName); + return SerializationBinder.BindToType(assemblyName!, typeName)!; } public void BindToName(Type serializedType, out string? assemblyName, out string? typeName) diff --git a/src/Exceptionless/Newtonsoft.Json/Serialization/TraceJsonReader.cs b/src/Exceptionless/Newtonsoft.Json/Serialization/TraceJsonReader.cs index 858e81ee..75dd3bad 100644 --- a/src/Exceptionless/Newtonsoft.Json/Serialization/TraceJsonReader.cs +++ b/src/Exceptionless/Newtonsoft.Json/Serialization/TraceJsonReader.cs @@ -138,7 +138,7 @@ public override char QuoteChar public override object? Value => _innerReader.Value; - public override Type ?ValueType => _innerReader.ValueType; + public override Type? ValueType => _innerReader.ValueType; public override void Close() { diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/AsyncUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/AsyncUtils.cs index ea921b3c..285c16a6 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/AsyncUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/AsyncUtils.cs @@ -61,9 +61,9 @@ public static Task FromCanceled(this CancellationToken cancellationToken) public static Task FromCanceled(this CancellationToken cancellationToken) { MiscellaneousUtils.Assert(cancellationToken.IsCancellationRequested); -#pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. +#pragma warning disable CS8603 // Possible null reference return. return new Task(() => default, cancellationToken); -#pragma warning restore CS8653 // A default expression introduces a null value for a type parameter. +#pragma warning restore CS8603 // Possible null reference return. } // Task.Delay(0) is optimised as a cached task within the framework, and indeed @@ -95,11 +95,11 @@ public static Task ReadAsync(this TextReader reader, char[] buffer, int ind return cancellationToken.IsCancellationRequested ? FromCanceled(cancellationToken) : reader.ReadAsync(buffer, index, count); } - public static bool IsCompletedSucessfully(this Task task) + public static bool IsCompletedSuccessfully(this Task task) { // IsCompletedSucessfully is the faster method, but only currently exposed on .NET Core 2.0 -#if NETCOREAPP2_0 - return task.IsCompletedSucessfully; +#if NETCOREAPP2_0_OR_GREATER + return task.IsCompletedSuccessfully; #else return task.Status == TaskStatus.RanToCompletion; #endif diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/Base64Encoder.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/Base64Encoder.cs index 42458cba..ea3d7db8 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/Base64Encoder.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/Base64Encoder.cs @@ -78,12 +78,12 @@ public void Encode(byte[] buffer, int index, int count) if (_leftOverBytesCount > 0) { - if(FulfillFromLeftover(buffer, index, ref count)) + if (FulfillFromLeftover(buffer, index, ref count)) { return; } - int num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); + int num2 = Convert.ToBase64CharArray(_leftOverBytes!, 0, 3, _charsLine, 0); WriteChars(_charsLine, 0, num2); } @@ -145,7 +145,7 @@ public void Flush() { if (_leftOverBytesCount > 0) { - int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); + int count = Convert.ToBase64CharArray(_leftOverBytes!, 0, _leftOverBytesCount, _charsLine, 0); WriteChars(_charsLine, 0, count); _leftOverBytesCount = 0; } @@ -169,7 +169,7 @@ public async Task EncodeAsync(byte[] buffer, int index, int count, CancellationT return; } - int num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); + int num2 = Convert.ToBase64CharArray(_leftOverBytes!, 0, 3, _charsLine, 0); await WriteCharsAsync(_charsLine, 0, num2, cancellationToken).ConfigureAwait(false); } @@ -203,7 +203,7 @@ public Task FlushAsync(CancellationToken cancellationToken) if (_leftOverBytesCount > 0) { - int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); + int count = Convert.ToBase64CharArray(_leftOverBytes!, 0, _leftOverBytesCount, _charsLine, 0); _leftOverBytesCount = 0; return WriteCharsAsync(_charsLine, 0, count, cancellationToken); } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs index 0c6d633b..847d46e8 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs @@ -25,11 +25,14 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace Exceptionless.Json.Utilities { internal class BidirectionalDictionary + where TFirst : notnull + where TSecond : notnull { private readonly IDictionary _firstToSecond; private readonly IDictionary _secondToFirst; @@ -61,7 +64,7 @@ public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, public void Set(TFirst first, TSecond second) { - if (_firstToSecond.TryGetValue(first, out TSecond existingSecond)) + if (_firstToSecond.TryGetValue(first, out TSecond? existingSecond)) { if (!existingSecond!.Equals(second)) { @@ -69,7 +72,7 @@ public void Set(TFirst first, TSecond second) } } - if (_secondToFirst.TryGetValue(second, out TFirst existingFirst)) + if (_secondToFirst.TryGetValue(second, out TFirst? existingFirst)) { if (!existingFirst!.Equals(first)) { @@ -81,12 +84,12 @@ public void Set(TFirst first, TSecond second) _secondToFirst.Add(second, first); } - public bool TryGetByFirst(TFirst first, out TSecond second) + public bool TryGetByFirst(TFirst first, [NotNullWhen(true)] out TSecond? second) { return _firstToSecond.TryGetValue(first, out second); } - public bool TryGetBySecond(TSecond second, out TFirst first) + public bool TryGetBySecond(TSecond second, [NotNullWhen(true)] out TFirst? first) { return _secondToFirst.TryGetValue(second, out first); } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/BoxedPrimitives.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/BoxedPrimitives.cs new file mode 100644 index 00000000..20c95514 --- /dev/null +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/BoxedPrimitives.cs @@ -0,0 +1,154 @@ +#region License +// Copyright (c) 2022 James Newton-King +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +#endregion + +using System; +using System.Diagnostics; + +namespace Exceptionless.Json.Utilities +{ + internal static class BoxedPrimitives + { + internal static object Get(bool value) => value ? BooleanTrue : BooleanFalse; + + internal static readonly object BooleanTrue = true; + internal static readonly object BooleanFalse = false; + + internal static object Get(int value) => value switch + { + -1 => Int32_M1, + 0 => Int32_0, + 1 => Int32_1, + 2 => Int32_2, + 3 => Int32_3, + 4 => Int32_4, + 5 => Int32_5, + 6 => Int32_6, + 7 => Int32_7, + 8 => Int32_8, + _ => value, + }; + + // integers tend to be weighted towards a handful of low numbers; we could argue + // for days over the "correct" range to have special handling, but I'm arbitrarily + // mirroring the same decision as the IL opcodes, which has M1 thru 8 + internal static readonly object Int32_M1 = -1; + internal static readonly object Int32_0 = 0; + internal static readonly object Int32_1 = 1; + internal static readonly object Int32_2 = 2; + internal static readonly object Int32_3 = 3; + internal static readonly object Int32_4 = 4; + internal static readonly object Int32_5 = 5; + internal static readonly object Int32_6 = 6; + internal static readonly object Int32_7 = 7; + internal static readonly object Int32_8 = 8; + + internal static object Get(long value) => value switch + { + -1 => Int64_M1, + 0 => Int64_0, + 1 => Int64_1, + 2 => Int64_2, + 3 => Int64_3, + 4 => Int64_4, + 5 => Int64_5, + 6 => Int64_6, + 7 => Int64_7, + 8 => Int64_8, + _ => value, + }; + + internal static readonly object Int64_M1 = -1L; + internal static readonly object Int64_0 = 0L; + internal static readonly object Int64_1 = 1L; + internal static readonly object Int64_2 = 2L; + internal static readonly object Int64_3 = 3L; + internal static readonly object Int64_4 = 4L; + internal static readonly object Int64_5 = 5L; + internal static readonly object Int64_6 = 6L; + internal static readonly object Int64_7 = 7L; + internal static readonly object Int64_8 = 8L; + + internal static object Get(decimal value) + { + // Decimals can contain trailing zeros. For example 1 vs 1.0. Unfortunatly, Equals doesn't check for trailing zeros. + // There isn't a way to find out if a decimal has trailing zeros in older frameworks without calling ToString. + // Don't provide a cached boxed decimal value in older frameworks. + +#if NET6_0_OR_GREATER + // Number of bits scale is shifted by. + const int ScaleShift = 16; + + if (value == decimal.Zero) + { + Span bits = stackalloc int[4]; + int written = decimal.GetBits(value, bits); + MiscellaneousUtils.Assert(written == 4); + + byte scale = (byte)(bits[3] >> ScaleShift); + // Only use cached boxed value if value is zero and there is zero or one trailing zeros. + if (scale == 0) + { + return DecimalZero; + } + else if (scale == 1) + { + return DecimalZeroWithTrailingZero; + } + } +#endif + + return value; + } + +#if NET6_0_OR_GREATER + private static readonly object DecimalZero = decimal.Zero; + private static readonly object DecimalZeroWithTrailingZero = 0.0m; +#endif + + internal static object Get(double value) + { + if (value == 0.0d) + { + // Double supports -0.0. Detection logic from https://stackoverflow.com/a/4739883/11829. + return double.IsNegativeInfinity(1.0 / value) ? DoubleNegativeZero : DoubleZero; + } + if (double.IsInfinity(value)) + { + return double.IsPositiveInfinity(value) ? DoublePositiveInfinity : DoubleNegativeInfinity; + } + if (double.IsNaN(value)) + { + return DoubleNaN; + } + return value; + } + + internal static readonly object DoubleNaN = double.NaN; + internal static readonly object DoublePositiveInfinity = double.PositiveInfinity; + internal static readonly object DoubleNegativeInfinity = double.NegativeInfinity; + internal static readonly object DoubleZero = 0.0d; + internal static readonly object DoubleNegativeZero = -0.0d; + } +} diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionUtils.cs index 1a6b7643..f865903c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionUtils.cs @@ -289,7 +289,7 @@ private static IList GetDimensions(IList values, int dimensionsCount) break; } - object v = currentArray[0]; + object? v = currentArray[0]; if (v is IList list) { currentArray = list; @@ -341,11 +341,11 @@ private static object JaggedArrayGetValue(IList values, int[] indices) int index = indices[i]; if (i == indices.Length - 1) { - return currentList[index]; + return currentList[index]!; } else { - currentList = (IList)currentList[index]; + currentList = (IList)currentList[index]!; } } return currentList; @@ -368,15 +368,21 @@ public static Array ToMultidimensionalArray(IList values, Type type, int rank) public static T[] ArrayEmpty() { +#if !HAS_ARRAY_EMPTY // Enumerable.Empty no longer returns an empty array in .NET Core 3.0 return EmptyArrayContainer.Empty; +#else + return Array.Empty(); +#endif } +#if !HAS_ARRAY_EMPTY private static class EmptyArrayContainer { #pragma warning disable CA1825 // Avoid zero-length array allocations. public static readonly T[] Empty = new T[0]; #pragma warning restore CA1825 // Avoid zero-length array allocations. } +#endif } } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionWrapper.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionWrapper.cs index f4ebafe7..3630bc81 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionWrapper.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/CollectionWrapper.cs @@ -168,7 +168,7 @@ public virtual bool Remove(T item) public virtual IEnumerator GetEnumerator() { - return (_genericCollection ?? _list.Cast()).GetEnumerator(); + return (_genericCollection ?? _list!.Cast()).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() @@ -176,25 +176,25 @@ IEnumerator IEnumerable.GetEnumerator() return ((IEnumerable)_genericCollection! ?? _list!).GetEnumerator(); } - int IList.Add(object value) + int IList.Add(object? value) { VerifyValueType(value); - Add((T)value); + Add((T)value!); return (Count - 1); } - bool IList.Contains(object value) + bool IList.Contains(object? value) { if (IsCompatibleObject(value)) { - return Contains((T)value); + return Contains((T)value!); } return false; } - int IList.IndexOf(object value) + int IList.IndexOf(object? value) { if (_genericCollection != null) { @@ -203,7 +203,7 @@ int IList.IndexOf(object value) if (IsCompatibleObject(value)) { - return _list!.IndexOf((T)value); + return _list!.IndexOf((T)value!); } return -1; @@ -219,7 +219,7 @@ void IList.RemoveAt(int index) _list!.RemoveAt(index); } - void IList.Insert(int index, object value) + void IList.Insert(int index, object? value) { if (_genericCollection != null) { @@ -227,7 +227,7 @@ void IList.Insert(int index, object value) } VerifyValueType(value); - _list!.Insert(index, (T)value); + _list!.Insert(index, (T)value!); } bool IList.IsFixedSize @@ -246,15 +246,15 @@ bool IList.IsFixedSize } } - void IList.Remove(object value) + void IList.Remove(object? value) { if (IsCompatibleObject(value)) { - Remove((T)value); + Remove((T)value!); } } - object IList.this[int index] + object? IList.this[int index] { get { @@ -273,7 +273,7 @@ object IList.this[int index] } VerifyValueType(value); - _list![index] = (T)value; + _list![index] = (T?)value; } } @@ -297,7 +297,7 @@ object ICollection.SyncRoot } } - private static void VerifyValueType(object value) + private static void VerifyValueType(object? value) { if (!IsCompatibleObject(value)) { @@ -305,7 +305,7 @@ private static void VerifyValueType(object value) } } - private static bool IsCompatibleObject(object value) + private static bool IsCompatibleObject(object? value) { if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T))))) { diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/ConvertUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/ConvertUtils.cs index f284a6a0..d8cd21c7 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/ConvertUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/ConvertUtils.cs @@ -215,7 +215,7 @@ public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum) // performance? if (ReflectionUtils.IsNullableType(t)) { - Type nonNullable = Nullable.GetUnderlyingType(t); + Type nonNullable = Nullable.GetUnderlyingType(t)!; if (nonNullable.IsEnum()) { Type nullableUnderlyingType = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(nonNullable)); @@ -263,7 +263,7 @@ public static TimeSpan ParseTimeSpan(string input) { Type initialType = t.Value1; Type targetType = t.Value2; - MethodInfo castMethodInfo = targetType.GetMethod("op_Implicit", new[] { initialType }) + MethodInfo? castMethodInfo = targetType.GetMethod("op_Implicit", new[] { initialType }) ?? targetType.GetMethod("op_Explicit", new[] { initialType }); if (castMethodInfo == null) @@ -414,7 +414,7 @@ private static ConvertResult TryConvertInternal(object? initialValue, CultureInf if (ReflectionUtils.IsNullableType(targetType)) { - targetType = Nullable.GetUnderlyingType(targetType); + targetType = Nullable.GetUnderlyingType(targetType)!; } Type initialType = initialValue.GetType(); @@ -432,7 +432,7 @@ private static ConvertResult TryConvertInternal(object? initialValue, CultureInf { if (initialValue is string) { - value = Enum.Parse(targetType, initialValue.ToString(), true); + value = Enum.Parse(targetType, initialValue.ToString()!, true); return ConvertResult.Success; } else if (IsInteger(initialValue)) @@ -503,6 +503,18 @@ private static ConvertResult TryConvertInternal(object? initialValue, CultureInf value = Type.GetType(s, true); return ConvertResult.Success; } +#if HAVE_DATE_ONLY + if (targetType == typeof(DateOnly)) + { + value = DateOnly.ParseExact(s, "yyyy'-'MM'-'dd", CultureInfo.InvariantCulture); + return ConvertResult.Success; + } + if (targetType == typeof(TimeOnly)) + { + value = TimeOnly.ParseExact(s, "HH':'mm':'ss.FFFFFFF", CultureInfo.InvariantCulture); + return ConvertResult.Success; + } +#endif } #if HAVE_BIG_INTEGER diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/DateTimeUtils.cs index 3ecdab68..529b024c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/DateTimeUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/DateTimeUtils.cs @@ -179,9 +179,9 @@ private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset) internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset) { - long universialTicks = ToUniversalTicks(dateTime, offset); + long universalTicks = ToUniversalTicks(dateTime, offset); - return UniversialTicksToJavaScriptTicks(universialTicks); + return UniversalTicksToJavaScriptTicks(universalTicks); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime) @@ -193,12 +193,12 @@ internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool co { long ticks = (convertToUtc) ? ToUniversalTicks(dateTime) : dateTime.Ticks; - return UniversialTicksToJavaScriptTicks(ticks); + return UniversalTicksToJavaScriptTicks(ticks); } - private static long UniversialTicksToJavaScriptTicks(long universialTicks) + private static long UniversalTicksToJavaScriptTicks(long universalTicks) { - long javaScriptTicks = (universialTicks - InitialJavaScriptDateTicks) / 10000; + long javaScriptTicks = (universalTicks - InitialJavaScriptDateTicks) / 10000; return javaScriptTicks; } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/DictionaryWrapper.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/DictionaryWrapper.cs index 30d7e9e0..6a97939e 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/DictionaryWrapper.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/DictionaryWrapper.cs @@ -89,7 +89,7 @@ public void Add(TKey key, TValue value) { if (_dictionary != null) { - _dictionary.Add(key, value); + _dictionary.Add(key!, value); } else if (_genericDictionary != null) { @@ -105,7 +105,7 @@ public bool ContainsKey(TKey key) { if (_dictionary != null) { - return _dictionary.Contains(key); + return _dictionary.Contains(key!); } #if HAVE_READ_ONLY_COLLECTIONS else if (_readOnlyDictionary != null) @@ -144,9 +144,9 @@ public bool Remove(TKey key) { if (_dictionary != null) { - if (_dictionary.Contains(key)) + if (_dictionary.Contains(key!)) { - _dictionary.Remove(key); + _dictionary.Remove(key!); return true; } else @@ -166,11 +166,13 @@ public bool Remove(TKey key) } } - public bool TryGetValue(TKey key, [MaybeNull]out TValue value) +#pragma warning disable CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). + public bool TryGetValue(TKey key, out TValue? value) +#pragma warning restore CS8767 // Nullability of reference types in type of parameter doesn't match implicitly implemented member (possibly because of nullability attributes). { if (_dictionary != null) { - if (!_dictionary.Contains(key)) + if (!_dictionary.Contains(key!)) { #pragma warning disable CS8653 // A default expression introduces a null value for a type parameter. value = default; @@ -179,7 +181,7 @@ public bool TryGetValue(TKey key, [MaybeNull]out TValue value) } else { - value = (TValue)_dictionary[key]; + value = (TValue)_dictionary[key!]!; return true; } } @@ -222,7 +224,7 @@ public TValue this[TKey key] { if (_dictionary != null) { - return (TValue)_dictionary[key]; + return (TValue)_dictionary[key!]!; } #if HAVE_READ_ONLY_COLLECTIONS else if (_readOnlyDictionary != null) @@ -239,7 +241,7 @@ public TValue this[TKey key] { if (_dictionary != null) { - _dictionary[key] = value; + _dictionary[key!] = value; } #if HAVE_READ_ONLY_COLLECTIONS else if (_readOnlyDictionary != null) @@ -319,7 +321,7 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) while (e.MoveNext()) { DictionaryEntry entry = e.Entry; - array[arrayIndex++] = new KeyValuePair((TKey)entry.Key, (TValue)entry.Value); + array[arrayIndex++] = new KeyValuePair((TKey)entry.Key, (TValue)entry.Value!); } } finally @@ -385,13 +387,13 @@ public bool Remove(KeyValuePair item) { if (_dictionary != null) { - if (_dictionary.Contains(item.Key)) + if (_dictionary.Contains(item.Key!)) { - object value = _dictionary[item.Key]; + object? value = _dictionary[item.Key!]; if (Equals(value, item.Value)) { - _dictionary.Remove(item.Key); + _dictionary.Remove(item.Key!); return true; } else @@ -420,7 +422,7 @@ public IEnumerator> GetEnumerator() { if (_dictionary != null) { - return _dictionary.Cast().Select(de => new KeyValuePair((TKey)de.Key, (TValue)de.Value)).GetEnumerator(); + return _dictionary.Cast().Select(de => new KeyValuePair((TKey)de.Key, (TValue)de.Value!)).GetEnumerator(); } #if HAVE_READ_ONLY_COLLECTIONS else if (_readOnlyDictionary != null) @@ -439,7 +441,7 @@ IEnumerator IEnumerable.GetEnumerator() return GetEnumerator(); } - void IDictionary.Add(object key, object value) + void IDictionary.Add(object key, object? value) { if (_dictionary != null) { @@ -453,7 +455,7 @@ void IDictionary.Add(object key, object value) #endif else { - GenericDictionary.Add((TKey)key, (TValue)value); + GenericDictionary.Add((TKey)key, (TValue)value!); } } @@ -490,8 +492,12 @@ void IDictionary.Add(object key, object value) #endif else { + // Consider changing this code to call GenericDictionary.Remove when value is null. + // #pragma warning disable CS8601 // Possible null reference assignment. +#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type. GenericDictionary[(TKey)key] = (TValue)value; +#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type. #pragma warning restore CS8601 // Possible null reference assignment. } } @@ -511,9 +517,9 @@ public DictionaryEnumerator(IEnumerator Entry.Key; - public object Value => Entry.Value; + public object? Value => Entry.Value; - public object Current => new DictionaryEntry(_e.Current.Key, _e.Current.Value); + public object Current => new DictionaryEntry(_e.Current.Key!, _e.Current.Value); public bool MoveNext() { diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs index 5c9205b0..879bf89c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs @@ -37,7 +37,7 @@ internal sealed class DynamicProxyMetaObject : DynamicMetaObject private readonly DynamicProxy _proxy; internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy proxy) - : base(expression, BindingRestrictions.Empty, value) + : base(expression, BindingRestrictions.Empty, value!) { _proxy = proxy; } @@ -109,7 +109,7 @@ public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, Dy new GetBinderAdapter(binder), NoArgs, fallback(null), - e => binder.FallbackInvoke(e, args, null) + e => binder.FallbackInvoke(e!, args, null) ), null ); @@ -197,7 +197,7 @@ private static ConstantExpression Constant(DynamicMetaObjectBinder binder) Type t = binder.GetType(); while (!t.IsVisible()) { - t = t.BaseType(); + t = t.BaseType()!; } return Expression.Constant(binder, t); } @@ -256,7 +256,7 @@ private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMe Expression.Condition( Expression.Call( Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), + typeof(DynamicProxy).GetMethod(methodName)!, callArgs ), resultMetaObject.Expression, @@ -304,7 +304,7 @@ private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObj Expression.Condition( Expression.Call( Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), + typeof(DynamicProxy).GetMethod(methodName)!, callArgs ), result, @@ -342,7 +342,7 @@ private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjec Expression.Condition( Expression.Call( Expression.Constant(_proxy), - typeof(DynamicProxy).GetMethod(methodName), + typeof(DynamicProxy).GetMethod(methodName)!, callArgs ), Expression.Empty(), @@ -366,7 +366,7 @@ private BindingRestrictions GetRestrictions() public override IEnumerable GetDynamicMemberNames() { - return _proxy.GetDynamicMemberNames((T)Value); + return _proxy.GetDynamicMemberNames((T)Value!); } // It is okay to throw NotSupported from this binder. This object @@ -380,7 +380,7 @@ internal GetBinderAdapter(InvokeMemberBinder binder) : { } - public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { throw new NotSupportedException(); } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs index 7a906d0b..8cde924a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs @@ -51,7 +51,7 @@ private static DynamicMethod CreateDynamicMethod(string name, Type? returnType, public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { - DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object[]) }, method.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString()!, typeof(object), new[] { typeof(object[]) }, method.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, generator, 0); @@ -61,7 +61,7 @@ public override ObjectConstructor CreateParameterizedConstructor(MethodB public override MethodCall CreateMethodCall(MethodBase method) { - DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString()!, typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, generator, 1); @@ -80,14 +80,14 @@ private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator generator.Emit(OpCodes.Ldlen); generator.Emit(OpCodes.Ldc_I4, args.Length); generator.Emit(OpCodes.Beq, argsOk); - generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)); + generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)!); generator.Emit(OpCodes.Throw); generator.MarkLabel(argsOk); if (!method.IsConstructor && !method.IsStatic) { - generator.PushInstance(method.DeclaringType); + generator.PushInstance(method.DeclaringType!); } LocalBuilder localConvertible = generator.DeclareLocal(typeof(IConvertible)); @@ -103,7 +103,7 @@ private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator if (parameterType.IsByRef) { - parameterType = parameterType.GetElementType(); + parameterType = parameterType.GetElementType()!; LocalBuilder localVariable = generator.DeclareLocal(parameterType); @@ -170,7 +170,7 @@ private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator if (parameterType.IsPrimitive()) { // for primitive types we need to handle type widening (e.g. short -> int) - MethodInfo toParameterTypeMethod = typeof(IConvertible) + MethodInfo? toParameterTypeMethod = typeof(IConvertible) .GetMethod("To" + parameterType.Name, new[] { typeof(IFormatProvider) }); if (toParameterTypeMethod != null) @@ -227,7 +227,7 @@ private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator } Type returnType = method.IsConstructor - ? method.DeclaringType + ? method.DeclaringType! : ((MethodInfo)method).ReturnType; if (returnType != typeof(void)) @@ -268,7 +268,7 @@ private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator } else { - ConstructorInfo constructorInfo = + ConstructorInfo? constructorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, ReflectionUtils.EmptyTypes, null); if (constructorInfo == null) @@ -284,7 +284,7 @@ private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator public override Func CreateGet(PropertyInfo propertyInfo) { - DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new[] { typeof(T) }, propertyInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new[] { typeof(T) }, propertyInfo.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateGetPropertyIL(propertyInfo, generator); @@ -294,7 +294,7 @@ private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { - MethodInfo getMethod = propertyInfo.GetGetMethod(true); + MethodInfo? getMethod = propertyInfo.GetGetMethod(true); if (getMethod == null) { throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name)); @@ -302,7 +302,7 @@ private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator if (!getMethod.IsStatic) { - generator.PushInstance(propertyInfo.DeclaringType); + generator.PushInstance(propertyInfo.DeclaringType!); } generator.CallMethod(getMethod); @@ -314,12 +314,12 @@ private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator { if (fieldInfo.IsLiteral) { - object constantValue = fieldInfo.GetValue(null); + object constantValue = fieldInfo.GetValue(null)!; Func getter = o => constantValue; return getter; } - DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateGetFieldIL(fieldInfo, generator); @@ -331,7 +331,7 @@ private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator { if (!fieldInfo.IsStatic) { - generator.PushInstance(fieldInfo.DeclaringType); + generator.PushInstance(fieldInfo.DeclaringType!); generator.Emit(OpCodes.Ldfld, fieldInfo); } else @@ -345,7 +345,7 @@ private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator public override Action CreateSet(FieldInfo fieldInfo) { - DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateSetFieldIL(fieldInfo, generator); @@ -357,7 +357,7 @@ internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator g { if (!fieldInfo.IsStatic) { - generator.PushInstance(fieldInfo.DeclaringType); + generator.PushInstance(fieldInfo.DeclaringType!); } generator.Emit(OpCodes.Ldarg_1); @@ -377,7 +377,7 @@ internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator g public override Action CreateSet(PropertyInfo propertyInfo) { - DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); + DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType!); ILGenerator generator = dynamicMethod.GetILGenerator(); GenerateCreateSetPropertyIL(propertyInfo, generator); @@ -387,10 +387,10 @@ internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator g internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { - MethodInfo setMethod = propertyInfo.GetSetMethod(true); + MethodInfo setMethod = propertyInfo.GetSetMethod(true)!; if (!setMethod.IsStatic) { - generator.PushInstance(propertyInfo.DeclaringType); + generator.PushInstance(propertyInfo.DeclaringType!); } generator.Emit(OpCodes.Ldarg_1); diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicUtils.cs index 0dd55c0a..8c6cf31a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/DynamicUtils.cs @@ -64,7 +64,7 @@ private static void Init() { if (!_init) { - Type binderType = Type.GetType(BinderTypeName, false); + Type? binderType = Type.GetType(BinderTypeName, false); if (binderType == null) { throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName)); @@ -82,15 +82,15 @@ private static void Init() private static object CreateSharpArgumentInfoArray(params int[] values) { - Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName); - Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName); + Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true)!; + Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName, true)!; Array a = Array.CreateInstance(csharpArgumentInfoType, values.Length); for (int i = 0; i < values.Length; i++) { - MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) }); - object arg = createArgumentInfoMethod.Invoke(null, new object?[] { 0, null }); + MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) })!; + object arg = createArgumentInfoMethod.Invoke(null, new object?[] { 0, null })!; a.SetValue(arg, i); } @@ -99,16 +99,16 @@ private static object CreateSharpArgumentInfoArray(params int[] values) private static void CreateMemberCalls() { - Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true); - Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName, true); - Type binderType = Type.GetType(BinderTypeName, true); + Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true)!; + Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName, true)!; + Type binderType = Type.GetType(BinderTypeName, true)!; Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType); - MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); + MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType })!; _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getMemberMethod); - MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType }); + MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType })!; _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(setMemberMethod); } #endif @@ -161,7 +161,7 @@ public NoThrowGetBinderMember(GetMemberBinder innerBinder) _innerBinder = innerBinder; } - public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { DynamicMetaObject retMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty()); @@ -183,7 +183,7 @@ public NoThrowSetBinderMember(SetMemberBinder innerBinder) _innerBinder = innerBinder; } - public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) + public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject? errorSuggestion) { DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value }); diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/EnumUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/EnumUtils.cs index 9f584776..7c31e3dc 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/EnumUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/EnumUtils.cs @@ -60,11 +60,11 @@ private static EnumInfo InitializeValuesAndNames(StructMultiKey() .Select(a => a.Value) .SingleOrDefault(); diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs index ec7ff005..9ea1631a 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs @@ -111,7 +111,7 @@ private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpres bool isByRef = false; if (parameterType.IsByRef) { - parameterType = parameterType.GetElementType(); + parameterType = parameterType.GetElementType()!; isByRef = true; } @@ -144,7 +144,7 @@ private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpres } else { - Expression readParameter = EnsureCastExpression(targetParameterExpression!, method.DeclaringType); + Expression readParameter = EnsureCastExpression(targetParameterExpression!, method.DeclaringType!); callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression); } @@ -194,7 +194,7 @@ public override Func CreateDefaultConstructor(Type type) // avoid error from expressions compiler because of abstract class if (type.IsAbstract()) { - return () => (T)Activator.CreateInstance(type); + return () => (T)Activator.CreateInstance(type)!; } try @@ -214,7 +214,7 @@ public override Func CreateDefaultConstructor(Type type) { // an error can be thrown if constructor is not valid on Win8 // will have INVOCATION_FLAGS_NON_W8P_FX_API invocation flag - return () => (T)Activator.CreateInstance(type); + return () => (T)Activator.CreateInstance(type)!; } } @@ -240,7 +240,7 @@ public override Func CreateDefaultConstructor(Type type) } else { - Expression readParameter = EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType); + Expression readParameter = EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType!); resultExpression = Expression.MakeMemberAccess(readParameter, propertyInfo); } @@ -266,7 +266,7 @@ public override Func CreateDefaultConstructor(Type type) } else { - Expression sourceExpression = EnsureCastExpression(sourceParameter, fieldInfo.DeclaringType); + Expression sourceExpression = EnsureCastExpression(sourceParameter, fieldInfo.DeclaringType!); fieldExpression = Expression.Field(sourceExpression, fieldInfo); } @@ -283,7 +283,7 @@ public override Func CreateDefaultConstructor(Type type) // use reflection for structs // expression doesn't correctly set value - if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly) + if (fieldInfo.DeclaringType!.IsValueType() || fieldInfo.IsInitOnly) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(fieldInfo); } @@ -298,7 +298,7 @@ public override Func CreateDefaultConstructor(Type type) } else { - Expression sourceExpression = EnsureCastExpression(sourceParameterExpression, fieldInfo.DeclaringType); + Expression sourceExpression = EnsureCastExpression(sourceParameterExpression, fieldInfo.DeclaringType!); fieldExpression = Expression.Field(sourceExpression, fieldInfo); } @@ -319,7 +319,7 @@ public override Func CreateDefaultConstructor(Type type) // use reflection for structs // expression doesn't correctly set value - if (propertyInfo.DeclaringType.IsValueType()) + if (propertyInfo.DeclaringType!.IsValueType()) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(propertyInfo); } @@ -345,7 +345,7 @@ public override Func CreateDefaultConstructor(Type type) } else { - Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType); + Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType!); setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter); } @@ -372,7 +372,7 @@ private Expression EnsureCastExpression(Expression expression, Type targetType, if (allowWidening && targetType.IsPrimitive()) { - MethodInfo toTargetTypeMethod = typeof(Convert) + MethodInfo? toTargetTypeMethod = typeof(Convert) .GetMethod("To" + targetType.Name, new[] { typeof(object) }); if (toTargetTypeMethod != null) diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/FSharpUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/FSharpUtils.cs index 2f9b8229..7d9bd645 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/FSharpUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/FSharpUtils.cs @@ -60,7 +60,7 @@ private FSharpUtils(Assembly fsharpCoreAssembly) { FSharpCoreAssembly = fsharpCoreAssembly; - Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType"); + Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType")!; MethodInfo isUnionMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "IsUnion", BindingFlags.Public | BindingFlags.Static); IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(isUnionMethodInfo)!; @@ -68,23 +68,23 @@ private FSharpUtils(Assembly fsharpCoreAssembly) MethodInfo getUnionCasesMethodInfo = GetMethodWithNonPublicFallback(fsharpType, "GetUnionCases", BindingFlags.Public | BindingFlags.Static); GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(getUnionCasesMethodInfo)!; - Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue"); + Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue")!; PreComputeUnionTagReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionTagReader"); PreComputeUnionReader = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionReader"); PreComputeUnionConstructor = CreateFSharpFuncCall(fsharpValue, "PreComputeUnionConstructor"); - Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo"); + Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo")!; GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Name")!)!; GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("Tag")!)!; GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(unionCaseInfo.GetProperty("DeclaringType")!)!; - GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(unionCaseInfo.GetMethod("GetFields")); + GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(unionCaseInfo.GetMethod("GetFields")!); - Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule"); - _ofSeq = listModule.GetMethod("OfSeq"); + Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule")!; + _ofSeq = listModule.GetMethod("OfSeq")!; - _mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2"); + _mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2")!; } private static readonly object Lock = new object(); @@ -133,7 +133,7 @@ public static void EnsureInitialized(Assembly fsharpCoreAssembly) private static MethodInfo GetMethodWithNonPublicFallback(Type type, string methodName, BindingFlags bindingFlags) { - MethodInfo methodInfo = type.GetMethod(methodName, bindingFlags); + MethodInfo methodInfo = type.GetMethod(methodName, bindingFlags)!; // if no matching method then attempt to find with nonpublic flag // this is required because in WinApps some methods are private but always using NonPublic breaks medium trust @@ -141,7 +141,7 @@ private static MethodInfo GetMethodWithNonPublicFallback(Type type, string metho // https://github.com/JamesNK/Exceptionless.Json/issues/821 if (methodInfo == null && (bindingFlags & BindingFlags.NonPublic) != BindingFlags.NonPublic) { - methodInfo = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic); + methodInfo = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic)!; } return methodInfo!; @@ -150,7 +150,7 @@ private static MethodInfo GetMethodWithNonPublicFallback(Type type, string metho private static MethodCall CreateFSharpFuncCall(Type type, string methodName) { MethodInfo innerMethodInfo = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Public | BindingFlags.Static); - MethodInfo invokeFunc = innerMethodInfo.ReturnType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance); + MethodInfo invokeFunc = innerMethodInfo.ReturnType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance)!; MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(innerMethodInfo); MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(invokeFunc)!; @@ -175,17 +175,17 @@ public ObjectConstructor CreateSeq(Type t) public ObjectConstructor CreateMap(Type keyType, Type valueType) { - MethodInfo creatorDefinition = typeof(FSharpUtils).GetMethod("BuildMapCreator"); + MethodInfo creatorDefinition = typeof(FSharpUtils).GetMethod("BuildMapCreator")!; MethodInfo creatorGeneric = creatorDefinition.MakeGenericMethod(keyType, valueType); - return (ObjectConstructor)creatorGeneric.Invoke(this, null); + return (ObjectConstructor)creatorGeneric.Invoke(this, null)!; } public ObjectConstructor BuildMapCreator() { Type genericMapType = _mapType.MakeGenericType(typeof(TKey), typeof(TValue)); - ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable>) }); + ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable>) })!; ObjectConstructor ctorDelegate = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(ctor); ObjectConstructor creator = args => diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs index b24e7d1b..76df8eff 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs @@ -116,17 +116,17 @@ internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type if (underlyingType.IsGenericType()) { Type underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition(); - string name = underlyingTypeDefinition.FullName; + string name = underlyingTypeDefinition.FullName!; - ImmutableCollectionTypeInfo definition = ArrayContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); + ImmutableCollectionTypeInfo? definition = ArrayContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); if (definition != null) { - Type createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); - Type builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); + Type? createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); + Type? builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); if (createdTypeDefinition != null && builderTypeDefinition != null) { - MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => m.Name == "CreateRange" && m.GetParameters().Length == 1); + MethodInfo? mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => m.Name == "CreateRange" && m.GetParameters().Length == 1); if (mb != null) { createdType = createdTypeDefinition.MakeGenericType(collectionItemType); @@ -148,17 +148,17 @@ internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, if (underlyingType.IsGenericType()) { Type underlyingTypeDefinition = underlyingType.GetGenericTypeDefinition(); - string name = underlyingTypeDefinition.FullName; + string name = underlyingTypeDefinition.FullName!; - ImmutableCollectionTypeInfo definition = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); + ImmutableCollectionTypeInfo? definition = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name); if (definition != null) { - Type createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); - Type builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); + Type? createdTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.CreatedTypeName); + Type? builderTypeDefinition = underlyingTypeDefinition.Assembly().GetType(definition.BuilderTypeName); if (createdTypeDefinition != null && builderTypeDefinition != null) { - MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => + MethodInfo? mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => { ParameterInfo[] parameters = m.GetParameters(); diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/JavaScriptUtils.cs index a6d3df71..be4cdf4c 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/JavaScriptUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/JavaScriptUtils.cs @@ -289,6 +289,7 @@ public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, ch } else { + MiscellaneousUtils.Assert(writeBuffer != null); writer.Write(writeBuffer, 0, UnicodeTextLength); } } @@ -386,7 +387,7 @@ private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter w bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { Task task = writer.WriteAsync(delimiter, cancellationToken); - if (!task.IsCompletedSucessfully()) + if (!task.IsCompletedSuccessfully()) { return WriteEscapedJavaScriptStringWithDelimitersAsync(task, writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } @@ -394,7 +395,7 @@ private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter w if (!StringUtils.IsNullOrEmpty(s)) { task = WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); - if (task.IsCompletedSucessfully()) + if (task.IsCompletedSuccessfully()) { return writer.WriteAsync(delimiter, cancellationToken); } @@ -629,7 +630,7 @@ public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime return true; } - private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, out string? errorMessage) + private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, [NotNullWhen(false)] out string? errorMessage) { integer = null; errorMessage = null; diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs index 0a3c3eb0..f71ef0b7 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs @@ -50,7 +50,7 @@ public override ObjectConstructor CreateParameterizedConstructor(MethodB return a => c.Invoke(a); } - return a => method.Invoke(null, a); + return a => method.Invoke(null, a)!; } public override MethodCall CreateMethodCall(MethodBase method) @@ -71,10 +71,14 @@ public override Func CreateDefaultConstructor(Type type) if (type.IsValueType()) { - return () => (T)Activator.CreateInstance(type); + return () => (T)Activator.CreateInstance(type)!; } - ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(type, true); + ConstructorInfo? constructorInfo = ReflectionUtils.GetDefaultConstructor(type, true); + if (constructorInfo == null) + { + throw new InvalidOperationException("Unable to find default constructor for " + type.FullName); + } return () => (T)constructorInfo.Invoke(null); } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs index dd71d9eb..c6b466c0 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs @@ -92,7 +92,7 @@ public static string ToString(object? value) return "{null}"; } - return (value is string s) ? @"""" + s + @"""" : value!.ToString(); + return (value is string s) ? @"""" + s + @"""" : value!.ToString()!; } public static int ByteArrayCompare(byte[] a1, byte[] a2) @@ -131,7 +131,7 @@ public static string GetLocalName(string qualifiedName) public static void GetQualifiedNameParts(string qualifiedName, out string? prefix, out string localName) { - int colonPosition = qualifiedName.IndexOf(':'); + int colonPosition = StringUtils.IndexOf(qualifiedName, ':'); if ((colonPosition == -1 || colonPosition == 0) || (qualifiedName.Length - 1) == colonPosition) { diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/NullableAttributes.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/NullableAttributes.cs index 1ca583c3..9e564125 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/NullableAttributes.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/NullableAttributes.cs @@ -23,6 +23,8 @@ // OTHER DEALINGS IN THE SOFTWARE. #endregion +#if !HAVE_NULLABLE_ATTRIBUTES + namespace System.Diagnostics.CodeAnalysis { /// Specifies that an output will not be null even if the corresponding type allows it. @@ -72,3 +74,5 @@ internal class DoesNotReturnIfAttribute : Attribute public bool ParameterValue { get; } } } + +#endif diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/ReflectionUtils.cs index 161796c6..c78fc602 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -177,7 +177,7 @@ private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder? bi return typeName + (assemblyName == null ? "" : ", " + assemblyName); } - return t.AssemblyQualifiedName; + return t.AssemblyQualifiedName!; } private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) @@ -187,19 +187,30 @@ private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) // loop through the type name and filter out qualified assembly details from nested type names bool writingAssemblyName = false; bool skippingAssemblyDetails = false; + bool followBrackets = false; for (int i = 0; i < fullyQualifiedTypeName.Length; i++) { char current = fullyQualifiedTypeName[i]; switch (current) { case '[': + writingAssemblyName = false; + skippingAssemblyDetails = false; + followBrackets = true; + builder.Append(current); + break; case ']': writingAssemblyName = false; skippingAssemblyDetails = false; + followBrackets = false; builder.Append(current); break; case ',': - if (!writingAssemblyName) + if (followBrackets) + { + builder.Append(current); + } + else if (!writingAssemblyName) { writingAssemblyName = true; builder.Append(current); @@ -210,6 +221,7 @@ private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) } break; default: + followBrackets = false; if (!skippingAssemblyDetails) { builder.Append(current); @@ -233,12 +245,12 @@ public static bool HasDefaultConstructor(Type t, bool nonPublic) return (GetDefaultConstructor(t, nonPublic) != null); } - public static ConstructorInfo GetDefaultConstructor(Type t) + public static ConstructorInfo? GetDefaultConstructor(Type t) { return GetDefaultConstructor(t, false); } - public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic) + public static ConstructorInfo? GetDefaultConstructor(Type t, bool nonPublic) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; if (nonPublic) @@ -271,14 +283,14 @@ public static bool IsNullableType(Type t) public static Type EnsureNotNullableType(Type t) { return (IsNullableType(t)) - ? Nullable.GetUnderlyingType(t) + ? Nullable.GetUnderlyingType(t)! : t; } public static Type EnsureNotByRefType(Type t) { return (t.IsByRef && t.HasElementType) - ? t.GetElementType() + ? t.GetElementType()! : t; } @@ -358,8 +370,9 @@ public static bool InheritsGenericDefinition(Type type, Type genericClassDefinit return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType); } - private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type? implementingType) + private static bool InheritsGenericDefinitionInternal(Type type, Type genericClassDefinition, out Type? implementingType) { + Type? currentType = type; do { if (currentType.IsGenericType() && genericClassDefinition == currentType.GetGenericTypeDefinition()) @@ -449,7 +462,7 @@ public static Type GetMemberUnderlyingType(MemberInfo member) case MemberTypes.Property: return ((PropertyInfo)member).PropertyType; case MemberTypes.Event: - return ((EventInfo)member).EventHandlerType; + return ((EventInfo)member).EventHandlerType!; case MemberTypes.Method: return ((MethodInfo)member).ReturnType; default: @@ -497,7 +510,7 @@ public static bool IsIndexedProperty(PropertyInfo property) /// The member. /// The target object. /// The member's value on the object. - public static object GetMemberValue(MemberInfo member, object target) + public static object? GetMemberValue(MemberInfo member, object target) { ValidationUtils.ArgumentNotNull(member, nameof(member)); ValidationUtils.ArgumentNotNull(target, nameof(target)); @@ -701,7 +714,7 @@ private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags return false; } - Type declaringType = propertyInfo.DeclaringType; + Type declaringType = propertyInfo.DeclaringType!; if (!declaringType.IsGenericType()) { return false; @@ -725,12 +738,12 @@ private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags return true; } - public static T GetAttribute(object attributeProvider) where T : Attribute + public static T? GetAttribute(object attributeProvider) where T : Attribute { return GetAttribute(attributeProvider, true); } - public static T GetAttribute(object attributeProvider, bool inherit) where T : Attribute + public static T? GetAttribute(object attributeProvider, bool inherit) where T : Attribute { T[] attributes = GetAttributes(attributeProvider, inherit); @@ -872,7 +885,7 @@ public static Attribute[] GetAttributes(object provider, Type? attributeType, bo return null; } - public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo) + public static MemberInfo? GetMemberInfoFromType(Type targetType, MemberInfo memberInfo) { const BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; @@ -904,8 +917,10 @@ public static IEnumerable GetFields(Type targetType, BindingFlags bin } #if !PORTABLE - private static void GetChildPrivateFields(IList initialFields, Type targetType, BindingFlags bindingAttr) + private static void GetChildPrivateFields(IList initialFields, Type type, BindingFlags bindingAttr) { + Type? targetType = type; + // fix weirdness with private FieldInfos only being returned for the current Type // find base type fields and add them to result if ((bindingAttr & BindingFlags.NonPublic) != 0) @@ -948,7 +963,7 @@ public static IEnumerable GetProperties(Type targetType, BindingFl PropertyInfo member = propertyInfos[i]; if (member.DeclaringType != targetType) { - PropertyInfo declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType, member); + PropertyInfo declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType!, member)!; propertyInfos[i] = declaredMember; } } @@ -963,13 +978,14 @@ public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlag : bindingAttr; } - private static void GetChildPrivateProperties(IList initialProperties, Type targetType, BindingFlags bindingAttr) + private static void GetChildPrivateProperties(IList initialProperties, Type type, BindingFlags bindingAttr) { // fix weirdness with private PropertyInfos only being returned for the current Type // find base type properties and add them to result // also find base properties that have been hidden by subtype properties with the same name + Type? targetType = type; while ((targetType = targetType.BaseType()) != null) { foreach (PropertyInfo propertyInfo in targetType.GetProperties(bindingAttr)) @@ -1013,11 +1029,11 @@ private static void GetChildPrivateProperties(IList initialPropert } else { - Type subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType; + Type subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType!; int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name && p.IsVirtual() - && (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType).IsAssignableFrom(subTypePropertyDeclaringType)); + && (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType!).IsAssignableFrom(subTypePropertyDeclaringType)); // don't add a virtual property that has an override if (index == -1) diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/StringBuffer.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/StringBuffer.cs index d32a84e3..78e40d97 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/StringBuffer.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/StringBuffer.cs @@ -107,7 +107,7 @@ public override string ToString() public string ToString(int start, int length) { - // TODO: validation + MiscellaneousUtils.Assert(_buffer != null); return new string(_buffer, start, length); } diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/StringUtils.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/StringUtils.cs index b1db50d8..43a76094 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/StringUtils.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/StringUtils.cs @@ -128,7 +128,7 @@ public static void ToCharAsUnicode(char c, char[] buffer) buffer[5] = MathUtils.IntToHex(c & '\x000f'); } - public static TSource ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, string testValue) + public static TSource? ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, string testValue) { if (source == null) { @@ -195,7 +195,7 @@ public static string ToCamelCase(string s) private static char ToLower(char c) { -#if HAVE_CHAR_TO_STRING_WITH_CULTURE +#if HAVE_CHAR_TO_LOWER_WITH_CULTURE c = char.ToLower(c, CultureInfo.InvariantCulture); #else c = char.ToLowerInvariant(c); @@ -303,6 +303,24 @@ public static bool IsLowSurrogate(char c) #endif } + public static int IndexOf(string s, char c) + { +#if HAVE_INDEXOF_STRING_COMPARISON + return s.IndexOf(c, StringComparison.Ordinal); +#else + return s.IndexOf(c); +#endif + } + + public static string Replace(string s, string oldValue, string newValue) + { +#if HAVE_REPLACE_STRING_COMPARISON + return s.Replace(oldValue, newValue, StringComparison.Ordinal); +#else + return s.Replace(oldValue, newValue); +#endif + } + public static bool StartsWith(this string source, char value) { return (source.Length > 0 && source[0] == value); diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/StructMultiKey.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/StructMultiKey.cs index e9c6dbe1..2c70222e 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/StructMultiKey.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/StructMultiKey.cs @@ -43,7 +43,7 @@ public override int GetHashCode() return (Value1?.GetHashCode() ?? 0) ^ (Value2?.GetHashCode() ?? 0); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (!(obj is StructMultiKey key)) { diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/ThreadSafeStore.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/ThreadSafeStore.cs index ff56b329..f754d8c8 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/ThreadSafeStore.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/ThreadSafeStore.cs @@ -36,7 +36,7 @@ namespace Exceptionless.Json.Utilities { - internal class ThreadSafeStore + internal class ThreadSafeStore where TKey : notnull { #if HAVE_CONCURRENT_DICTIONARY private readonly ConcurrentDictionary _concurrentStore; diff --git a/src/Exceptionless/Newtonsoft.Json/Utilities/TypeExtensions.cs b/src/Exceptionless/Newtonsoft.Json/Utilities/TypeExtensions.cs index 27b7e1e2..b0c60d39 100644 --- a/src/Exceptionless/Newtonsoft.Json/Utilities/TypeExtensions.cs +++ b/src/Exceptionless/Newtonsoft.Json/Utilities/TypeExtensions.cs @@ -171,7 +171,7 @@ public static bool IsGenericTypeDefinition(this Type type) #endif } - public static Type BaseType(this Type type) + public static Type? BaseType(this Type type) { #if HAVE_FULL_REFLECTION return type.BaseType; @@ -580,7 +580,7 @@ public static bool IsPrimitive(this Type type) public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, [NotNullWhen(true)]out Type? match) { - Type current = type; + Type? current = type; while (current != null) { @@ -616,7 +616,7 @@ public static bool AssignableToTypeName(this Type type, string fullTypeName, boo public static bool ImplementInterface(this Type type, Type interfaceType) { - for (Type currentType = type; currentType != null; currentType = currentType.BaseType()) + for (Type? currentType = type; currentType != null; currentType = currentType.BaseType()) { IEnumerable interfaces = currentType.GetInterfaces(); foreach (Type i in interfaces) diff --git a/src/Exceptionless/update-json.ps1 b/src/Exceptionless/update-json.ps1 index dded8e05..f0f5746c 100644 --- a/src/Exceptionless/update-json.ps1 +++ b/src/Exceptionless/update-json.ps1 @@ -1,35 +1,36 @@ # Pull sources if (Test-Path json.zip) { - del json.zip + Remove-Item json.zip } [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -Invoke-WebRequest https://github.com/JamesNK/Newtonsoft.Json/archive/12.0.3.zip -OutFile json.zip +Invoke-WebRequest https://github.com/JamesNK/Newtonsoft.Json/archive/13.0.3.zip -OutFile json.zip if (Test-Path json-temp) { - rmdir './json-temp' -Recurse -Force + Remove-Item './json-temp' -Recurse -Force } [System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null [System.IO.Compression.ZipFile]::ExtractToDirectory($pwd.Path + "/json.zip", $pwd.Path + "/json-temp") if (Test-Path Newtonsoft.Json) { - rmdir './Newtonsoft.Json' -Recurse -Force + Remove-Item './Newtonsoft.Json' -Recurse -Force } -cd 'json-temp/Newtonsoft.Json*' +Set-Location 'json-temp/Newtonsoft.Json*' Copy-Item 'Src/Newtonsoft.Json' -Destination '../../' -Recurse -cd '../../' +Set-Location '../../' -rmdir './json-temp' -Recurse -Force -del json.zip +Remove-Item './json-temp' -Recurse -Force -ErrorAction SilentlyContinue *> $null +Remove-Item json.zip +Remove-Item './json-temp' -Recurse -Force -ErrorAction SilentlyContinue *> $null Get-ChildItem './Newtonsoft.Json' *.cs -recurse | Foreach-Object { - $c = ($_ | Get-Content) + $c = ($_ | Get-Content) $c = $c -replace 'Newtonsoft.Json','Exceptionless.Json' $c = $c -replace 'JsonIgnoreAttribute','ExceptionlessIgnoreAttribute' if($_.name -ne 'JsonIgnoreAttribute.cs'){ - $c = $c -replace 'public( (?:static|sealed|abstract|partial))? (class|struct|interface|enum)','internal$1 $2' + $c = $c -replace 'public((?: (?:readonly|static|sealed|abstract|partial))+)? (class|struct|interface|enum)','internal$1 $2' $c = $c -replace 'public delegate void','internal delegate void' $c = $c -replace '\[CLSCompliant\(false\)\]','' } @@ -38,6 +39,9 @@ Get-ChildItem './Newtonsoft.Json' *.cs -recurse | Rename-Item -Path "./Newtonsoft.Json/JsonIgnoreAttribute.cs" "ExceptionlessIgnoreAttribute.cs" -del './Newtonsoft.Json/*.csproj' -Force -del './Newtonsoft.Json/Newtonsoft.Json.ruleset' -Force -del './Newtonsoft.Json/Properties' -Force -Recurse +Remove-Item './Newtonsoft.Json/*.csproj' -Force +Remove-Item './Newtonsoft.Json/CompatibilitySuppressions.xml' -Force -Recurse +Remove-Item './Newtonsoft.Json/Newtonsoft.Json.ruleset' -Force +Remove-Item './Newtonsoft.Json/Properties' -Force -Recurse +Remove-Item './Newtonsoft.Json/packageIcon.png' -Force -Recurse +Remove-Item './Newtonsoft.Json/README.md' -Force -Recurse