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

MemberLookup

sealed class MemberLookup
using Microsoft.CSharp.RuntimeBinder.Errors; using Microsoft.CSharp.RuntimeBinder.Syntax; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; namespace Microsoft.CSharp.RuntimeBinder.Semantics { internal sealed class MemberLookup { private CType _typeSrc; private CType _typeQual; private ParentSymbol _symWhere; private Name _name; private int _arity; private MemLookFlags _flags; private readonly List<AggregateType> _rgtypeStart; private List<AggregateType> _prgtype; private int _csym; private readonly SymWithType _swtFirst; private readonly List<MethPropWithType> _methPropWithTypeList; private readonly SymWithType _swtAmbig; private readonly SymWithType _swtInaccess; private readonly SymWithType _swtBad; private readonly SymWithType _swtBogus; private readonly SymWithType _swtBadArity; private bool _fMulti; private void RecordType(AggregateType type, Symbol sym) { if (!_prgtype.Contains(type)) _prgtype.Add(type); _csym++; if (_swtFirst == (SymWithType)null) { _swtFirst.Set(sym, type); _fMulti = (sym is MethodSymbol || sym is IndexerSymbol); } } private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) { bool result = false; pfHideByName = false; bool flag = !CSemanticChecker.CheckTypeAccess(typeCur, _symWhere); if (flag && (_csym != 0 || _swtInaccess != (SymWithType)null)) return false; Symbol symbol = SymbolLoader.LookupAggMember(_name, typeCur.OwningAggregate, symbmask_t.MASK_Member); while (true) { if (symbol == null) return result; if (_arity > 0) { MethodSymbol methodSymbol = symbol as MethodSymbol; if (methodSymbol == null || methodSymbol.typeVars.Count != _arity) { if (!(bool)_swtBadArity) _swtBadArity.Set(symbol, typeCur); goto IL_040f; } } if (!symbol.IsOverride() || symbol.IsHideByName()) { MethodOrPropertySymbol methodOrPropertySymbol = symbol as MethodOrPropertySymbol; MethodSymbol methodSymbol2 = symbol as MethodSymbol; if (methodOrPropertySymbol != null && (_flags & MemLookFlags.UserCallable) != 0 && !methodOrPropertySymbol.isUserCallable() && (methodSymbol2 == null || !methodSymbol2.isPropertyAccessor() || ((!symbol.name.Text.StartsWith("set_", StringComparison.Ordinal) || methodSymbol2.Params.Count <= 1) && (!symbol.name.Text.StartsWith("get_", StringComparison.Ordinal) || methodSymbol2.Params.Count <= 0)))) { if (!(bool)_swtInaccess) _swtInaccess.Set(symbol, typeCur); } else if (flag || !CSemanticChecker.CheckAccess(symbol, typeCur, _symWhere, _typeQual)) { if (!(bool)_swtInaccess) _swtInaccess.Set(symbol, typeCur); if (flag) return false; } else { PropertySymbol propertySymbol = symbol as PropertySymbol; if ((_flags & MemLookFlags.Ctor) == MemLookFlags.None != (methodSymbol2 == null || !methodSymbol2.IsConstructor()) || (_flags & MemLookFlags.Operator) == MemLookFlags.None != (methodSymbol2 == null || !methodSymbol2.isOperator) || (_flags & MemLookFlags.Indexer) == MemLookFlags.None != !(propertySymbol is IndexerSymbol)) { if (!(bool)_swtBad) _swtBad.Set(symbol, typeCur); } else if (!(symbol is MethodSymbol) && (_flags & MemLookFlags.Indexer) == MemLookFlags.None && CSemanticChecker.CheckBogus(symbol)) { if (!(bool)_swtBogus) _swtBogus.Set(symbol, typeCur); } else { if ((_flags & MemLookFlags.MustBeInvocable) != 0) { FieldSymbol fieldSymbol = symbol as FieldSymbol; if ((fieldSymbol != null && !IsDelegateType(fieldSymbol.GetType(), typeCur) && !IsDynamicMember(symbol)) || (propertySymbol != null && !IsDelegateType(propertySymbol.RetType, typeCur) && !IsDynamicMember(symbol))) { if (!(bool)_swtBad) _swtBad.Set(symbol, typeCur); goto IL_040f; } } if (methodOrPropertySymbol != null) { MethPropWithType item = new MethPropWithType(methodOrPropertySymbol, typeCur); _methPropWithTypeList.Add(item); } result = true; if ((bool)_swtFirst) { if (!typeCur.IsInterfaceType) { if (!_fMulti) { if ((!(_swtFirst.Sym is FieldSymbol) || !(symbol is EventSymbol) || !_swtFirst.Field().isEvent) && (!(_swtFirst.Sym is FieldSymbol) || !(symbol is EventSymbol))) break; goto IL_040f; } if (_swtFirst.Sym.getKind() != symbol.getKind()) { if (typeCur == _prgtype[0]) break; pfHideByName = true; goto IL_040f; } } else if (!_fMulti) { if (!(symbol is MethodSymbol)) break; _prgtype = new List<AggregateType>(); _csym = 0; _swtFirst.Clear(); _swtAmbig.Clear(); } else if (_swtFirst.Sym.getKind() != symbol.getKind()) { if (!typeCur.DiffHidden && !(_swtFirst.Sym is MethodSymbol)) break; pfHideByName = true; goto IL_040f; } } RecordType(typeCur, symbol); if (methodOrPropertySymbol != null && methodOrPropertySymbol.isHideByName) pfHideByName = true; } } } goto IL_040f; IL_040f: symbol = symbol.LookupNext(symbmask_t.MASK_Member); } if (!(bool)_swtAmbig) _swtAmbig.Set(symbol, typeCur); pfHideByName = true; return true; } private static bool IsDynamicMember(Symbol sym) { DynamicAttribute dynamicAttribute = null; FieldSymbol fieldSymbol = sym as FieldSymbol; if (fieldSymbol != null) { if (!fieldSymbol.getType().IsPredefType(PredefinedType.PT_OBJECT)) return false; object[] array = fieldSymbol.AssociatedFieldInfo.GetCustomAttributes(typeof(DynamicAttribute), false).ToArray(); if (array.Length == 1) dynamicAttribute = (array[0] as DynamicAttribute); } else { PropertySymbol propertySymbol = (PropertySymbol)sym; if (!propertySymbol.getType().IsPredefType(PredefinedType.PT_OBJECT)) return false; object[] array2 = propertySymbol.AssociatedPropertyInfo.GetCustomAttributes(typeof(DynamicAttribute), false).ToArray(); if (array2.Length == 1) dynamicAttribute = (array2[0] as DynamicAttribute); } if (dynamicAttribute == null) return false; if (dynamicAttribute.TransformFlags.Count != 0) { if (dynamicAttribute.TransformFlags.Count == 1) return dynamicAttribute.TransformFlags[0]; return false; } return true; } private bool LookupInClass(AggregateType typeStart, ref AggregateType ptypeEnd) { AggregateType aggregateType = ptypeEnd; AggregateType aggregateType2 = typeStart; while (aggregateType2 != aggregateType && aggregateType2 != null) { SearchSingleType(aggregateType2, out bool pfHideByName); if ((bool)_swtFirst && !_fMulti) return false; if (pfHideByName) { ptypeEnd = null; return true; } if ((_flags & MemLookFlags.Ctor) != 0) return false; aggregateType2 = aggregateType2.BaseClass; } return true; } private bool LookupInInterfaces(AggregateType typeStart, TypeArray types) { if (typeStart != null) { typeStart.AllHidden = false; typeStart.DiffHidden = (_swtFirst != (SymWithType)null); } for (int i = 0; i < types.Count; i++) { AggregateType aggregateType = (AggregateType)types[i]; aggregateType.AllHidden = false; aggregateType.DiffHidden = _swtFirst; } bool flag = false; AggregateType aggregateType2 = typeStart; int num = 0; if (aggregateType2 == null) aggregateType2 = (AggregateType)types[num++]; while (true) { if (!aggregateType2.AllHidden && SearchSingleType(aggregateType2, out bool pfHideByName)) { pfHideByName |= !_fMulti; CType[] items = aggregateType2.IfacesAll.Items; for (int j = 0; j < items.Length; j++) { AggregateType aggregateType3 = (AggregateType)items[j]; if (pfHideByName) aggregateType3.AllHidden = true; aggregateType3.DiffHidden = true; } if (pfHideByName) flag = true; } if (num >= types.Count) break; aggregateType2 = (types[num++] as AggregateType); } return !flag; } private static RuntimeBinderException ReportBogus(SymWithType swt) { MethodSymbol getterMethod = swt.Prop().GetterMethod; MethodSymbol setterMethod = swt.Prop().SetterMethod; if (!((getterMethod == null) | (setterMethod == null))) return ErrorHandling.Error(ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(getterMethod, swt.GetType()), new SymWithType(setterMethod, swt.GetType()), new ErrArgRefOnly(swt.Sym)); return ErrorHandling.Error(ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(getterMethod ?? setterMethod, swt.GetType()), new ErrArgRefOnly(swt.Sym)); } private static bool IsDelegateType(CType pSrcType, AggregateType pAggType) { return TypeManager.SubstType(pSrcType, pAggType, pAggType.TypeArgsAll).IsDelegateType; } public MemberLookup() { _methPropWithTypeList = new List<MethPropWithType>(); _rgtypeStart = new List<AggregateType>(); _swtFirst = new SymWithType(); _swtAmbig = new SymWithType(); _swtInaccess = new SymWithType(); _swtBad = new SymWithType(); _swtBogus = new SymWithType(); _swtBadArity = new SymWithType(); } public bool Lookup(CType typeSrc, Expr obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags) { _prgtype = _rgtypeStart; _typeSrc = typeSrc; _symWhere = symWhere; _name = name; _arity = arity; _flags = flags; _typeQual = (((_flags & MemLookFlags.Ctor) != 0) ? _typeSrc : obj?.Type); AggregateType aggregateType; AggregateType aggregateType2; TypeArray typeArray; if (typeSrc.IsInterfaceType) { aggregateType = null; aggregateType2 = (AggregateType)typeSrc; typeArray = aggregateType2.IfacesAll; } else { aggregateType = (AggregateType)typeSrc; aggregateType2 = null; typeArray = (aggregateType.IsWindowsRuntimeType ? aggregateType.WinRTCollectionIfacesAll : TypeArray.Empty); } AggregateType ptypeEnd = (aggregateType2 != null || typeArray.Count > 0) ? SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT) : null; if ((aggregateType == null || LookupInClass(aggregateType, ref ptypeEnd)) && (aggregateType2 != null || typeArray.Count > 0) && LookupInInterfaces(aggregateType2, typeArray) && ptypeEnd != null) { AggregateType ptypeEnd2 = null; LookupInClass(ptypeEnd, ref ptypeEnd2); } return !FError(); } private bool FError() { if ((bool)_swtFirst) return _swtAmbig; return true; } public SymWithType SwtFirst() { return _swtFirst; } public Exception ReportErrors() { if ((bool)_swtFirst) return ErrorHandling.Error(ErrorCode.ERR_AmbigMember, _swtFirst, _swtAmbig); if ((bool)_swtInaccess) { if (_swtInaccess.Sym.isUserCallable() || (_flags & MemLookFlags.UserCallable) == MemLookFlags.None) return CSemanticChecker.ReportAccessError(_swtInaccess, _symWhere, _typeQual); return ErrorHandling.Error(ErrorCode.ERR_CantCallSpecialMethod, _swtInaccess); } if ((_flags & MemLookFlags.Ctor) != 0) { if (_arity <= 0) return ErrorHandling.Error(ErrorCode.ERR_NoConstructors, ((AggregateType)_typeSrc).OwningAggregate); return ErrorHandling.Error(ErrorCode.ERR_BadCtorArgCount, ((AggregateType)_typeSrc).OwningAggregate, _arity); } if ((_flags & MemLookFlags.Operator) != 0) return ErrorHandling.Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); if ((_flags & MemLookFlags.Indexer) != 0) return ErrorHandling.Error(ErrorCode.ERR_BadIndexLHS, _typeSrc); if ((bool)_swtBad) return ErrorHandling.Error(((_flags & MemLookFlags.MustBeInvocable) != 0) ? ErrorCode.ERR_NonInvocableMemberCalled : ErrorCode.ERR_CantCallSpecialMethod, _swtBad); if ((bool)_swtBogus) return ReportBogus(_swtBogus); if ((bool)_swtBadArity) { MethodSymbol methodSymbol = _swtBadArity.Sym as MethodSymbol; if (methodSymbol != null) { int count = methodSymbol.typeVars.Count; return ErrorHandling.Error((count > 0) ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), count); } return ErrorHandling.Error(ErrorCode.ERR_TypeArgsNotAllowed, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym)); } return ErrorHandling.Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); } } }