| File: BoundTree\BoundCollectionExpression.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp { internal partial class BoundCollectionExpression { private partial void Validate() { var collectionCreation = this.GetUnconvertedCollectionCreation(); var collectionBuilderElementsPlaceholder = this.CollectionBuilderElementsPlaceholder; if (collectionCreation is BoundCall boundCall) { Debug.Assert(this.CollectionTypeKind == CollectionExpressionTypeKind.CollectionBuilder); Debug.Assert(this.CollectionCreation is not null); Debug.Assert(this.CollectionBuilderMethod is not null); Debug.Assert(collectionBuilderElementsPlaceholder is not null); Debug.Assert(collectionBuilderElementsPlaceholder.Type is not null); Debug.Assert(boundCall.Arguments is [.., BoundCollectionBuilderElementsPlaceholder placeholder] && placeholder == collectionBuilderElementsPlaceholder); Debug.Assert(collectionBuilderElementsPlaceholder.Type.IsReadOnlySpan()); } else { Debug.Assert(this.CollectionTypeKind != CollectionExpressionTypeKind.CollectionBuilder); Debug.Assert(this.CollectionBuilderMethod is null); Debug.Assert(collectionBuilderElementsPlaceholder is null); } } /// <summary> /// Returns <see cref="CollectionCreation"/> with any outer <see cref="BoundConversion"/> nodes unwrapped. The /// final returned <see cref="BoundExpression"/> will either be: /// <list type="bullet"> /// <item><see langword="null"/> (when no <c>with(...)</c> element is present),</item> /// <item>a <see cref="BoundObjectCreationExpression"/> (when targeting a collection with a constructor),</item> /// <item>a <see cref="BoundCall"/> (when targeting a CollectionBuilder method),</item> /// <item>a <see cref="BoundNewT"/> (when targeting a type parameter with the <c>new()</c> constraint,</item> /// <item>or a <see cref="BoundBadExpression"/> in the case of errors where the <c>with(...)</c> element does /// not bind properly.</item> /// </list> /// </summary> public BoundExpression? GetUnconvertedCollectionCreation() { var collectionCreation = this.CollectionCreation; while (collectionCreation is BoundConversion conversion) collectionCreation = conversion.Operand; Debug.Assert(collectionCreation is null or BoundObjectCreationExpression or BoundCall or BoundNewT or BoundBadExpression); return collectionCreation; } } internal partial class BoundCollectionExpressionBase { private partial void Validate() { foreach (var element in Elements) Debug.Assert(element is not BoundUnconvertedWithElement); } /// <summary> /// Returns true if the collection expression contains any spreads. /// </summary> /// <param name="numberIncludingLastSpread">The number of elements up to and including the /// last spread element. If the length of the collection expression is known, this is the number /// of elements evaluated before any are added to the collection instance in lowering.</param> /// <param name="hasKnownLength"><see langword="true"/> if all the spread elements are countable.</param> internal bool HasSpreadElements(out int numberIncludingLastSpread, out bool hasKnownLength) { hasKnownLength = true; numberIncludingLastSpread = 0; for (int i = 0; i < Elements.Length; i++) { if (Elements[i] is BoundCollectionExpressionSpreadElement spreadElement) { numberIncludingLastSpread = i + 1; if (spreadElement.LengthOrCount is null) { hasKnownLength = false; } } } return numberIncludingLastSpread > 0; } public new bool IsParamsArrayOrCollection { get { return base.IsParamsArrayOrCollection; } init { base.IsParamsArrayOrCollection = value; } } } }