public static MethodContext BuildMethodContext(XElement methodTag)
{
if (methodTag == null)
{
throw new ArgumentNullException("methodTag");
}
else if (!(methodTag.Name == SRC.Function || methodTag.Name == SRC.Constructor || methodTag.Name == SRC.Destructor))
{
throw new ArgumentException(string.Format("The passed XElement must represent a <function>, <constructor> or <destructor> element. Received a <{0}> element.", methodTag.Name.ToString()), "methodTag");
}
MethodContext mc = new MethodContext();
//set return type
if (methodTag.Name == SRC.Function)
{
bool isPrimitive;
mc.IdType = ConstructTypeName(methodTag.Element(SRC.Type), out isPrimitive);
mc.IdTypeIsPrimitive = isPrimitive;
}
//record if constructor
if (methodTag.Name == SRC.Constructor) { mc.IsConstructor = true; }
//record if destructor
if (methodTag.Name == SRC.Destructor) { mc.IsDestructor = true; }
//record if static
//look for the static keyword (at the function definition)
//This is not entirely sufficient because it's possible for the static keyword to be present at only the function declaration and not the definition
//Also, some other word may be #defined to static and used instead
var typeElement = methodTag.Element(SRC.Type);
if (typeElement != null)
{
foreach (var typeNameTag in typeElement.Elements(SRC.Name))
{
if (typeNameTag.Value.Equals("static", StringComparison.InvariantCultureIgnoreCase))
{
mc.IsStatic = true;
break;
}
}
}
//formal parameters
mc.FormalParameters = new List<FormalParameterRecord>();
XElement paramList = methodTag.Element(SRC.ParameterList);
if (paramList != null)
{
foreach (var param in paramList.Elements(SRC.Parameter))
{
//a param (usually) looks like: <param><decl><type><name>...</name></type> <name>...</name></decl></param>
string type = string.Empty;
string name = string.Empty;
bool isPrimitive = false;
var declElement = param.Element(SRC.Declaration);
if (declElement != null && declElement.Element(SRC.Type) != null)
{
type = ConstructTypeName(declElement.Element(SRC.Type), out isPrimitive);
}
if (declElement != null && declElement.Element(SRC.Name) != null)
{
name = param.Element(SRC.Declaration).Element(SRC.Name).Value;
}
//add parameter, if it's valid
if(!(string.IsNullOrEmpty(type) && string.IsNullOrEmpty(name)) && type != "void")
{
mc.FormalParameters.Add(new FormalParameterRecord(type, isPrimitive, name));
}
}
}
//Determine declaring class
XElement classNameTag = SrcMLElement.GetClassNameForMethod(methodTag);
if (classNameTag != null)
{
//class name listed with method name: <ClassName>::<MethodName>
mc.DeclaringClass = classNameTag.Value;
}
else if (classNameTag == null && mc.IsConstructor)
{
//class name not listed, but the method is a constructor
//I'm not sure if this is actually possible
mc.DeclaringClass = SrcMLElement.GetNameForMethod(methodTag).Value;
}
else if (classNameTag == null)
{
//no class name listed, but this might be an inline method in the class declaration
//search for the enclosing <class> or <struct> tag
XElement classElement = FindEnclosingClassElement(methodTag);
if (classElement != null && classElement.Element(SRC.Name) != null)
{
mc.DeclaringClass = GetNameFromNameElement(classElement.Element(SRC.Name));
}
}
return mc;
}