diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/ContentValidator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/ContentValidator.cs index 306d605dda442..60dc7a394078b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/ContentValidator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/ContentValidator.cs @@ -1439,7 +1439,7 @@ private void CheckUniqueParticleAttribution(BitSet curpos) int symbolsCount = _symbols!.Count; // transition table (Dtran in the book) - ArrayList transitionTable = new ArrayList(); + List transitionTable = new(); // state lookup table (Dstate in the book) Dictionary stateTable = new(); @@ -1461,7 +1461,7 @@ private void CheckUniqueParticleAttribution(BitSet curpos) { BitSet statePosSet = unmarked.Dequeue(); // all positions that constitute DFA state Debug.Assert(state == stateTable[statePosSet]); // just make sure that statePosSet is for correct state - int[] transition = (int[])transitionTable[state]!; + int[] transition = transitionTable[state]!; if (statePosSet[endMarkerPos]) { transition[symbolsCount] = 1; // accepting @@ -1506,7 +1506,7 @@ private void CheckUniqueParticleAttribution(BitSet curpos) state++; } // now convert transition table to array - return (int[][])transitionTable.ToArray(typeof(int[])); + return transitionTable.ToArray(); } #if DEBUG diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs index c026afb4c4ce4..f4f3c6489b939 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/DataTypeImplementation.cs @@ -5,6 +5,7 @@ using System.IO; using System.Collections; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; using System.Text.RegularExpressions; @@ -521,8 +522,6 @@ internal override bool HasValueFacets protected DatatypeImplementation? Base { get { return _baseType; } } - internal abstract Type ListValueType { get; } - internal abstract RestrictionFlags ValidRestrictionFlags { get; } internal override XmlSchemaWhiteSpace BuiltInWhitespaceFacet { get { return XmlSchemaWhiteSpace.Preserve; } } @@ -1126,8 +1125,8 @@ internal override RestrictionFlags ValidRestrictionFlags values.Add(typedValue); } - array = values.ToArray(_itemType.ValueType); - Debug.Assert(array.GetType() == ListValueType); + Debug.Assert(_itemType.ListValueType.GetElementType() == _itemType.ValueType); + array = ToArray(values, _itemType.ListValueType); } if (values.Count < _minListSize) { @@ -1143,6 +1142,12 @@ internal override RestrictionFlags ValidRestrictionFlags Error: return exception; + + // TODO: Replace with https://github.com/dotnet/runtime/issues/76478 once available + [UnconditionalSuppressMessage("AotAnalysis", "IL3050:AotUnfriendlyApi", + Justification = "Array type is always present as it is passed in as a parameter.")] + static Array ToArray(ArrayList values, Type arrayType) + => values.ToArray(arrayType.GetElementType()!); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs index e6a9aff012f7a..5cd0d5b9d35a7 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaDataType.cs @@ -21,6 +21,8 @@ public abstract class XmlSchemaDatatype public virtual XmlSchemaDatatypeVariety Variety { get { return XmlSchemaDatatypeVariety.Atomic; } } + internal abstract Type ListValueType { get; } + internal XmlSchemaDatatype() { } public virtual object ChangeType(object value, Type targetType) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlValueConverter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlValueConverter.cs index a52eb320166ca..66756e9913627 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlValueConverter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlValueConverter.cs @@ -6,6 +6,7 @@ using System.Xml.XPath; using System.Globalization; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Collections; using System.Collections.Generic; using System.Xml.Schema; @@ -225,6 +226,7 @@ internal abstract class XmlBaseConverter : XmlValueConverter private readonly XmlSchemaType? _schemaType; private readonly XmlTypeCode _typeCode; private readonly Type? _clrTypeDefault; + private readonly Type? _clrListTypeDefault; protected XmlBaseConverter(XmlSchemaType schemaType) { @@ -242,6 +244,7 @@ protected XmlBaseConverter(XmlSchemaType schemaType) _schemaType = schemaType; _typeCode = schemaType.TypeCode; _clrTypeDefault = schemaType.Datatype.ValueType; + _clrListTypeDefault = schemaType.Datatype.ListValueType; } protected XmlBaseConverter(XmlTypeCode typeCode) @@ -250,14 +253,17 @@ protected XmlBaseConverter(XmlTypeCode typeCode) { case XmlTypeCode.Item: _clrTypeDefault = XPathItemType; + _clrListTypeDefault = XPathItemArrayType; break; case XmlTypeCode.Node: _clrTypeDefault = XPathNavigatorType; + _clrListTypeDefault = XPathNavigatorArrayType; break; case XmlTypeCode.AnyAtomicType: _clrTypeDefault = XmlAtomicValueType; + _clrListTypeDefault = XmlAtomicValueArrayType; break; default: @@ -272,14 +278,18 @@ protected XmlBaseConverter(XmlBaseConverter converterAtomic) { _schemaType = converterAtomic._schemaType; _typeCode = converterAtomic._typeCode; - _clrTypeDefault = Array.CreateInstance(converterAtomic.DefaultClrType!, 0).GetType(); + _clrTypeDefault = converterAtomic.DefaultClrListType; + Debug.Assert(_clrTypeDefault!.IsArray); + // We don't support lists-of-lists, so we set _clrListTypeDefault to null. + _clrListTypeDefault = null; } - protected XmlBaseConverter(XmlBaseConverter converterAtomic, Type clrTypeDefault) + protected XmlBaseConverter(XmlBaseConverter converterAtomic, Type clrTypeDefault, Type clrListTypeDefault) { _schemaType = converterAtomic._schemaType; _typeCode = converterAtomic._typeCode; _clrTypeDefault = clrTypeDefault; + _clrListTypeDefault = clrListTypeDefault; } protected static readonly Type ICollectionType = typeof(ICollection); @@ -287,7 +297,10 @@ protected XmlBaseConverter(XmlBaseConverter converterAtomic, Type clrTypeDefault protected static readonly Type IListType = typeof(IList); protected static readonly Type ObjectArrayType = typeof(object[]); protected static readonly Type StringArrayType = typeof(string[]); + protected static readonly Type StringArrayArrayType = typeof(string[][]); protected static readonly Type XmlAtomicValueArrayType = typeof(XmlAtomicValue[]); + protected static readonly Type XPathItemArrayType = typeof(XPathItem[]); + protected static readonly Type XPathNavigatorArrayType = typeof(XPathNavigator[]); #region AUTOGENERATED_XMLBASECONVERTER protected static readonly Type DecimalType = typeof(decimal); @@ -432,6 +445,14 @@ protected Type? DefaultClrType get { return _clrTypeDefault; } } + /// + /// Return an array type with the element type of the default V1 Clr mapping of this converter's type. + /// + protected Type? DefaultClrListType + { + get { return _clrListTypeDefault; } + } + /// /// Type.IsSubtypeOf does not return true if types are equal, this method does. /// @@ -1988,7 +2009,7 @@ private XmlUntypedConverter() : base(DatatypeImplementation.UntypedAtomicType) } private XmlUntypedConverter(XmlUntypedConverter atomicConverter, bool allowListToList) - : base(atomicConverter, allowListToList ? StringArrayType : StringType) + : base(atomicConverter, allowListToList ? StringArrayType : StringType, allowListToList ? StringArrayArrayType : StringArrayType) { _allowListToList = allowListToList; } @@ -2875,7 +2896,7 @@ protected XmlListConverter(XmlBaseConverter atomicConverter) : base(atomicConver this.atomicConverter = atomicConverter; } - protected XmlListConverter(XmlBaseConverter atomicConverter, Type clrTypeDefault) : base(atomicConverter, clrTypeDefault) + protected XmlListConverter(XmlBaseConverter atomicConverter, Type clrTypeDefault, Type clrListTypeDefault) : base(atomicConverter, clrTypeDefault, clrListTypeDefault) { this.atomicConverter = atomicConverter; }