private static FunctionDocIndexNode GetFunctionDocumentationNode(XmlReader xmlReader) { var functionDocumentationNode = new FunctionDocIndexNode { Name = xmlReader.GetAttribute("name"), FullName = xmlReader.GetAttribute("fullname"), Access = xmlReader.GetAttribute("access"), Location = xmlReader.GetAttribute("location"), LineNumber = int.Parse(xmlReader.GetAttribute("lineno")), HRef = xmlReader.GetAttribute("href"), IsObsolete = xmlReader.GetAttribute("status") == "obsolete" }; using (var xmlSubReader = xmlReader.ReadSubtree()) { while (xmlSubReader.Read()) { if (xmlSubReader.NodeType == XmlNodeType.Element && xmlSubReader.Name == "parameter") { functionDocumentationNode.ParametersModifiers.Add(xmlSubReader.GetAttribute("left")); } } } return(functionDocumentationNode); }
public void DocumentFunction(Function function) { var nodeKey = function.OriginalName; if (function.IsDependent && !function.IsOperator && nodeKey.Contains('<')) { nodeKey = nodeKey.Substring(0, nodeKey.IndexOf('<')); } if (!this.functionNodes.ContainsKey(nodeKey)) { return; } var lineStart = function.LineNumberStart; var lineEnd = function.LineNumberEnd; var functions = this.functionNodes[nodeKey]; var unit = function.OriginalNamespace.TranslationUnit; var location = unit.FileName; FunctionDocIndexNode node = null; var nodes = functions.FindAll( f => f.Location == location && (f.LineNumber == lineStart || f.LineNumber == lineEnd)); // incredible but we actually have a case of different functions with the same name in headers with the same name at the same line if (nodes.Count > 0) { if (nodes.Count == 1) { node = nodes[0]; } else { node = nodes.Find(n => n.FullName == function.QualifiedOriginalName); } } var @params = function.Parameters.Where(p => p.Kind == ParameterKind.Regular).ToList(); int realParamsCount = @params.Count(p => !string.IsNullOrWhiteSpace(p.OriginalName) || p.DefaultArgument == null); // functions can have different line numbers because of #defines if (node == null || node.HRef == null) { nodes = functions.FindAll( f => CheckLocation(f.Location, location) && (f.FullName == function.QualifiedOriginalName || f.Name == function.OriginalName) && f.Access != "private" && f.ParametersModifiers.Count == realParamsCount); // HACK: work around https://bugreports.qt.io/browse/QTBUG-53994 if (nodes.Count == 1) { node = nodes[0]; } else { var paramTypes = @params.Select(p => p.Type.ToString()).ToList(); node = nodes.Find( f => f.ParametersModifiers.SequenceEqual(paramTypes, new TypeInIndexEqualityComparer())); } } if (node != null && node.HRef != null) { var link = node.HRef.Split('#'); var file = link[0]; if (this.membersDocumentation.ContainsKey(file)) { var id = link[1].Split('-'); var key = EscapeId(function.IsAmbiguous && node.Access == "private" ? id[0] : link[1]); if (this.membersDocumentation[file].ContainsKey(key)) { var docs = this.membersDocumentation[file][key]; var i = 0; // HACK: work around https://bugreports.qt.io/browse/QTBUG-53941 if (function.Namespace.Name == "QByteArray" && function.OriginalName == "qCompress" && @params.Count == 2) { docs = this.membersDocumentation[file][key + "-hack"]; } foreach (Match match in regexParameters.Matches(docs[0].InnerHtml)) { // variadic and void "parameters" are invalid if (function.IsVariadic && @params.Count == i || match.Groups[1].Value == "void") { break; } var param = csharpSources.SafeIdentifier(match.Groups[1].Value); if (i >= @params.Count) { break; } @params[i].Name = param; if (function.IsDependent && function is Method && function.Namespace.IsDependent) { foreach (var specialization in ((Class)function.Namespace).Specializations) { var specializedFunction = specialization.Methods.First(m => m.InstantiatedFrom == function); specializedFunction.Parameters.Where(p => p.Kind == ParameterKind.Regular).ElementAt(i).Name = param; } } i++; } // TODO: create links in the "See Also" section function.Comment = new RawComment { BriefText = StripTags(ConstructDocumentText(docs.Skip(1))) }; if (node.IsObsolete) { AddObsoleteAttribute(function); } var @event = function.Namespace.Events.FirstOrDefault(e => e.OriginalDeclaration == function); if (@event != null) { for (i = 0; i < function.Parameters.Count; i++) { @event.Parameters[i].Name = function.Parameters[i].Name; } } } } } }