File: Microsoft\CSharp\RuntimeBinder\Semantics\Symbols\AggregateSymbol.cs
Web Access
Project: src\src\libraries\Microsoft.CSharp\src\Microsoft.CSharp.csproj (Microsoft.CSharp)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.CSharp.RuntimeBinder.Syntax;
 
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
    // Name used for AGGDECLs in the symbol table.
 
    // AggregateSymbol - a symbol representing an aggregate type. These are classes,
    // interfaces, and structs. Parent is a namespace or class. Children are methods,
    // properties, and member variables, and types (including its own AGGTYPESYMs).
 
    internal sealed class AggregateSymbol : NamespaceOrAggregateSymbol
    {
        public Type AssociatedSystemType;
        public Assembly AssociatedAssembly;
 
        // The instance type. Created when first needed.
        private AggregateType _atsInst;
 
        private AggregateType _pBaseClass;     // For a class/struct/enum, the base class. For iface: unused.
        private AggregateType _pUnderlyingType; // For enum, the underlying type. For iface, the resolved CoClass. Not used for class/struct.
 
        private TypeArray _ifaces;         // The explicit base interfaces for a class or interface.
        private TypeArray _ifacesAll;      // Recursive closure of base interfaces ordered so an iface appears before all of its base ifaces.
 
        private TypeArray _typeVarsThis; // Type variables for this generic class, as declarations.
        private TypeArray _typeVarsAll;     // The type variables for this generic class and all containing classes.
 
        // First UD conversion operator. This chain is for this type only (not base types).
        // The hasConversion flag indicates whether this or any base types have UD conversions.
        private MethodSymbol _pConvFirst;
 
        // ------------------------------------------------------------------------
        //
        // Put members that are bits under here in a contiguous section.
        //
        // ------------------------------------------------------------------------
 
        private AggKindEnum _aggKind;
 
        // Where this came from - fabricated, source, import
        // Fabricated AGGs have isSource == true but hasParseTree == false.
        // N.B.: in incremental builds, it is quite possible for
        // isSource==TRUE and hasParseTree==FALSE. Be
        // sure you use the correct variable for what you are trying to do!
 
        // Predefined
        private bool _isPredefined;    // A special predefined type.
        private PredefinedType _iPredef;        // index of the predefined type, if isPredefined.
 
        // Flags
        private bool _isAbstract;      // Can it be instantiated?
        private bool _isSealed;        // Can it be derived from?
 
        // Constructors
        private bool _hasPubNoArgCtor; // Whether it has a public instance constructor taking no args
 
        // User defined operators
 
        private bool _isSkipUDOps; // Never check for user defined operators on this type (eg, decimal, string, delegate).
 
        // When this is unset we don't know if we have conversions.  When this
        // is set it indicates if this type or any base type has user defined
        // conversion operators
        private bool? _hasConversion;
 
        // ----------------------------------------------------------------------------
        // AggregateSymbol
        // ----------------------------------------------------------------------------
 
        public AggregateSymbol GetBaseAgg()
        {
            return _pBaseClass?.OwningAggregate;
        }
 
        public AggregateType getThisType()
        {
            if (_atsInst == null)
            {
                Debug.Assert(GetTypeVars() == GetTypeVarsAll() || isNested());
 
                AggregateType pOuterType = isNested() ? GetOuterAgg().getThisType() : null;
 
                _atsInst = TypeManager.GetAggregate(this, pOuterType, GetTypeVars());
            }
 
            //Debug.Assert(GetTypeVars().Size == atsInst.GenericArguments.Count);
            return _atsInst;
        }
 
        public bool FindBaseAgg(AggregateSymbol agg)
        {
            for (AggregateSymbol aggT = this; aggT != null; aggT = aggT.GetBaseAgg())
            {
                if (aggT == agg)
                    return true;
            }
            return false;
        }
 
        public NamespaceOrAggregateSymbol Parent => parent as NamespaceOrAggregateSymbol;
 
        public bool isNested() => parent is AggregateSymbol;
 
        public AggregateSymbol GetOuterAgg() => parent as AggregateSymbol;
 
        public bool isPredefAgg(PredefinedType pt)
        {
            return _isPredefined && (PredefinedType)_iPredef == pt;
        }
 
        // ----------------------------------------------------------------------------
        // The following are the Accessor functions for AggregateSymbol.
        // ----------------------------------------------------------------------------
 
        public AggKindEnum AggKind()
        {
            return (AggKindEnum)_aggKind;
        }
 
        public void SetAggKind(AggKindEnum aggKind)
        {
            // NOTE: When importing can demote types:
            //  - enums with no underlying type go to struct
            //  - delegates which are abstract or have no .ctor/Invoke method goto class
            _aggKind = aggKind;
 
            //An interface is always abstract
            if (aggKind == AggKindEnum.Interface)
            {
                SetAbstract(true);
            }
        }
 
        public bool IsClass()
        {
            return AggKind() == AggKindEnum.Class;
        }
 
        public bool IsDelegate()
        {
            return AggKind() == AggKindEnum.Delegate;
        }
 
        public bool IsInterface()
        {
            return AggKind() == AggKindEnum.Interface;
        }
 
        public bool IsStruct()
        {
            return AggKind() == AggKindEnum.Struct;
        }
 
        public bool IsEnum()
        {
            return AggKind() == AggKindEnum.Enum;
        }
 
        public bool IsValueType()
        {
            return AggKind() == AggKindEnum.Struct || AggKind() == AggKindEnum.Enum;
        }
 
        public bool IsRefType()
        {
            return AggKind() == AggKindEnum.Class ||
                AggKind() == AggKindEnum.Interface || AggKind() == AggKindEnum.Delegate;
        }
 
        public bool IsStatic()
        {
            return (_isAbstract && _isSealed);
        }
 
        public bool IsAbstract()
        {
            return _isAbstract;
        }
 
        public void SetAbstract(bool @abstract)
        {
            _isAbstract = @abstract;
        }
 
        public bool IsPredefined()
        {
            return _isPredefined;
        }
 
        public void SetPredefined(bool predefined)
        {
            _isPredefined = predefined;
        }
 
        public PredefinedType GetPredefType()
        {
            return (PredefinedType)_iPredef;
        }
 
        public void SetPredefType(PredefinedType predef)
        {
            _iPredef = predef;
        }
 
        public bool IsSealed()
        {
            return _isSealed;
        }
 
        public void SetSealed(bool @sealed)
        {
            _isSealed = @sealed;
        }
 
        ////////////////////////////////////////////////////////////////////////////////
 
        [RequiresUnreferencedCode(Binder.TrimmerWarning)]
        public bool HasConversion()
        {
            SymbolTable.AddConversionsForType(AssociatedSystemType);
 
            if (!_hasConversion.HasValue)
            {
                // ok, we tried defining all the conversions, and we didn't get anything
                // for this type.  However, we will still think this type has conversions
                // if it's base type has conversions.
                _hasConversion = GetBaseAgg() != null && GetBaseAgg().HasConversion();
            }
 
            return _hasConversion.Value;
        }
 
        ////////////////////////////////////////////////////////////////////////////////
 
        public void SetHasConversion()
        {
            _hasConversion = true;
        }
 
        ////////////////////////////////////////////////////////////////////////////////
 
        public bool HasPubNoArgCtor()
        {
            return _hasPubNoArgCtor;
        }
 
        public void SetHasPubNoArgCtor(bool hasPubNoArgCtor)
        {
            _hasPubNoArgCtor = hasPubNoArgCtor;
        }
 
        public bool IsSkipUDOps()
        {
            return _isSkipUDOps;
        }
 
        public void SetSkipUDOps(bool skipUDOps)
        {
            _isSkipUDOps = skipUDOps;
        }
 
        public TypeArray GetTypeVars()
        {
            return _typeVarsThis;
        }
 
        public void SetTypeVars(TypeArray typeVars)
        {
            if (typeVars == null)
            {
                _typeVarsThis = null;
                _typeVarsAll = null;
            }
            else
            {
                TypeArray outerTypeVars;
                if (GetOuterAgg() != null)
                {
                    Debug.Assert(GetOuterAgg().GetTypeVars() != null);
                    Debug.Assert(GetOuterAgg().GetTypeVarsAll() != null);
 
                    outerTypeVars = GetOuterAgg().GetTypeVarsAll();
                }
                else
                {
                    outerTypeVars = TypeArray.Empty;
                }
 
                _typeVarsThis = typeVars;
                _typeVarsAll = TypeArray.Concat(outerTypeVars, typeVars);
            }
        }
 
        public TypeArray GetTypeVarsAll()
        {
            return _typeVarsAll;
        }
 
        public AggregateType GetBaseClass()
        {
            return _pBaseClass;
        }
 
        public void SetBaseClass(AggregateType baseClass)
        {
            _pBaseClass = baseClass;
        }
 
        public AggregateType GetUnderlyingType()
        {
            return _pUnderlyingType;
        }
 
        public void SetUnderlyingType(AggregateType underlyingType)
        {
            _pUnderlyingType = underlyingType;
        }
 
        public TypeArray GetIfaces()
        {
            return _ifaces;
        }
 
        public void SetIfaces(TypeArray ifaces)
        {
            _ifaces = ifaces;
        }
 
        public TypeArray GetIfacesAll()
        {
            return _ifacesAll;
        }
 
        public void SetIfacesAll(TypeArray ifacesAll)
        {
            _ifacesAll = ifacesAll;
        }
 
        public MethodSymbol GetFirstUDConversion()
        {
            return _pConvFirst;
        }
 
        public void SetFirstUDConversion(MethodSymbol conv)
        {
            _pConvFirst = conv;
        }
 
        public bool InternalsVisibleTo(Assembly assembly) => TypeManager.InternalsVisibleTo(AssociatedAssembly, assembly);
    }
}