private static MemberDocumentNode GetMemberDocumentNode(
            FunctionDescriptor function,
            XmlReader xml)
        {
            //customNodeDefinitions typedParameters don't have functionDescriptors
            if (function == null)
            {
                return(null);
            }
            var assemblyName = function.Assembly;

            if (string.IsNullOrEmpty(assemblyName))
            {
                return(null);
            }

            var fullyQualifiedName = MemberDocumentNode.MakeFullyQualifiedName
                                         (assemblyName, GetMemberElementName(function));

            if (!documentNodes.ContainsKey(fullyQualifiedName))
            {
                if (xml == null)
                {
                    xml = DocumentationServices.GetForAssembly(function.Assembly, function.PathManager);
                }
                LoadDataFromXml(xml, assemblyName);
            }

            MemberDocumentNode documentNode = null;

            if (documentNodes.ContainsKey(fullyQualifiedName))
            {
                documentNode = documentNodes[fullyQualifiedName];
            }
            else
            {
                // Note that the following may take the incorrect overload.
                // Unfortunately we can't map back to the exact .NET parameter types from the DS function descriptor.
                var overloadedName = documentNodes.Keys.
                                     Where(key => key.Contains(function.ClassName + "." + function.FunctionName)).FirstOrDefault();

                if (overloadedName == null)
                {
                    return(null);
                }
                if (documentNodes.ContainsKey(overloadedName))
                {
                    documentNode = documentNodes[overloadedName];
                }
            }

            return(documentNode);
        }
        private static void LoadDataFromXml(XmlReader reader, string assemblyName)
        {
            if (reader == null)
            {
                return;
            }

            MemberDocumentNode currentDocNode   = null;
            XmlTagType         currentTag       = XmlTagType.None;
            string             currentParamName = String.Empty;

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                case XmlNodeType.Element:
                    switch (reader.Name)
                    {
                    case "member":
                        // Find attribute "name".
                        if (reader.MoveToAttribute("name"))
                        {
                            currentDocNode = new MemberDocumentNode(assemblyName, reader.Value);
                            documentNodes.Add(currentDocNode.FullyQualifiedName, currentDocNode);
                        }
                        currentTag = XmlTagType.Member;
                        break;

                    case "summary":
                        currentTag = XmlTagType.Summary;
                        break;

                    case "param":
                        if (reader.MoveToAttribute("name"))
                        {
                            currentParamName = reader.Value;
                        }
                        currentTag = XmlTagType.Parameter;
                        break;

                    case "returns":
                        if (reader.MoveToAttribute("name"))
                        {
                            currentParamName = reader.Value;
                        }
                        else
                        {
                            currentParamName = null;
                        }
                        currentTag = XmlTagType.Returns;
                        break;

                    case "search":
                        currentTag = XmlTagType.SearchTags;
                        break;

                    case "weights":
                        currentTag = XmlTagType.SearchTagWeights;
                        break;

                    default:
                        currentTag = XmlTagType.None;
                        break;
                    }
                    break;

                case XmlNodeType.Text:
                    if (currentDocNode == null)
                    {
                        continue;
                    }

                    switch (currentTag)
                    {
                    case XmlTagType.Summary:
                        currentDocNode.Summary = reader.Value.CleanUpDocString();
                        break;

                    case XmlTagType.Parameter:
                        currentDocNode.Parameters.Add(currentParamName, reader.Value.CleanUpDocString());
                        break;

                    case XmlTagType.Returns:
                        currentDocNode.Returns.Add(new Tuple <string, string>(currentParamName, reader.Value.CleanUpDocString()));
                        break;

                    case XmlTagType.SearchTags:
                        currentDocNode.SearchTags = reader.Value.CleanUpDocString();
                        break;

                    case XmlTagType.SearchTagWeights:
                        currentDocNode.SearchTagWeights = reader.Value.CleanUpDocString();
                        break;
                    }

                    break;
                }
            }
        }
        private static void LoadDataFromXml(XmlReader reader, string assemblyName)
        {
            if (reader == null)
                return;

            MemberDocumentNode currentDocNode = null;
            XmlTagType currentTag = XmlTagType.None;
            string currentParamName = String.Empty;

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                            case "member":
                                // Find attribute "name".
                                if (reader.MoveToAttribute("name"))
                                {
                                    currentDocNode = new MemberDocumentNode(assemblyName, reader.Value);
                                    documentNodes.Add(currentDocNode.FullyQualifiedName, currentDocNode);
                                }
                                currentTag = XmlTagType.Member;
                                break;

                            case "summary":
                                currentTag = XmlTagType.Summary;
                                break;

                            case "param":
                                if (reader.MoveToAttribute("name"))
                                {
                                    currentParamName = reader.Value;
                                }
                                currentTag = XmlTagType.Parameter;
                                break;

                            case "returns":
                                if (reader.MoveToAttribute("name"))
                                {
                                    currentParamName = reader.Value;
                                }
                                else
                                {
                                    currentParamName = null;
                                }
                                currentTag = XmlTagType.Returns;
                                break;

                            case "search":
                                currentTag = XmlTagType.SearchTags;
                                break;

                            case "weights":
                                currentTag = XmlTagType.SearchTagWeights;
                                break;

                            default:
                                currentTag = XmlTagType.None;
                                break;
                        }
                        break;
                    case XmlNodeType.Text:
                        if (currentDocNode == null)
                            continue;

                        switch (currentTag)
                        {
                            case XmlTagType.Summary:
                                currentDocNode.Summary = reader.Value.CleanUpDocString();
                                break;
                            case XmlTagType.Parameter:
                                currentDocNode.Parameters.Add(currentParamName, reader.Value.CleanUpDocString());
                                break;
                            case XmlTagType.Returns:
                                currentDocNode.Returns.Add(new Tuple<string,string>(currentParamName, reader.Value.CleanUpDocString()));
                                break;
                            case XmlTagType.SearchTags:
                                currentDocNode.SearchTags = reader.Value.CleanUpDocString();
                                break;
                            case XmlTagType.SearchTagWeights:
                                currentDocNode.SearchTagWeights = reader.Value.CleanUpDocString();
                                break;
                        }

                        break;
                }
            }
        }
        private static void LoadDataFromXml(XmlReader reader, string assemblyName)
        {
            if (reader == null)
            {
                return;
            }

            MemberDocumentNode currentDocNode   = null;
            XmlTagType         currentTag       = XmlTagType.None;
            string             currentParamName = String.Empty;

            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                case XmlNodeType.Element:
                    switch (reader.Name)
                    {
                    case "member":
                        // Find attribute "name".
                        if (reader.MoveToAttribute("name"))
                        {
                            currentDocNode = new MemberDocumentNode(assemblyName, reader.Value);
                            documentNodes.Add(currentDocNode.FullyQualifiedName, currentDocNode);
                        }
                        currentTag = XmlTagType.Member;
                        break;

                    case "summary":
                        currentTag = XmlTagType.Summary;
                        break;

                    case "param":
                        if (reader.MoveToAttribute("name"))
                        {
                            currentParamName = reader.Value;
                        }
                        currentTag = XmlTagType.Parameter;
                        break;

                    case "returns":
                        if (reader.MoveToAttribute("name"))
                        {
                            currentParamName = reader.Value;
                        }
                        else
                        {
                            currentParamName = null;
                        }
                        currentTag = XmlTagType.Returns;
                        break;

                    case "search":
                        currentTag = XmlTagType.SearchTags;
                        break;

                    case "weights":
                        currentTag = XmlTagType.SearchTagWeights;
                        break;

                    default:
                        currentTag = XmlTagType.None;
                        break;
                    }
                    break;

                case XmlNodeType.Text:
                    if (currentDocNode == null)
                    {
                        continue;
                    }

                    switch (currentTag)
                    {
                    case XmlTagType.Summary:
                        currentDocNode.Summary = reader.Value.CleanUpDocString();
                        break;

                    case XmlTagType.Parameter:
                        // If a tag is missing around text after <params> tag, the text can be added as a new parameter
                        // under the previous parameter name. This check avoids the resulting ArgumentException with the dictionary.
                        if (!currentDocNode.Parameters.ContainsKey(currentParamName))
                        {
                            currentDocNode.Parameters.Add(currentParamName, reader.Value.CleanUpDocString());
                        }
                        else
                        {
                            OnMissingXmlTags(
                                $"{currentDocNode.FullyQualifiedName} {Properties.Resources.MissingXmlTagConsoleMessage}");
                        }

                        break;

                    case XmlTagType.Returns:
                        currentDocNode.Returns.Add(new Tuple <string, string>(currentParamName, reader.Value.CleanUpDocString()));
                        break;

                    case XmlTagType.SearchTags:
                        currentDocNode.SearchTags = reader.Value.CleanUpDocString();
                        break;

                    case XmlTagType.SearchTagWeights:
                        currentDocNode.SearchTagWeights = reader.Value.CleanUpDocString();
                        break;
                    }

                    break;
                }
            }
        }