| File: Symbols\Source\SourceEnumConstantSymbol.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. #nullable disable using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Threading; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// <summary> /// Represents a constant field of an enum. /// </summary> internal abstract class SourceEnumConstantSymbol : SourceFieldSymbolWithSyntaxReference { public static SourceEnumConstantSymbol CreateExplicitValuedConstant( SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, BindingDiagnosticBag diagnostics) { return new ExplicitValuedEnumConstantSymbol(containingEnum, syntax, diagnostics); } public static SourceEnumConstantSymbol CreateImplicitValuedConstant( SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, SourceEnumConstantSymbol otherConstant, int otherConstantOffset, BindingDiagnosticBag diagnostics) { if ((object)otherConstant == null) { Debug.Assert(otherConstantOffset == 0); return new ZeroValuedEnumConstantSymbol(containingEnum, syntax, diagnostics); } else { Debug.Assert(otherConstantOffset > 0); return new ImplicitValuedEnumConstantSymbol(containingEnum, syntax, otherConstant, (uint)otherConstantOffset, diagnostics); } } protected SourceEnumConstantSymbol(SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, BindingDiagnosticBag diagnostics) : base(containingEnum, syntax.Identifier.ValueText, syntax.GetReference(), syntax.Identifier.Span) { if (this.Name == WellKnownMemberNames.EnumBackingFieldName) { diagnostics.Add(ErrorCode.ERR_ReservedEnumerator, this.ErrorLocation, WellKnownMemberNames.EnumBackingFieldName); } } public sealed override RefKind RefKind => RefKind.None; internal sealed override CallerUnsafeMode GetCallerUnsafeMode(ConsList<FieldSymbol> fieldsBeingBound) => CallerUnsafeMode.None; internal override TypeWithAnnotations GetFieldType(ConsList<FieldSymbol> fieldsBeingBound) { return TypeWithAnnotations.Create(this.ContainingType); } public override Symbol AssociatedSymbol { get { return null; } } protected sealed override DeclarationModifiers Modifiers { get { return DeclarationModifiers.Const | DeclarationModifiers.Static | DeclarationModifiers.Public; } } public new EnumMemberDeclarationSyntax SyntaxNode { get { return (EnumMemberDeclarationSyntax)base.SyntaxNode; } } protected override OneOrMany<SyntaxList<AttributeListSyntax>> GetAttributeDeclarations() { if (this.containingType.AnyMemberHasAttributes) { return OneOrMany.Create(this.SyntaxNode.AttributeLists); } return OneOrMany<SyntaxList<AttributeListSyntax>>.Empty; } #nullable enable internal sealed override void ForceComplete(SourceLocation? locationOpt, Predicate<Symbol>? filter, CancellationToken cancellationToken) { if (filter?.Invoke(this) == false) { return; } while (true) { cancellationToken.ThrowIfCancellationRequested(); var incompletePart = state.NextIncompletePart; switch (incompletePart) { case CompletionPart.Attributes: GetAttributes(); break; case CompletionPart.Type: state.NotePartComplete(CompletionPart.Type); break; case CompletionPart.FixedSize: Debug.Assert(!this.IsFixedSizeBuffer); state.NotePartComplete(CompletionPart.FixedSize); break; case CompletionPart.ConstantValue: GetConstantValue(ConstantFieldsInProgress.Empty, earlyDecodingWellKnownAttributes: false); break; case CompletionPart.None: return; default: // any other values are completion parts intended for other kinds of symbols state.NotePartComplete(CompletionPart.All & ~CompletionPart.FieldSymbolAll); break; } state.SpinWaitComplete(incompletePart, cancellationToken); } } #nullable disable private sealed class ZeroValuedEnumConstantSymbol : SourceEnumConstantSymbol { public ZeroValuedEnumConstantSymbol( SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, BindingDiagnosticBag diagnostics) : base(containingEnum, syntax, diagnostics) { } protected override ConstantValue MakeConstantValue(HashSet<SourceFieldSymbolWithSyntaxReference> dependencies, bool earlyDecodingWellKnownAttributes, BindingDiagnosticBag diagnostics) { var constantType = this.ContainingType.EnumUnderlyingType.SpecialType; return Microsoft.CodeAnalysis.ConstantValue.Default(constantType); } } private sealed class ExplicitValuedEnumConstantSymbol : SourceEnumConstantSymbol { public ExplicitValuedEnumConstantSymbol( SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, BindingDiagnosticBag diagnostics) : base(containingEnum, syntax, diagnostics) { Debug.Assert(syntax.EqualsValue != null); } protected override ConstantValue MakeConstantValue(HashSet<SourceFieldSymbolWithSyntaxReference> dependencies, bool earlyDecodingWellKnownAttributes, BindingDiagnosticBag diagnostics) { var syntax = this.SyntaxNode; Debug.Assert(syntax.EqualsValue != null); return ConstantValueUtils.EvaluateFieldConstant(this, syntax.EqualsValue, dependencies, earlyDecodingWellKnownAttributes, diagnostics); } } private sealed class ImplicitValuedEnumConstantSymbol : SourceEnumConstantSymbol { private readonly SourceEnumConstantSymbol _otherConstant; private readonly uint _otherConstantOffset; public ImplicitValuedEnumConstantSymbol( SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, SourceEnumConstantSymbol otherConstant, uint otherConstantOffset, BindingDiagnosticBag diagnostics) : base(containingEnum, syntax, diagnostics) { Debug.Assert((object)otherConstant != null); Debug.Assert(otherConstantOffset > 0); _otherConstant = otherConstant; _otherConstantOffset = otherConstantOffset; } protected override ConstantValue MakeConstantValue(HashSet<SourceFieldSymbolWithSyntaxReference> dependencies, bool earlyDecodingWellKnownAttributes, BindingDiagnosticBag diagnostics) { var otherValue = _otherConstant.GetConstantValue(new ConstantFieldsInProgress(this, dependencies), earlyDecodingWellKnownAttributes); // Value may be Unset if there are dependencies // that must be evaluated first. if (otherValue == Microsoft.CodeAnalysis.ConstantValue.Unset) { return Microsoft.CodeAnalysis.ConstantValue.Unset; } if (otherValue.IsBad) { return Microsoft.CodeAnalysis.ConstantValue.Bad; } ConstantValue value; var overflowKind = EnumConstantHelper.OffsetValue(otherValue, _otherConstantOffset, out value); if (overflowKind == EnumOverflowKind.OverflowReport) { // Report an error if the value is immediately // outside the range, but not otherwise. diagnostics.Add(ErrorCode.ERR_EnumeratorOverflow, this.GetFirstLocation(), this); } return value; } } } }