private EXPRMEMGRP CreateMemberGroupEXPR(
string Name,
IList<Type> typeArguments,
EXPR callingObject,
SYMKIND kind)
{
Name name = SymbolTable.GetName(Name, _semanticChecker.GetNameManager());
AggregateType callingType;
if (callingObject.type.IsArrayType())
{
callingType = _semanticChecker.GetSymbolLoader().GetReqPredefType(PredefinedType.PT_ARRAY);
}
else if (callingObject.type.IsNullableType())
{
callingType = callingObject.type.AsNullableType().GetAts(_semanticChecker.GetSymbolLoader().GetErrorContext());
}
else if (callingObject.type.IsAggregateType())
{
callingType = callingObject.type.AsAggregateType();
}
else
{
callingType = null;
Debug.Assert(false, "MemberGroup on non-array, non-aggregate");
}
List<CType> callingTypes = new List<CType>();
// The C# binder expects that only the base virtual method is inserted
// into the list of candidates, and only the type containing the base
// virtual method is inserted into the list of types. However, since we
// don't want to do all the logic, we're just going to insert every type
// that has a member of the given name, and allow the C# binder to filter
// out all overrides.
//
// Find that set of types now.
symbmask_t mask = symbmask_t.MASK_MethodSymbol;
switch (kind)
{
case SYMKIND.SK_PropertySymbol:
case SYMKIND.SK_IndexerSymbol:
mask = symbmask_t.MASK_PropertySymbol;
break;
case SYMKIND.SK_MethodSymbol:
mask = symbmask_t.MASK_MethodSymbol;
break;
default:
Debug.Assert(false, "Unhandled kind");
break;
}
// If we have a constructor, only find its type.
bool bIsConstructor = name == SymbolLoader.GetNameManager().GetPredefinedName(PredefinedName.PN_CTOR);
for (AggregateType t = callingType; t != null; t = t.GetBaseClass())
{
if (_symbolTable.AggregateContainsMethod(t.GetOwningAggregate(), Name, mask))
{
callingTypes.Add(t);
}
// If we have a constructor, run the loop once for the constructor's type, and thats it.
if (bIsConstructor)
{
break;
}
}
// If this is a WinRT type we have to add all collection interfaces that have this method
// as well so that overload resolution can find them.
if (callingType.IsWindowsRuntimeType())
{
TypeArray collectioniFaces = callingType.GetWinRTCollectionIfacesAll(SymbolLoader);
for (int i = 0; i < collectioniFaces.size; i++)
{
CType t = collectioniFaces.Item(i);
// Collection interfaces will be aggregates.
Debug.Assert(t.IsAggregateType());
if (_symbolTable.AggregateContainsMethod(t.AsAggregateType().GetOwningAggregate(), Name, mask))
{
callingTypes.Add(t);
}
}
}
EXPRFLAG flags = EXPRFLAG.EXF_USERCALLABLE;
// If its a delegate, mark that on the memgroup.
if (Name == SpecialNames.Invoke && callingObject.type.isDelegateType())
{
flags |= EXPRFLAG.EXF_DELEGATE;
}
// For a constructor, we need to seed the memgroup with the constructor flag.
if (Name == SpecialNames.Constructor)
{
flags |= EXPRFLAG.EXF_CTOR;
}
// If we have an indexer, mark that.
if (Name == SpecialNames.Indexer)
{
flags |= EXPRFLAG.EXF_INDEXER;
}
TypeArray typeArgumentsAsTypeArray = BSYMMGR.EmptyTypeArray();
if (typeArguments != null && typeArguments.Count > 0)
{
typeArgumentsAsTypeArray = _semanticChecker.getBSymmgr().AllocParams(
_symbolTable.GetCTypeArrayFromTypes(typeArguments));
}
EXPRMEMGRP memgroup = _exprFactory.CreateMemGroup(// Tree
flags, name, typeArgumentsAsTypeArray, kind, callingType, null, null, new CMemberLookupResults(
_semanticChecker.getBSymmgr().AllocParams(callingTypes.Count, callingTypes.ToArray()),
name));
if (callingObject.isCLASS())
{
memgroup.SetOptionalLHS(callingObject);
}
else
{
memgroup.SetOptionalObject(callingObject);
}
return memgroup;
}