public MethodSpec CreateMethod(MethodBase mb, TypeSpec declaringType)
{
Modifiers mod = ReadMethodModifiers (mb, declaringType);
TypeParameterSpec[] tparams;
var parameters = CreateParameters (declaringType, mb.GetParameters (), mb);
if (mb.IsGenericMethod) {
if (!mb.IsGenericMethodDefinition)
throw new NotSupportedException ("assert");
tparams = CreateGenericParameters (0, mb.GetGenericArguments ());
} else {
tparams = null;
}
MemberKind kind;
TypeSpec returnType;
if (mb.MemberType == MemberTypes.Constructor) {
kind = MemberKind.Constructor;
returnType = TypeManager.void_type;
} else {
//
// Detect operators and destructors
//
string name = mb.Name;
kind = MemberKind.Method;
if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) {
if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) {
if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') {
var op_type = Operator.GetType (name);
if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) {
kind = MemberKind.Operator;
}
}
} else if (parameters.IsEmpty && name == Destructor.MetadataName) {
kind = MemberKind.Destructor;
if (declaringType == TypeManager.object_type) {
mod &= ~Modifiers.OVERRIDE;
mod |= Modifiers.VIRTUAL;
}
}
}
var mi = (MethodInfo) mb;
returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter));
// Cannot set to OVERRIDE without full hierarchy checks
// this flag indicates that the method could be override
// but further validation is needed
if ((mod & Modifiers.OVERRIDE) != 0 && kind == MemberKind.Method && declaringType.BaseType != null) {
var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null);
var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None);
//
// For imported class method do additional validation to be sure that metadata
// override flag was correct
//
// Difference between protected internal and protected is ok
//
const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL;
if (candidate == null || (candidate.Modifiers & conflict_mask) != (mod & conflict_mask) || candidate.IsStatic) {
mod &= ~Modifiers.OVERRIDE;
mod |= Modifiers.VIRTUAL;
}
}
}
IMemberDefinition definition;
if (tparams != null) {
var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this);
foreach (var tp in gmd.TypeParameters) {
ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ());
}
definition = gmd;
} else {
definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this);
}
MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod);
if (tparams != null)
ms.IsGeneric = true;
return ms;
}