| File: Symbols\Tuples\TupleErrorFieldSymbol.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.Collections.Immutable; using System.Diagnostics; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// <summary> /// Represents a field of a tuple type (such as (int, byte).Item1) /// that doesn't have a corresponding backing field within the tuple underlying type. /// Created in response to an error condition. /// </summary> internal sealed class TupleErrorFieldSymbol : SynthesizedFieldSymbolBase { private readonly TypeWithAnnotations _type; /// <summary> /// If this field represents a tuple element with index X /// 2X if this field represents Default-named element /// 2X + 1 if this field represents Friendly-named element /// Otherwise, (-1 - [index in members array]); /// </summary> private readonly int _tupleElementIndex; private readonly ImmutableArray<Location> _locations; private readonly DiagnosticInfo _useSiteDiagnosticInfo; private readonly TupleErrorFieldSymbol _correspondingDefaultField; // default tuple elements like Item1 or Item20 could be provided by the user or // otherwise implicitly declared by compiler private readonly bool _isImplicitlyDeclared; public TupleErrorFieldSymbol( NamedTypeSymbol container, string name, int tupleElementIndex, Location location, TypeWithAnnotations type, DiagnosticInfo useSiteDiagnosticInfo, bool isImplicitlyDeclared, TupleErrorFieldSymbol correspondingDefaultFieldOpt) : base(container, name, DeclarationModifiers.Public, isReadOnly: false, isStatic: false) { Debug.Assert(name != null); _type = type; _locations = location == null ? ImmutableArray<Location>.Empty : ImmutableArray.Create(location); _useSiteDiagnosticInfo = useSiteDiagnosticInfo; _tupleElementIndex = (object)correspondingDefaultFieldOpt == null ? tupleElementIndex << 1 : (tupleElementIndex << 1) + 1; _isImplicitlyDeclared = isImplicitlyDeclared; Debug.Assert((correspondingDefaultFieldOpt == null) == this.IsDefaultTupleElement); Debug.Assert(correspondingDefaultFieldOpt == null || correspondingDefaultFieldOpt.IsDefaultTupleElement); _correspondingDefaultField = correspondingDefaultFieldOpt ?? this; } /// <summary> /// If this is a field representing a tuple element, /// returns the index of the element (zero-based). /// Otherwise returns -1 /// </summary> public override int TupleElementIndex { get { if (_tupleElementIndex < 0) { return -1; } return _tupleElementIndex >> 1; } } public override bool IsDefaultTupleElement { get { // not negative and even return (_tupleElementIndex & ((1 << 31) | 1)) == 0; } } public override bool IsExplicitlyNamedTupleElement { get { return _tupleElementIndex >= 0 && !_isImplicitlyDeclared; } } public override FieldSymbol TupleUnderlyingField { get { // Failed to find one return null; } } public override FieldSymbol OriginalDefinition { get { return this; } } public override ImmutableArray<Location> Locations { get { return _locations; } } public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences { get { return _isImplicitlyDeclared ? ImmutableArray<SyntaxReference>.Empty : GetDeclaringSyntaxReferenceHelper<CSharpSyntaxNode>(_locations); } } public override bool IsImplicitlyDeclared { get { return _isImplicitlyDeclared; } } public override FieldSymbol CorrespondingTupleField { get { return _correspondingDefaultField; } } internal override bool SuppressDynamicAttribute { get { return true; } } internal sealed override CallerUnsafeMode GetCallerUnsafeMode(ConsList<FieldSymbol> fieldsBeingBound) => CallerUnsafeMode.None; public override RefKind RefKind => RefKind.None; public override ImmutableArray<CustomModifier> RefCustomModifiers => ImmutableArray<CustomModifier>.Empty; internal override TypeWithAnnotations GetFieldType(ConsList<FieldSymbol> fieldsBeingBound) { return _type; } internal override UseSiteInfo<AssemblySymbol> GetUseSiteInfo() { return new UseSiteInfo<AssemblySymbol>(_useSiteDiagnosticInfo); } public sealed override int GetHashCode() { return Hash.Combine(ContainingType.GetHashCode(), _tupleElementIndex.GetHashCode()); } public override bool Equals(Symbol obj, TypeCompareKind compareKind) { return Equals(obj as TupleErrorFieldSymbol, compareKind); } public bool Equals(TupleErrorFieldSymbol other, TypeCompareKind compareKind) { if ((object)other == this) { return true; } return (object)other != null && _tupleElementIndex == other._tupleElementIndex && TypeSymbol.Equals(ContainingType, other.ContainingType, compareKind); } internal override FieldSymbol AsMember(NamedTypeSymbol newOwner) { Debug.Assert(newOwner.IsTupleType && newOwner.TupleElementTypesWithAnnotations.Length > TupleElementIndex); if (ReferenceEquals(newOwner, ContainingType)) { return this; } TupleErrorFieldSymbol newCorrespondingField = null; if (!ReferenceEquals(_correspondingDefaultField, this)) { newCorrespondingField = (TupleErrorFieldSymbol)_correspondingDefaultField.AsMember(newOwner); } return new TupleErrorFieldSymbol( newOwner, Name, TupleElementIndex, _locations.IsEmpty ? null : GetFirstLocation(), newOwner.TupleElementTypesWithAnnotations[TupleElementIndex], _useSiteDiagnosticInfo, _isImplicitlyDeclared, newCorrespondingField); } } }