/// <summary>
        /// Builds a MethodContext object based on the given method element.
        /// </summary>
        /// <param name="methodTag">An XElement representing the method to build the context for. This can be either a function, constructor or destructor element.</param>
        /// <returns>A MethodContext object based on the given method.</returns>
        /// <exception cref="System.ArgumentException">The passed XElement does not represent a function, constructor, or destructor element.</exception>
        /// <exception cref="System.ArgumentNullException">methodTag is null.</exception>
        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);
        }