1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Diagnostics; 7 using System.Reflection; 8 using Microsoft.CSharp.RuntimeBinder.Syntax; 9 10 namespace Microsoft.CSharp.RuntimeBinder.Semantics 11 { 12 // Name used for AGGDECLs in the symbol table. 13 14 // AggregateSymbol - a symbol representing an aggregate type. These are classes, 15 // interfaces, and structs. Parent is a namespace or class. Children are methods, 16 // properties, and member variables, and types (including its own AGGTYPESYMs). 17 18 internal class AggregateSymbol : NamespaceOrAggregateSymbol 19 { 20 public Type AssociatedSystemType; 21 public Assembly AssociatedAssembly; 22 23 // The instance type. Created when first needed. 24 private AggregateType _atsInst; 25 26 private AggregateType _pBaseClass; // For a class/struct/enum, the base class. For iface: unused. 27 private AggregateType _pUnderlyingType; // For enum, the underlying type. For iface, the resolved CoClass. Not used for class/struct. 28 29 private TypeArray _ifaces; // The explicit base interfaces for a class or interface. 30 private TypeArray _ifacesAll; // Recursive closure of base interfaces ordered so an iface appears before all of its base ifaces. 31 32 private TypeArray _typeVarsThis; // Type variables for this generic class, as declarations. 33 private TypeArray _typeVarsAll; // The type variables for this generic class and all containing classes. 34 35 private TypeManager _pTypeManager; // This is so AGGTYPESYMs can instantiate their baseClass and ifacesAll members on demand. 36 37 // First UD conversion operator. This chain is for this type only (not base types). 38 // The hasConversion flag indicates whether this or any base types have UD conversions. 39 private MethodSymbol _pConvFirst; 40 41 // ------------------------------------------------------------------------ 42 // 43 // Put members that are bits under here in a contiguous section. 44 // 45 // ------------------------------------------------------------------------ 46 47 private AggKindEnum _aggKind; 48 49 // Where this came from - fabricated, source, import 50 // Fabricated AGGs have isSource == true but hasParseTree == false. 51 // N.B.: in incremental builds, it is quite possible for 52 // isSource==TRUE and hasParseTree==FALSE. Be 53 // sure you use the correct variable for what you are trying to do! 54 55 // Predefined 56 private bool _isPredefined; // A special predefined type. 57 private PredefinedType _iPredef; // index of the predefined type, if isPredefined. 58 59 // Flags 60 private bool _isAbstract; // Can it be instantiated? 61 private bool _isSealed; // Can it be derived from? 62 63 // Constructors 64 private bool _hasPubNoArgCtor; // Whether it has a public instance constructor taking no args 65 66 // User defined operators 67 68 private bool _isSkipUDOps; // Never check for user defined operators on this type (eg, decimal, string, delegate). 69 70 // When this is unset we don't know if we have conversions. When this 71 // is set it indicates if this type or any base type has user defined 72 // conversion operators 73 private bool? _hasConversion; 74 75 // ---------------------------------------------------------------------------- 76 // AggregateSymbol 77 // ---------------------------------------------------------------------------- 78 GetBaseAgg()79 public AggregateSymbol GetBaseAgg() 80 { 81 return _pBaseClass?.getAggregate(); 82 } 83 getThisType()84 public AggregateType getThisType() 85 { 86 if (_atsInst == null) 87 { 88 Debug.Assert(GetTypeVars() == GetTypeVarsAll() || isNested()); 89 90 AggregateType pOuterType = isNested() ? GetOuterAgg().getThisType() : null; 91 92 _atsInst = _pTypeManager.GetAggregate(this, pOuterType, GetTypeVars()); 93 } 94 95 //Debug.Assert(GetTypeVars().Size == atsInst.GenericArguments.Count); 96 return _atsInst; 97 } 98 FindBaseAgg(AggregateSymbol agg)99 public bool FindBaseAgg(AggregateSymbol agg) 100 { 101 for (AggregateSymbol aggT = this; aggT != null; aggT = aggT.GetBaseAgg()) 102 { 103 if (aggT == agg) 104 return true; 105 } 106 return false; 107 } 108 109 public NamespaceOrAggregateSymbol Parent => parent as NamespaceOrAggregateSymbol; 110 isNested()111 public bool isNested() => parent is AggregateSymbol; 112 GetOuterAgg()113 public AggregateSymbol GetOuterAgg() => parent as AggregateSymbol; 114 isPredefAgg(PredefinedType pt)115 public bool isPredefAgg(PredefinedType pt) 116 { 117 return _isPredefined && (PredefinedType)_iPredef == pt; 118 } 119 120 // ---------------------------------------------------------------------------- 121 // The following are the Accessor functions for AggregateSymbol. 122 // ---------------------------------------------------------------------------- 123 AggKind()124 public AggKindEnum AggKind() 125 { 126 return (AggKindEnum)_aggKind; 127 } 128 SetAggKind(AggKindEnum aggKind)129 public void SetAggKind(AggKindEnum aggKind) 130 { 131 // NOTE: When importing can demote types: 132 // - enums with no underlying type go to struct 133 // - delegates which are abstract or have no .ctor/Invoke method goto class 134 _aggKind = aggKind; 135 136 //An interface is always abstract 137 if (aggKind == AggKindEnum.Interface) 138 { 139 SetAbstract(true); 140 } 141 } 142 IsClass()143 public bool IsClass() 144 { 145 return AggKind() == AggKindEnum.Class; 146 } 147 IsDelegate()148 public bool IsDelegate() 149 { 150 return AggKind() == AggKindEnum.Delegate; 151 } 152 IsInterface()153 public bool IsInterface() 154 { 155 return AggKind() == AggKindEnum.Interface; 156 } 157 IsStruct()158 public bool IsStruct() 159 { 160 return AggKind() == AggKindEnum.Struct; 161 } 162 IsEnum()163 public bool IsEnum() 164 { 165 return AggKind() == AggKindEnum.Enum; 166 } 167 IsValueType()168 public bool IsValueType() 169 { 170 return AggKind() == AggKindEnum.Struct || AggKind() == AggKindEnum.Enum; 171 } 172 IsRefType()173 public bool IsRefType() 174 { 175 return AggKind() == AggKindEnum.Class || 176 AggKind() == AggKindEnum.Interface || AggKind() == AggKindEnum.Delegate; 177 } 178 IsStatic()179 public bool IsStatic() 180 { 181 return (_isAbstract && _isSealed); 182 } 183 IsAbstract()184 public bool IsAbstract() 185 { 186 return _isAbstract; 187 } 188 189 public void SetAbstract(bool @abstract) 190 { 191 _isAbstract = @abstract; 192 } 193 IsPredefined()194 public bool IsPredefined() 195 { 196 return _isPredefined; 197 } 198 SetPredefined(bool predefined)199 public void SetPredefined(bool predefined) 200 { 201 _isPredefined = predefined; 202 } 203 GetPredefType()204 public PredefinedType GetPredefType() 205 { 206 return (PredefinedType)_iPredef; 207 } 208 SetPredefType(PredefinedType predef)209 public void SetPredefType(PredefinedType predef) 210 { 211 _iPredef = predef; 212 } 213 IsSealed()214 public bool IsSealed() 215 { 216 return _isSealed == true; 217 } 218 219 public void SetSealed(bool @sealed) 220 { 221 _isSealed = @sealed; 222 } 223 224 //////////////////////////////////////////////////////////////////////////////// 225 HasConversion(SymbolLoader pLoader)226 public bool HasConversion(SymbolLoader pLoader) 227 { 228 pLoader.RuntimeBinderSymbolTable.AddConversionsForType(AssociatedSystemType); 229 230 if (!_hasConversion.HasValue) 231 { 232 // ok, we tried defining all the conversions, and we didn't get anything 233 // for this type. However, we will still think this type has conversions 234 // if it's base type has conversions. 235 _hasConversion = GetBaseAgg() != null && GetBaseAgg().HasConversion(pLoader); 236 } 237 238 return _hasConversion.Value; 239 } 240 241 //////////////////////////////////////////////////////////////////////////////// 242 SetHasConversion()243 public void SetHasConversion() 244 { 245 _hasConversion = true; 246 } 247 248 //////////////////////////////////////////////////////////////////////////////// 249 HasPubNoArgCtor()250 public bool HasPubNoArgCtor() 251 { 252 return _hasPubNoArgCtor == true; 253 } 254 SetHasPubNoArgCtor(bool hasPubNoArgCtor)255 public void SetHasPubNoArgCtor(bool hasPubNoArgCtor) 256 { 257 _hasPubNoArgCtor = hasPubNoArgCtor; 258 } 259 IsSkipUDOps()260 public bool IsSkipUDOps() 261 { 262 return _isSkipUDOps == true; 263 } 264 SetSkipUDOps(bool skipUDOps)265 public void SetSkipUDOps(bool skipUDOps) 266 { 267 _isSkipUDOps = skipUDOps; 268 } 269 GetTypeVars()270 public TypeArray GetTypeVars() 271 { 272 return _typeVarsThis; 273 } 274 SetTypeVars(TypeArray typeVars)275 public void SetTypeVars(TypeArray typeVars) 276 { 277 if (typeVars == null) 278 { 279 _typeVarsThis = null; 280 _typeVarsAll = null; 281 } 282 else 283 { 284 TypeArray outerTypeVars; 285 if (GetOuterAgg() != null) 286 { 287 Debug.Assert(GetOuterAgg().GetTypeVars() != null); 288 Debug.Assert(GetOuterAgg().GetTypeVarsAll() != null); 289 290 outerTypeVars = GetOuterAgg().GetTypeVarsAll(); 291 } 292 else 293 { 294 outerTypeVars = BSYMMGR.EmptyTypeArray(); 295 } 296 297 _typeVarsThis = typeVars; 298 _typeVarsAll = _pTypeManager.ConcatenateTypeArrays(outerTypeVars, typeVars); 299 } 300 } 301 GetTypeVarsAll()302 public TypeArray GetTypeVarsAll() 303 { 304 return _typeVarsAll; 305 } 306 GetBaseClass()307 public AggregateType GetBaseClass() 308 { 309 return _pBaseClass; 310 } 311 SetBaseClass(AggregateType baseClass)312 public void SetBaseClass(AggregateType baseClass) 313 { 314 _pBaseClass = baseClass; 315 } 316 GetUnderlyingType()317 public AggregateType GetUnderlyingType() 318 { 319 return _pUnderlyingType; 320 } 321 SetUnderlyingType(AggregateType underlyingType)322 public void SetUnderlyingType(AggregateType underlyingType) 323 { 324 _pUnderlyingType = underlyingType; 325 } 326 GetIfaces()327 public TypeArray GetIfaces() 328 { 329 return _ifaces; 330 } 331 SetIfaces(TypeArray ifaces)332 public void SetIfaces(TypeArray ifaces) 333 { 334 _ifaces = ifaces; 335 } 336 GetIfacesAll()337 public TypeArray GetIfacesAll() 338 { 339 return _ifacesAll; 340 } 341 SetIfacesAll(TypeArray ifacesAll)342 public void SetIfacesAll(TypeArray ifacesAll) 343 { 344 _ifacesAll = ifacesAll; 345 } 346 GetTypeManager()347 public TypeManager GetTypeManager() 348 { 349 return _pTypeManager; 350 } 351 SetTypeManager(TypeManager typeManager)352 public void SetTypeManager(TypeManager typeManager) 353 { 354 _pTypeManager = typeManager; 355 } 356 GetFirstUDConversion()357 public MethodSymbol GetFirstUDConversion() 358 { 359 return _pConvFirst; 360 } 361 SetFirstUDConversion(MethodSymbol conv)362 public void SetFirstUDConversion(MethodSymbol conv) 363 { 364 _pConvFirst = conv; 365 } 366 InternalsVisibleTo(Assembly assembly)367 public bool InternalsVisibleTo(Assembly assembly) 368 { 369 return _pTypeManager.InternalsVisibleTo(AssociatedAssembly, assembly); 370 } 371 } 372 } 373