File: Symbols\Synthesized\ReadOnlyListType\SynthesizedReadOnlyListEnumeratorTypeSymbol.cs
Web Access
Project: src\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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal sealed class SynthesizedReadOnlyListEnumeratorTypeSymbol : NamedTypeSymbol
    {
        private readonly SynthesizedReadOnlyListTypeSymbol _containingType;
        private readonly ImmutableArray<NamedTypeSymbol> _interfaces;
        private readonly ImmutableArray<Symbol> _members;
        private readonly FieldSymbol _itemField;
        private readonly FieldSymbol _moveNextCalledField;
 
        public SynthesizedReadOnlyListEnumeratorTypeSymbol(SynthesizedReadOnlyListTypeSymbol containingType, SynthesizedReadOnlyListTypeParameterSymbol typeParameter)
        {
            _containingType = containingType;
 
            var compilation = containingType.DeclaringCompilation;
            var typeArgs = containingType.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;
 
            _itemField = new SynthesizedFieldSymbol(this, typeParameter, "_item", isReadOnly: true);
            _moveNextCalledField = new SynthesizedFieldSymbol(this, compilation.GetSpecialType(SpecialType.System_Boolean), "_moveNextCalled", isReadOnly: false);
 
            var iDisposable = compilation.GetSpecialType(SpecialType.System_IDisposable);
            var iEnumerator = compilation.GetSpecialType(SpecialType.System_Collections_IEnumerator);
            var iEnumeratorT = compilation.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T).Construct(typeArgs);
 
            _interfaces = ImmutableArray.Create(
                iDisposable,
                iEnumerator,
                iEnumeratorT);
 
            var membersBuilder = ArrayBuilder<Symbol>.GetInstance();
            membersBuilder.Add(_itemField);
            membersBuilder.Add(_moveNextCalledField);
            membersBuilder.Add(
                new SynthesizedReadOnlyListEnumeratorConstructor(this, typeParameter));
            addProperty(membersBuilder,
                new SynthesizedReadOnlyListProperty(
                    this,
                    (PropertySymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__Current),
                    static (f, method, interfaceMethod) =>
                    {
                        var containingType = (SynthesizedReadOnlyListEnumeratorTypeSymbol)method.ContainingType;
                        var itemField = containingType._itemField;
                        var itemFieldReference = f.Field(f.This(), itemField);
                        // return (object)_item;
                        return f.Return(f.Convert(method.ReturnType, itemFieldReference));
                    }));
            addProperty(membersBuilder,
                new SynthesizedReadOnlyListProperty(
                    this,
                    ((PropertySymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_Generic_IEnumerator_T__Current)).AsMember(iEnumeratorT),
                    static (f, method, interfaceMethod) =>
                    {
                        var containingType = (SynthesizedReadOnlyListEnumeratorTypeSymbol)method.ContainingType;
                        var itemField = containingType._itemField;
                        var itemFieldReference = f.Field(f.This(), itemField);
                        // return _item;
                        return f.Return(itemFieldReference);
                    }));
            membersBuilder.Add(
                new SynthesizedReadOnlyListMethod(
                    this,
                    ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__MoveNext)),
                    static (f, method, interfaceMethod) =>
                    {
                        var containingType = (SynthesizedReadOnlyListEnumeratorTypeSymbol)method.ContainingType;
                        var moveNextCalledField = containingType._moveNextCalledField;
                        var moveNextCalledFieldReference = f.Field(f.This(), moveNextCalledField);
                        // return _moveNextCalled ? false : (_moveNextCalled = true);
                        return f.Return(
                            f.Conditional(
                                moveNextCalledFieldReference,
                                f.Literal(false),
                                f.AssignmentExpression(
                                    moveNextCalledFieldReference,
                                    f.Literal(true)),
                                method.ReturnType));
                    }));
            membersBuilder.Add(
                new SynthesizedReadOnlyListMethod(
                    this,
                    ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_Collections_IEnumerator__Reset)),
                    static (f, method, interfaceMethod) =>
                    {
                        var containingType = (SynthesizedReadOnlyListEnumeratorTypeSymbol)method.ContainingType;
                        var moveNextCalledField = containingType._moveNextCalledField;
                        var moveNextCalledFieldReference = f.Field(f.This(), moveNextCalledField);
                        // _moveNextCalled = false;
                        // return;
                        return f.Block(f.Assignment(moveNextCalledFieldReference, f.Literal(false)), f.Return());
                    }));
            membersBuilder.Add(
                new SynthesizedReadOnlyListMethod(
                    this,
                    ((MethodSymbol)compilation.GetSpecialTypeMember(SpecialMember.System_IDisposable__Dispose)),
                    static (f, method, interfaceMethod) => f.Return()));
            _members = membersBuilder.ToImmutableAndFree();
            return;
 
            static void addProperty(ArrayBuilder<Symbol> builder, PropertySymbol property)
            {
                Debug.Assert(property is { GetMethod: not null, SetMethod: null });
                builder.Add(property);
                builder.Add(property.GetMethod);
            }
        }
 
        public override int Arity => 0;
 
        public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;
 
        public override NamedTypeSymbol ConstructedFrom => this;
 
        public override bool MightContainExtensionMethods => false;
 
        public override string Name => "Enumerator";
 
        public override IEnumerable<string> MemberNames => GetMembers().Select(m => m.Name);
 
        public override Accessibility DeclaredAccessibility => Accessibility.Private;
 
        public override bool IsSerializable => false;
 
        public override bool AreLocalsZeroed => true;
 
        public override TypeKind TypeKind => TypeKind.Class;
 
        public override bool IsRefLikeType => false;
 
        public override bool IsReadOnly => false;
 
        public override Symbol ContainingSymbol => _containingType;
 
        internal override ModuleSymbol ContainingModule => _containingType.ContainingModule;
 
        public override AssemblySymbol ContainingAssembly => _containingType.ContainingAssembly;
 
        public override ImmutableArray<Location> Locations => ImmutableArray<Location>.Empty;
 
        public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => ImmutableArray<SyntaxReference>.Empty;
 
        public override bool IsStatic => false;
 
        public override bool IsAbstract => false;
 
        public override bool IsSealed => true;
 
        internal override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotationsNoUseSiteDiagnostics => GetTypeParametersAsTypeArguments();
 
        internal override bool IsFileLocal => false;
 
        internal override FileIdentifier? AssociatedFileIdentifier => null;
 
        internal override bool MangleName => false;
 
        internal override bool HasDeclaredRequiredMembers => false;
 
        internal override bool HasCodeAnalysisEmbeddedAttribute => false;
 
        internal override bool IsInterpolatedStringHandlerType => false;
 
        internal override bool HasSpecialName => false;
 
        internal override bool IsComImport => false;
 
        internal override bool IsWindowsRuntimeImport => false;
 
        internal override bool ShouldAddWinRTMembers => false;
 
        internal override TypeLayout Layout => default;
 
        internal override CharSet MarshallingCharSet => DefaultMarshallingCharSet;
 
        internal override bool HasDeclarativeSecurity => false;
 
        internal override bool IsInterface => false;
 
        internal override NamedTypeSymbol? NativeIntegerUnderlyingType => null;
 
        internal override NamedTypeSymbol BaseTypeNoUseSiteDiagnostics => ContainingAssembly.GetSpecialType(SpecialType.System_Object);
 
        internal override bool IsRecord => false;
 
        internal override bool IsRecordStruct => false;
 
        internal override ObsoleteAttributeData? ObsoleteAttributeData => null;
 
        public override ImmutableArray<Symbol> GetMembers() => _members;
 
        public override ImmutableArray<Symbol> GetMembers(string name) => GetMembers().WhereAsArray(static (m, name) => m.Name == name, name);
 
        public override ImmutableArray<NamedTypeSymbol> GetTypeMembers() => ImmutableArray<NamedTypeSymbol>.Empty;
 
        public override ImmutableArray<NamedTypeSymbol> GetTypeMembers(ReadOnlyMemory<char> name, int arity) => ImmutableArray<NamedTypeSymbol>.Empty;
 
        public override ImmutableArray<NamedTypeSymbol> GetTypeMembers(ReadOnlyMemory<char> name) => ImmutableArray<NamedTypeSymbol>.Empty;
 
        protected override NamedTypeSymbol WithTupleDataCore(TupleExtraData newData) => throw ExceptionUtilities.Unreachable();
 
        internal override NamedTypeSymbol AsNativeInteger() => throw ExceptionUtilities.Unreachable();
 
        internal override ImmutableArray<string> GetAppliedConditionalSymbols() => ImmutableArray<string>.Empty;
 
        internal override AttributeUsageInfo GetAttributeUsageInfo() => default;
 
        internal override NamedTypeSymbol GetDeclaredBaseType(ConsList<TypeSymbol> basesBeingResolved) => BaseTypeNoUseSiteDiagnostics;
 
        internal override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList<TypeSymbol> basesBeingResolved) => _interfaces;
 
        internal override ImmutableArray<Symbol> GetEarlyAttributeDecodingMembers() => throw ExceptionUtilities.Unreachable();
 
        internal override ImmutableArray<Symbol> GetEarlyAttributeDecodingMembers(string name) => throw ExceptionUtilities.Unreachable();
 
        internal override IEnumerable<FieldSymbol> GetFieldsToEmit() => _members.OfType<FieldSymbol>();
 
        internal override ImmutableArray<NamedTypeSymbol> GetInterfacesToEmit() => _interfaces;
 
        internal override IEnumerable<Cci.SecurityAttribute> GetSecurityInformation() => SpecializedCollections.EmptyEnumerable<Cci.SecurityAttribute>();
 
        internal override bool GetGuidString(out string? guidString)
        {
            guidString = null;
            return false;
        }
 
        internal override bool HasCollectionBuilderAttribute(out TypeSymbol? builderType, out string? methodName)
        {
            builderType = null;
            methodName = null;
            return false;
        }
 
        internal override bool HasInlineArrayAttribute(out int length)
        {
            length = 0;
            return false;
        }
 
        internal override bool HasAsyncMethodBuilderAttribute(out TypeSymbol? builderArgument)
        {
            builderArgument = null;
            return false;
        }
 
        internal override bool HasPossibleWellKnownCloneMethod() => false;
 
        internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<TypeSymbol>? basesBeingResolved = null) => _interfaces;
 
        internal override IEnumerable<(MethodSymbol Body, MethodSymbol Implemented)> SynthesizedInterfaceMethodImpls() => SpecializedCollections.EmptyEnumerable<(MethodSymbol Body, MethodSymbol Implemented)>();
    }
}