diff --git a/src/Microsoft.AspNetCore.Razor.Language/DefaultItemCollection.cs b/src/Microsoft.AspNetCore.Razor.Language/DefaultItemCollection.cs index b868649c73..62457ea37e 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/DefaultItemCollection.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/DefaultItemCollection.cs @@ -39,5 +39,68 @@ namespace Microsoft.AspNetCore.Razor.Language _items[key] = value; } } + + public override int Count => _items.Count; + + public override bool IsReadOnly => false; + + public override void Add(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + ((ICollection>)_items).Add(item); + } + + public override void Clear() + { + _items.Clear(); + } + + public override bool Contains(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + return ((ICollection>)_items).Contains(item); + } + + public override void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + if (arrayIndex < 0 || arrayIndex > array.Length) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + else if (array.Length - arrayIndex < Count) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + + ((ICollection>)_items).CopyTo(array, arrayIndex); + } + + public override IEnumerator> GetEnumerator() + { + return _items.GetEnumerator(); + } + + public override bool Remove(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + return ((ICollection>)_items).Remove(item); + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/ItemCollection.cs b/src/Microsoft.AspNetCore.Razor.Language/ItemCollection.cs index f156528196..914fce3ffd 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/ItemCollection.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/ItemCollection.cs @@ -1,10 +1,34 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections; +using System.Collections.Generic; + namespace Microsoft.AspNetCore.Razor.Language { - public abstract class ItemCollection + public abstract class ItemCollection : ICollection> { public abstract object this[object key] { get; set; } + + public abstract int Count { get; } + + public abstract bool IsReadOnly { get; } + + public abstract void Add(KeyValuePair item); + + public abstract void Clear(); + + public abstract bool Contains(KeyValuePair item); + + public abstract void CopyTo(KeyValuePair[] array, int arrayIndex); + + public abstract IEnumerator> GetEnumerator(); + + public abstract bool Remove(KeyValuePair item); + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs index 89459d415c..fbae6b1aad 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/Properties/Resources.Designer.cs @@ -444,6 +444,20 @@ namespace Microsoft.AspNetCore.Razor.Language internal static string FormatDirectiveMustAppearAtStartOfLine(object p0) => string.Format(CultureInfo.CurrentCulture, GetString("DirectiveMustAppearAtStartOfLine"), p0); + /// + /// The key must not be null. + /// + internal static string KeyMustNotBeNull + { + get => GetString("KeyMustNotBeNull"); + } + + /// + /// The key must not be null. + /// + internal static string FormatKeyMustNotBeNull() + => GetString("KeyMustNotBeNull"); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Razor.Language/ReadonlyItemCollection.cs b/src/Microsoft.AspNetCore.Razor.Language/ReadonlyItemCollection.cs index ca7e841955..d26bfdbf2d 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/ReadonlyItemCollection.cs +++ b/src/Microsoft.AspNetCore.Razor.Language/ReadonlyItemCollection.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; +using System.Linq; namespace Microsoft.AspNetCore.Razor.Language { @@ -14,5 +16,68 @@ namespace Microsoft.AspNetCore.Razor.Language get => null; set => throw new NotSupportedException(); } + + public override int Count => 0; + + public override bool IsReadOnly => true; + + public override void Add(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + throw new NotSupportedException(); + } + + public override void Clear() + { + throw new NotSupportedException(); + } + + public override bool Contains(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + return false; + } + + public override void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + if (arrayIndex < 0 || arrayIndex > array.Length) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + else if (array.Length - arrayIndex < Count) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + + // Do nothing. + } + + public override IEnumerator> GetEnumerator() + { + return Enumerable.Empty>().GetEnumerator(); + } + + public override bool Remove(KeyValuePair item) + { + if (item.Key == null) + { + throw new ArgumentException(Resources.KeyMustNotBeNull, nameof(item)); + } + + throw new NotSupportedException(); + } } } diff --git a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx index b05f1016c4..3de7f278a6 100644 --- a/src/Microsoft.AspNetCore.Razor.Language/Resources.resx +++ b/src/Microsoft.AspNetCore.Razor.Language/Resources.resx @@ -210,4 +210,7 @@ The '{0}` directive must appear at the start of the line. + + The key must not be null. + \ No newline at end of file