MemberLookup
class MemberLookup
using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal class MemberLookup
{
private CSemanticChecker _pSemanticChecker;
private SymbolLoader _pSymbolLoader;
private CType _typeSrc;
private EXPR _obj;
private CType _typeQual;
private ParentSymbol _symWhere;
private Name _name;
private int _arity;
private MemLookFlags _flags;
private CMemberLookupResults _results;
private List<AggregateType> _rgtypeStart;
private List<AggregateType> _prgtype;
private int _csym;
private SymWithType _swtFirst;
private List<MethPropWithType> _methPropWithTypeList;
private SymWithType _swtAmbig;
private SymWithType _swtInaccess;
private SymWithType _swtBad;
private SymWithType _swtBogus;
private SymWithType _swtBadArity;
private SymWithType _swtAmbigWarn;
private SymWithType _swtOverride;
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.IsMethodSymbol() || (sym.IsPropertySymbol() && sym.AsPropertySymbol().isIndexer()));
}
}
private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName)
{
bool result = false;
pfHideByName = false;
bool flag = !GetSemanticChecker().CheckTypeAccess(typeCur, _symWhere);
if (flag && (_csym != 0 || _swtInaccess != (SymWithType)null))
return false;
Symbol symbol = null;
for (symbol = GetSymbolLoader().LookupAggMember(_name, typeCur.getAggregate(), symbmask_t.MASK_ALL); symbol != null; symbol = GetSymbolLoader().LookupNextSym(symbol, typeCur.getAggregate(), symbmask_t.MASK_ALL)) {
switch (symbol.getKind()) {
case SYMKIND.SK_MethodSymbol:
if (_arity > 0 && symbol.AsMethodSymbol().typeVars.size != _arity) {
if (!(bool)_swtBadArity)
_swtBadArity.Set(symbol, typeCur);
break;
}
goto IL_0161;
case SYMKIND.SK_AggregateSymbol:
if (symbol.AsAggregateSymbol().GetTypeVars().size != _arity) {
if (!(bool)_swtBadArity)
_swtBadArity.Set(symbol, typeCur);
break;
}
goto IL_0161;
case SYMKIND.SK_TypeParameterSymbol:
if ((_flags & MemLookFlags.TypeVarsAllowed) == MemLookFlags.None)
break;
if (_arity > 0) {
if (!(bool)_swtBadArity)
_swtBadArity.Set(symbol, typeCur);
break;
}
goto IL_0161;
default:
{
if (_arity > 0) {
if (!(bool)_swtBadArity)
_swtBadArity.Set(symbol, typeCur);
break;
}
goto IL_0161;
}
IL_054f:
RecordType(typeCur, symbol);
if (symbol.IsMethodOrPropertySymbol() && symbol.AsMethodOrPropertySymbol().isHideByName)
pfHideByName = true;
break;
IL_058c:
if (!(bool)_swtAmbig)
_swtAmbig.Set(symbol, typeCur);
pfHideByName = true;
return true;
IL_0161:
if (symbol.IsOverride() && !symbol.IsHideByName()) {
if (!(bool)_swtOverride)
_swtOverride.Set(symbol, typeCur);
break;
}
if ((_flags & MemLookFlags.UserCallable) != 0 && symbol.IsMethodOrPropertySymbol() && !symbol.AsMethodOrPropertySymbol().isUserCallable()) {
bool flag2 = false;
if (symbol.IsMethodSymbol() && symbol.AsMethodSymbol().isPropertyAccessor() && ((symbol.name.Text.StartsWith("set_", StringComparison.Ordinal) && symbol.AsMethodSymbol().Params.size > 1) || (symbol.name.Text.StartsWith("get_", StringComparison.Ordinal) && symbol.AsMethodSymbol().Params.size > 0)))
flag2 = true;
if (!flag2) {
if (!(bool)_swtInaccess)
_swtInaccess.Set(symbol, typeCur);
break;
}
}
if (flag || !GetSemanticChecker().CheckAccess(symbol, typeCur, _symWhere, _typeQual)) {
if (!(bool)_swtInaccess)
_swtInaccess.Set(symbol, typeCur);
if (flag)
return false;
break;
}
if ((_flags & MemLookFlags.Ctor) == MemLookFlags.None != (!symbol.IsMethodSymbol() || !symbol.AsMethodSymbol().IsConstructor()) || (_flags & MemLookFlags.Operator) == MemLookFlags.None != (!symbol.IsMethodSymbol() || !symbol.AsMethodSymbol().isOperator) || (_flags & MemLookFlags.Indexer) == MemLookFlags.None != (!symbol.IsPropertySymbol() || !symbol.AsPropertySymbol().isIndexer())) {
if (!(bool)_swtBad)
_swtBad.Set(symbol, typeCur);
break;
}
if (!symbol.IsMethodSymbol() && (_flags & MemLookFlags.Indexer) == MemLookFlags.None && GetSemanticChecker().CheckBogus(symbol)) {
if (!(bool)_swtBogus)
_swtBogus.Set(symbol, typeCur);
break;
}
if ((_flags & MemLookFlags.MustBeInvocable) != 0 && ((symbol.IsFieldSymbol() && !IsDelegateType(symbol.AsFieldSymbol().GetType(), typeCur) && !IsDynamicMember(symbol)) || (symbol.IsPropertySymbol() && !IsDelegateType(symbol.AsPropertySymbol().RetType, typeCur) && !IsDynamicMember(symbol)))) {
if (!(bool)_swtBad)
_swtBad.Set(symbol, typeCur);
break;
}
if (symbol.IsMethodOrPropertySymbol()) {
MethPropWithType item = new MethPropWithType(symbol.AsMethodOrPropertySymbol(), typeCur);
_methPropWithTypeList.Add(item);
}
result = true;
if ((bool)_swtFirst) {
if (!typeCur.isInterfaceType()) {
if (!_fMulti) {
if ((_swtFirst.Sym.IsFieldSymbol() && symbol.IsEventSymbol() && _swtFirst.Field().isEvent) || (_swtFirst.Sym.IsFieldSymbol() && symbol.IsEventSymbol()))
break;
} else {
if (_swtFirst.Sym.getKind() == symbol.getKind())
goto IL_054f;
if (typeCur != _prgtype[0]) {
pfHideByName = true;
break;
}
}
goto IL_058c;
}
if (!_fMulti) {
if (!symbol.IsMethodSymbol())
goto IL_058c;
_swtAmbigWarn = _swtFirst;
_prgtype = new List<AggregateType>();
_csym = 0;
_swtFirst.Clear();
_swtAmbig.Clear();
} else if (_swtFirst.Sym.getKind() != symbol.getKind()) {
if (!typeCur.fDiffHidden) {
if (!_swtFirst.Sym.IsMethodSymbol())
goto IL_058c;
if (!(bool)_swtAmbigWarn)
_swtAmbigWarn.Set(symbol, typeCur);
}
pfHideByName = true;
break;
}
}
goto IL_054f;
}
}
return result;
}
private bool IsDynamicMember(Symbol sym)
{
DynamicAttribute dynamicAttribute = null;
if (sym.IsFieldSymbol()) {
if (!sym.AsFieldSymbol().getType().isPredefType(PredefinedType.PT_OBJECT))
return false;
Attribute[] array = CustomAttributeExtensions.GetCustomAttributes(sym.AsFieldSymbol().AssociatedFieldInfo, typeof(DynamicAttribute), false).ToArray();
if (array.Length == 1)
dynamicAttribute = (array[0] as DynamicAttribute);
} else {
if (!sym.AsPropertySymbol().getType().isPredefType(PredefinedType.PT_OBJECT))
return false;
Attribute[] array2 = CustomAttributeExtensions.GetCustomAttributes(sym.AsPropertySymbol().AssociatedPropertyInfo, 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) {
bool pfHideByName = false;
SearchSingleType(aggregateType2, out pfHideByName);
_flags &= (MemLookFlags)3221225471;
if ((bool)_swtFirst && !_fMulti)
return false;
if (pfHideByName) {
ptypeEnd = null;
return true;
}
if ((_flags & MemLookFlags.Ctor) != 0)
return false;
aggregateType2 = aggregateType2.GetBaseClass();
}
return true;
}
private bool LookupInInterfaces(AggregateType typeStart, TypeArray types)
{
if (typeStart != null) {
typeStart.fAllHidden = false;
typeStart.fDiffHidden = (_swtFirst != (SymWithType)null);
}
for (int i = 0; i < types.size; i++) {
AggregateType aggregateType = types.Item(i).AsAggregateType();
aggregateType.fAllHidden = false;
aggregateType.fDiffHidden = _swtFirst;
}
bool flag = false;
AggregateType aggregateType2 = typeStart;
int num = 0;
if (aggregateType2 == null)
aggregateType2 = types.Item(num++).AsAggregateType();
while (true) {
bool pfHideByName = false;
if (!aggregateType2.fAllHidden && SearchSingleType(aggregateType2, out pfHideByName)) {
pfHideByName |= !_fMulti;
TypeArray ifacesAll = aggregateType2.GetIfacesAll();
for (int j = 0; j < ifacesAll.size; j++) {
AggregateType aggregateType3 = ifacesAll.Item(j).AsAggregateType();
if (pfHideByName)
aggregateType3.fAllHidden = true;
aggregateType3.fDiffHidden = true;
}
if (pfHideByName)
flag = true;
}
_flags &= (MemLookFlags)3221225471;
if (num >= types.size)
break;
aggregateType2 = types.Item(num++).AsAggregateType();
}
return !flag;
}
private SymbolLoader GetSymbolLoader()
{
return _pSymbolLoader;
}
private CSemanticChecker GetSemanticChecker()
{
return _pSemanticChecker;
}
private ErrorHandling GetErrorContext()
{
return GetSymbolLoader().GetErrorContext();
}
private void ReportBogus(SymWithType swt)
{
switch (swt.Sym.getKind()) {
case SYMKIND.SK_PropertySymbol:
if (swt.Prop().useMethInstead) {
MethodSymbol methGet = swt.Prop().methGet;
MethodSymbol methSet = swt.Prop().methSet;
ReportBogusForEventsAndProperties(swt, methGet, methSet);
return;
}
break;
case SYMKIND.SK_MethodSymbol:
if (swt.Meth().name == GetSymbolLoader().GetNameManager().GetPredefName(PredefinedName.PN_INVOKE) && swt.Meth().getClass().IsDelegate())
swt.Set(swt.Meth().getClass(), swt.GetType());
break;
}
GetErrorContext().ErrorRef(ErrorCode.ERR_BindToBogus, swt);
}
private void ReportBogusForEventsAndProperties(SymWithType swt, MethodSymbol meth1, MethodSymbol meth2)
{
if (meth1 != null && meth2 != null)
GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()), new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym));
else {
if (meth1 == null && meth2 == null)
throw Error.InternalCompilerError();
GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType((meth1 != null) ? meth1 : meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym));
}
}
private bool IsDelegateType(CType pSrcType, AggregateType pAggType)
{
CType cType = GetSymbolLoader().GetTypeManager().SubstType(pSrcType, pAggType, pAggType.GetTypeArgsAll());
return cType.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();
_swtAmbigWarn = new SymWithType();
_swtOverride = new SymWithType();
}
public bool Lookup(CSemanticChecker checker, CType typeSrc, EXPR obj, ParentSymbol symWhere, Name name, int arity, MemLookFlags flags)
{
_prgtype = _rgtypeStart;
_pSemanticChecker = checker;
_pSymbolLoader = checker.GetSymbolLoader();
_typeSrc = typeSrc;
_obj = ((obj != null && !obj.isCLASS()) ? obj : null);
_symWhere = symWhere;
_name = name;
_arity = arity;
_flags = flags;
if ((_flags & MemLookFlags.BaseCall) != 0)
_typeQual = null;
else if ((_flags & MemLookFlags.Ctor) != 0) {
_typeQual = _typeSrc;
} else if (obj != null) {
_typeQual = obj.type;
} else {
_typeQual = null;
}
AggregateType aggregateType = null;
AggregateType aggregateType2 = null;
TypeArray typeArray = BSYMMGR.EmptyTypeArray();
AggregateType ptypeEnd = null;
if (typeSrc.IsTypeParameterType()) {
_flags &= (MemLookFlags)3221225471;
typeArray = typeSrc.AsTypeParameterType().GetInterfaceBounds();
aggregateType = typeSrc.AsTypeParameterType().GetEffectiveBaseClass();
if (typeArray.size > 0 && aggregateType.isPredefType(PredefinedType.PT_OBJECT))
aggregateType = null;
} else if (!typeSrc.isInterfaceType()) {
aggregateType = typeSrc.AsAggregateType();
if (aggregateType.IsWindowsRuntimeType())
typeArray = aggregateType.GetWinRTCollectionIfacesAll(GetSymbolLoader());
} else {
aggregateType2 = typeSrc.AsAggregateType();
typeArray = aggregateType2.GetIfacesAll();
}
if (aggregateType2 != null || typeArray.size > 0)
ptypeEnd = GetSymbolLoader().GetReqPredefType(PredefinedType.PT_OBJECT);
if ((aggregateType == null || LookupInClass(aggregateType, ref ptypeEnd)) && (aggregateType2 != null || typeArray.size > 0) && LookupInInterfaces(aggregateType2, typeArray) && ptypeEnd != null) {
AggregateType ptypeEnd2 = null;
LookupInClass(ptypeEnd, ref ptypeEnd2);
}
_results = new CMemberLookupResults(GetAllTypes(), _name);
return !FError();
}
public CMemberLookupResults GetResults()
{
return _results;
}
public bool FError()
{
if ((bool)_swtFirst)
return _swtAmbig;
return true;
}
public Symbol SymFirst()
{
return _swtFirst.Sym;
}
public SymWithType SwtFirst()
{
return _swtFirst;
}
public SymWithType SwtInaccessible()
{
return _swtInaccess;
}
public EXPR GetObject()
{
return _obj;
}
public CType GetSourceType()
{
return _typeSrc;
}
public MemLookFlags GetFlags()
{
return _flags;
}
public TypeArray GetAllTypes()
{
return GetSymbolLoader().getBSymmgr().AllocParams(_prgtype.Count, _prgtype.ToArray());
}
public void ReportErrors()
{
if ((bool)_swtFirst)
GetErrorContext().ErrorRef(ErrorCode.ERR_AmbigMember, _swtFirst, _swtAmbig);
else if ((bool)_swtInaccess) {
if (!_swtInaccess.Sym.isUserCallable() && (_flags & MemLookFlags.UserCallable) != 0)
GetErrorContext().Error(ErrorCode.ERR_CantCallSpecialMethod, _swtInaccess);
else
GetSemanticChecker().ReportAccessError(_swtInaccess, _symWhere, _typeQual);
} else if ((_flags & MemLookFlags.Ctor) != 0) {
if (_arity > 0)
GetErrorContext().Error(ErrorCode.ERR_BadCtorArgCount, _typeSrc.getAggregate(), _arity);
else
GetErrorContext().Error(ErrorCode.ERR_NoConstructors, _typeSrc.getAggregate());
} else if ((_flags & MemLookFlags.Operator) != 0) {
GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name);
} else if ((_flags & MemLookFlags.Indexer) != 0) {
GetErrorContext().Error(ErrorCode.ERR_BadIndexLHS, _typeSrc);
} else if ((bool)_swtBad) {
GetErrorContext().Error(((_flags & MemLookFlags.MustBeInvocable) != 0) ? ErrorCode.ERR_NonInvocableMemberCalled : ErrorCode.ERR_CantCallSpecialMethod, _swtBad);
} else if ((bool)_swtBogus) {
ReportBogus(_swtBogus);
} else if ((bool)_swtBadArity) {
switch (_swtBadArity.Sym.getKind()) {
case SYMKIND.SK_MethodSymbol: {
int size = _swtBadArity.Sym.AsMethodSymbol().typeVars.size;
GetErrorContext().ErrorRef((size > 0) ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), size);
break;
}
case SYMKIND.SK_AggregateSymbol: {
int size = _swtBadArity.Sym.AsAggregateSymbol().GetTypeVars().size;
GetErrorContext().ErrorRef((size > 0) ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), size);
break;
}
default:
ExpressionBinder.ReportTypeArgsNotAllowedError(GetSymbolLoader(), _arity, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym));
break;
}
} else if (((int)_flags & -2147483648) != 0) {
GetErrorContext().Error(ErrorCode.ERR_NoSuchMemberOrExtension, _typeSrc, _name);
} else {
GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name);
}
}
}
}