<PackageReference Include="Microsoft.CSharp" Version="4.4.0" />

SymbolLoader

sealed class SymbolLoader
using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Syntax; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal sealed class SymbolLoader { private readonly NameManager _nameManager; public PredefinedMembers PredefinedMembers { get; } private GlobalSymbolContext GlobalSymbolContext { get; } public ErrorHandling ErrorContext { get; } public SymbolTable RuntimeBinderSymbolTable { get; set; } public TypeManager TypeManager => GlobalSymbolContext.TypeManager; public SymbolLoader(GlobalSymbolContext globalSymbols, UserStringBuilder userStringBuilder, ErrorHandling errorContext) { _nameManager = globalSymbols.GetNameManager(); PredefinedMembers = new PredefinedMembers(this); ErrorContext = errorContext; GlobalSymbolContext = globalSymbols; } public ErrorHandling GetErrorContext() { return ErrorContext; } public GlobalSymbolContext GetGlobalSymbolContext() { return GlobalSymbolContext; } public MethodSymbol LookupInvokeMeth(AggregateSymbol pAggDel) { for (Symbol symbol = LookupAggMember(NameManager.GetPredefinedName(PredefinedName.PN_INVOKE), pAggDel, symbmask_t.MASK_ALL); symbol != null; symbol = LookupNextSym(symbol, pAggDel, symbmask_t.MASK_ALL)) { if (symbol.IsMethodSymbol() && symbol.AsMethodSymbol().isInvoke()) return symbol.AsMethodSymbol(); } return null; } public NameManager GetNameManager() { return _nameManager; } public PredefinedTypes getPredefTypes() { return GlobalSymbolContext.GetPredefTypes(); } public TypeManager GetTypeManager() { return TypeManager; } public PredefinedMembers getPredefinedMembers() { return PredefinedMembers; } public BSYMMGR getBSymmgr() { return GlobalSymbolContext.GetGlobalSymbols(); } public SymFactory GetGlobalSymbolFactory() { return GlobalSymbolContext.GetGlobalSymbolFactory(); } public MiscSymFactory GetGlobalMiscSymFactory() { return GlobalSymbolContext.GetGlobalMiscSymFactory(); } public AggregateType GetReqPredefType(PredefinedType pt) { return GetReqPredefType(pt, true); } public AggregateType GetReqPredefType(PredefinedType pt, bool fEnsureState) { return GetTypeManager().GetReqPredefAgg(pt)?.getThisType(); } public AggregateSymbol GetOptPredefAgg(PredefinedType pt) { return GetOptPredefAgg(pt, true); } private AggregateSymbol GetOptPredefAgg(PredefinedType pt, bool fEnsureState) { return GetTypeManager().GetOptPredefAgg(pt); } public AggregateType GetOptPredefType(PredefinedType pt) { return GetOptPredefType(pt, true); } public AggregateType GetOptPredefType(PredefinedType pt, bool fEnsureState) { return GetTypeManager().GetOptPredefAgg(pt)?.getThisType(); } public AggregateType GetOptPredefTypeErr(PredefinedType pt, bool fEnsureState) { AggregateSymbol optPredefAgg = GetTypeManager().GetOptPredefAgg(pt); if (optPredefAgg == null) { getPredefTypes().ReportMissingPredefTypeError(ErrorContext, pt); return null; } return optPredefAgg.getThisType(); } public Symbol LookupAggMember(Name name, AggregateSymbol agg, symbmask_t mask) { return getBSymmgr().LookupAggMember(name, agg, mask); } public Symbol LookupNextSym(Symbol sym, ParentSymbol parent, symbmask_t kindmask) { return BSYMMGR.LookupNextSym(sym, parent, kindmask); } public AggregateType GetAggTypeSym(CType typeSym) { switch (typeSym.GetTypeKind()) { case TypeKind.TK_AggregateType: return typeSym.AsAggregateType(); case TypeKind.TK_ArrayType: return GetReqPredefType(PredefinedType.PT_ARRAY); case TypeKind.TK_TypeParameterType: return typeSym.AsTypeParameterType().GetEffectiveBaseClass(); case TypeKind.TK_NullableType: return typeSym.AsNullableType().GetAts(ErrorContext); default: return null; } } private bool IsBaseInterface(CType pDerived, CType pBase) { if (!pBase.isInterfaceType()) return false; if (!pDerived.IsAggregateType()) return false; for (AggregateType aggregateType = pDerived.AsAggregateType(); aggregateType != null; aggregateType = aggregateType.GetBaseClass()) { TypeArray ifacesAll = aggregateType.GetIfacesAll(); for (int i = 0; i < ifacesAll.Count; i++) { if (AreTypesEqualForConversion(ifacesAll[i], pBase)) return true; } } return false; } public bool IsBaseClassOfClass(CType pDerived, CType pBase) { if (!pDerived.isClassType()) return false; return IsBaseClass(pDerived, pBase); } private bool IsBaseClass(CType pDerived, CType pBase) { if (!pBase.isClassType()) return false; if (pDerived.IsNullableType()) { pDerived = pDerived.AsNullableType().GetAts(ErrorContext); if (pDerived == null) return false; } if (!pDerived.IsAggregateType()) return false; AggregateType aggregateType = pDerived.AsAggregateType(); AggregateType aggregateType2 = pBase.AsAggregateType(); for (AggregateType baseClass = aggregateType.GetBaseClass(); baseClass != null; baseClass = baseClass.GetBaseClass()) { if (baseClass == aggregateType2) return true; } return false; } private bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDest) { if (pSource.rank == pDest.rank && pSource.IsSZArray == pDest.IsSZArray) return HasImplicitReferenceConversion(pSource.GetElementType(), pDest.GetElementType()); return false; } public bool HasIdentityOrImplicitReferenceConversion(CType pSource, CType pDest) { if (AreTypesEqualForConversion(pSource, pDest)) return true; return HasImplicitReferenceConversion(pSource, pDest); } private bool AreTypesEqualForConversion(CType pType1, CType pType2) { return pType1.Equals(pType2); } private bool HasArrayConversionToInterface(ArrayType pSource, CType pDest) { if (!pSource.IsSZArray) return false; if (!pDest.isInterfaceType()) return false; if (pDest.isPredefType(PredefinedType.PT_IENUMERABLE)) return true; AggregateType aggregateType = pDest.AsAggregateType(); AggregateSymbol aggregate = pDest.getAggregate(); if (!aggregate.isPredefAgg(PredefinedType.PT_G_ILIST) && !aggregate.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) && !aggregate.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) && !aggregate.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) && !aggregate.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST)) return false; CType elementType = pSource.GetElementType(); CType pDest2 = aggregateType.GetTypeArgsAll()[0]; return HasIdentityOrImplicitReferenceConversion(elementType, pDest2); } private bool HasImplicitReferenceConversion(CType pSource, CType pDest) { if (pSource.IsRefType() && pDest.isPredefType(PredefinedType.PT_OBJECT)) return true; if (pSource.isClassType() && pDest.isClassType() && IsBaseClass(pSource, pDest)) return true; if (pSource.isClassType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest)) return true; if (pSource.isInterfaceType() && pDest.isInterfaceType() && HasAnyBaseInterfaceConversion(pSource, pDest)) return true; if (pSource.isInterfaceType() && pDest.isInterfaceType() && pSource != pDest && HasInterfaceConversion(pSource.AsAggregateType(), pDest.AsAggregateType())) return true; if (pSource.IsArrayType() && pDest.IsArrayType() && HasCovariantArrayConversion(pSource.AsArrayType(), pDest.AsArrayType())) return true; if (pSource.IsArrayType() && (pDest.isPredefType(PredefinedType.PT_ARRAY) || IsBaseInterface(GetReqPredefType(PredefinedType.PT_ARRAY, false), pDest))) return true; if (pSource.IsArrayType() && HasArrayConversionToInterface(pSource.AsArrayType(), pDest)) return true; if (pSource.isDelegateType() && (pDest.isPredefType(PredefinedType.PT_MULTIDEL) || pDest.isPredefType(PredefinedType.PT_DELEGATE) || IsBaseInterface(GetReqPredefType(PredefinedType.PT_MULTIDEL, false), pDest))) return true; if (pSource.isDelegateType() && pDest.isDelegateType() && HasDelegateConversion(pSource.AsAggregateType(), pDest.AsAggregateType())) return true; if (pSource.IsNullType() && pDest.IsRefType()) return true; if (pSource.IsNullType() && pDest.IsNullableType()) return true; if (pSource.IsTypeParameterType() && HasImplicitReferenceTypeParameterConversion(pSource.AsTypeParameterType(), pDest)) return true; return false; } private bool HasImplicitReferenceTypeParameterConversion(TypeParameterType pSource, CType pDest) { if (!pSource.IsRefType()) return false; AggregateType effectiveBaseClass = pSource.GetEffectiveBaseClass(); if (pDest == effectiveBaseClass) return true; if (IsBaseClass(effectiveBaseClass, pDest)) return true; if (IsBaseInterface(effectiveBaseClass, pDest)) return true; TypeArray interfaceBounds = pSource.GetInterfaceBounds(); for (int i = 0; i < interfaceBounds.Count; i++) { if (interfaceBounds[i] == pDest) return true; } if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType())) return true; return false; } private bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase) { if (!pBase.isInterfaceType()) return false; if (!pDerived.IsAggregateType()) return false; for (AggregateType aggregateType = pDerived.AsAggregateType(); aggregateType != null; aggregateType = aggregateType.GetBaseClass()) { TypeArray ifacesAll = aggregateType.GetIfacesAll(); for (int i = 0; i < ifacesAll.Count; i++) { if (HasInterfaceConversion(ifacesAll[i].AsAggregateType(), pBase.AsAggregateType())) return true; } } return false; } private bool HasInterfaceConversion(AggregateType pSource, AggregateType pDest) { return HasVariantConversion(pSource, pDest); } private bool HasDelegateConversion(AggregateType pSource, AggregateType pDest) { return HasVariantConversion(pSource, pDest); } private bool HasVariantConversion(AggregateType pSource, AggregateType pDest) { if (pSource == pDest) return true; AggregateSymbol aggregate = pSource.getAggregate(); if (aggregate != pDest.getAggregate()) return false; TypeArray typeVarsAll = aggregate.GetTypeVarsAll(); TypeArray typeArgsAll = pSource.GetTypeArgsAll(); TypeArray typeArgsAll2 = pDest.GetTypeArgsAll(); for (int i = 0; i < typeVarsAll.Count; i++) { CType cType = typeArgsAll[i]; CType cType2 = typeArgsAll2[i]; if (cType != cType2) { TypeParameterType typeParameterType = typeVarsAll[i].AsTypeParameterType(); if (typeParameterType.Invariant) return false; if (typeParameterType.Covariant && !HasImplicitReferenceConversion(cType, cType2)) return false; if (typeParameterType.Contravariant && !HasImplicitReferenceConversion(cType2, cType)) return false; } } return true; } private bool HasImplicitBoxingTypeParameterConversion(TypeParameterType pSource, CType pDest) { if (pSource.IsRefType()) return false; AggregateType effectiveBaseClass = pSource.GetEffectiveBaseClass(); if (pDest == effectiveBaseClass) return true; if (IsBaseClass(effectiveBaseClass, pDest)) return true; if (IsBaseInterface(effectiveBaseClass, pDest)) return true; TypeArray interfaceBounds = pSource.GetInterfaceBounds(); for (int i = 0; i < interfaceBounds.Count; i++) { if (interfaceBounds[i] == pDest) return true; } return false; } private bool HasImplicitTypeParameterBaseConversion(TypeParameterType pSource, CType pDest) { if (HasImplicitReferenceTypeParameterConversion(pSource, pDest)) return true; if (HasImplicitBoxingTypeParameterConversion(pSource, pDest)) return true; if (pDest.IsTypeParameterType() && pSource.DependsOn(pDest.AsTypeParameterType())) return true; return false; } public bool HasImplicitBoxingConversion(CType pSource, CType pDest) { if (pSource.IsTypeParameterType() && HasImplicitBoxingTypeParameterConversion(pSource.AsTypeParameterType(), pDest)) return true; if (!pSource.IsValType() || !pDest.IsRefType()) return false; if (pSource.IsNullableType()) return HasImplicitBoxingConversion(pSource.AsNullableType().GetUnderlyingType(), pDest); if (IsBaseClass(pSource, pDest)) return true; if (HasAnyBaseInterfaceConversion(pSource, pDest)) return true; return false; } public bool HasBaseConversion(CType pSource, CType pDest) { if (pSource.IsAggregateType() && pDest.isPredefType(PredefinedType.PT_OBJECT)) return true; if (HasIdentityOrImplicitReferenceConversion(pSource, pDest)) return true; if (HasImplicitBoxingConversion(pSource, pDest)) return true; if (pSource.IsTypeParameterType() && HasImplicitTypeParameterBaseConversion(pSource.AsTypeParameterType(), pDest)) return true; return false; } public bool FCanLift() { return GetOptPredefAgg(PredefinedType.PT_G_OPTIONAL, false) != null; } public bool IsBaseAggregate(AggregateSymbol derived, AggregateSymbol base) { if (derived == base) return true; if (base.IsInterface()) { while (derived != null) { for (int i = 0; i < derived.GetIfacesAll().Count; i++) { AggregateType aggregateType = derived.GetIfacesAll()[i].AsAggregateType(); if (aggregateType.getAggregate() == base) return true; } derived = derived.GetBaseAgg(); } return false; } while (derived.GetBaseClass() != null) { derived = derived.GetBaseClass().getAggregate(); if (derived == base) return true; } return false; } internal void SetSymbolTable(SymbolTable symbolTable) { RuntimeBinderSymbolTable = symbolTable; } } }