public void AddChildren(APIRecord Record) { foreach (APIRecord DerivedRecord in Record.DerivedRecords) { APIHierarchyNode DerivedNode = new APIHierarchyNode(DerivedRecord.FullName, DerivedRecord.LinkPath, true); Children.Add(DerivedNode); DerivedNode.AddChildren(DerivedRecord); } }
public static bool CreateParametersStruct(APIPage Parent, List <APIMember> Children, DoxygenEntity Entity) { string Name = Entity.Name; int ClassMaxIdx = Name.IndexOf("_event"); if (ClassMaxIdx == -1) { return(false); } string ClassName = Name.Substring(0, ClassMaxIdx); APIRecord ClassRecord = Children.OfType <APIRecord>().FirstOrDefault(x => x.Name.EndsWith(ClassName) && x.Name.Length == ClassName.Length + 1); if (ClassRecord == null) { return(false); } if (!Name.EndsWith("_Parms")) { return(false); } int MemberMinIdx = ClassMaxIdx + 6; int MemberMaxIdx = Name.Length - 6; string MemberName = Name.Substring(MemberMinIdx, MemberMaxIdx - MemberMinIdx); APIRecord Delegate = Children.OfType <APIRecord>().FirstOrDefault(x => x.Name == "F" + MemberName); if (Delegate != null) { Delegate.DelegateEventParameters = new APIEventParameters(Parent, Delegate, Entity); Children.Add(Delegate.DelegateEventParameters); return(true); } APIFunction Function = ClassRecord.Children.OfType <APIFunction>().FirstOrDefault(x => x.Name == MemberName); if (Function != null) { Function.EventParameters = new APIEventParameters(Parent, Function, Entity); Children.Add(Function.EventParameters); return(true); } return(false); }
public static List<APIMember> CreateChildren(APIPage Parent, IEnumerable<DoxygenEntity> Entities) { List<APIMember> Children = new List<APIMember>(); Dictionary<APIFunctionKey, List<DoxygenEntity>> PendingFunctionGroups = new Dictionary<APIFunctionKey, List<DoxygenEntity>>(); // List of autogenerated structs List<DoxygenEntity> GeneratedEntities = new List<DoxygenEntity>(); // Parse the entities foreach (DoxygenEntity Entity in Entities) { if (Entity.Kind == "class" || Entity.Kind == "struct" || Entity.Kind == "union") { if (Entity.Kind == "struct" && Entity.Name.Contains("_event") && Entity.Name.EndsWith("_Parms")) { GeneratedEntities.Add(Entity); } else { APIRecord Record = new APIRecord(Parent, Entity); Record.Children.AddRange(CreateChildren(Record, Entity.Members)); Children.Add(Record); } } else if (Entity.Kind == "function") { APIFunctionKey FunctionKey = APIFunctionKey.FromEntity(Parent, Entity); if (!Program.IgnoredFunctionMacros.Contains(FunctionKey.Name)) { List<DoxygenEntity> EntityList; if (!PendingFunctionGroups.TryGetValue(FunctionKey, out EntityList)) { EntityList = new List<DoxygenEntity>(); PendingFunctionGroups.Add(FunctionKey, EntityList); } EntityList.Add(Entity); } } else if (Entity.Kind == "variable") { if (IsConstantVariable(Entity)) { Children.Add(new APIConstantVariable(Parent, Entity)); } else { Children.Add(new APIVariable(Parent, Entity.Node)); } } else if (Entity.Kind == "typedef") { Children.Add(new APITypeDef(Parent, Entity.Node)); } else if (Entity.Kind == "enum") { if (Entity.Name != null && Entity.Name.StartsWith("@")) { // It's an enum constant Children.AddRange(APIConstantEnum.Read(Parent, Entity)); } else { // It's an enum Children.Add(new APIEnum(Parent, Entity, Entity.Name)); } } } // Fixup the functions foreach (KeyValuePair<APIFunctionKey, List<DoxygenEntity>> PendingFunctionGroup in PendingFunctionGroups) { if (PendingFunctionGroup.Value.Count == 1) { APIFunction Function = new APIFunction(Parent, PendingFunctionGroup.Value[0], PendingFunctionGroup.Key); Children.Add(Function); } else { APIFunctionGroup FunctionGroup = new APIFunctionGroup(Parent, PendingFunctionGroup.Key, PendingFunctionGroup.Value); Children.Add(FunctionGroup); } } // Attach all the autogenerated structures to their parent functions foreach(DoxygenEntity Entity in GeneratedEntities) { if(!CreateParametersStruct(Parent, Children, Entity)) { APIRecord Record = new APIRecord(Parent, Entity); Record.Children.AddRange(CreateChildren(Record, Entity.Members)); Children.Add(Record); } } // Sort the children by name Children.Sort((x, y) => String.Compare(x.Name, y.Name)); return Children; }
public static List <APIMember> CreateChildren(APIPage Parent, IEnumerable <DoxygenEntity> Entities) { List <APIMember> Children = new List <APIMember>(); Dictionary <APIFunctionKey, List <DoxygenEntity> > PendingFunctionGroups = new Dictionary <APIFunctionKey, List <DoxygenEntity> >(); // List of autogenerated structs List <DoxygenEntity> GeneratedEntities = new List <DoxygenEntity>(); // Parse the entities foreach (DoxygenEntity Entity in Entities) { if (Entity.Kind == "class" || Entity.Kind == "struct" || Entity.Kind == "union") { if (Entity.Kind == "struct" && Entity.Name.Contains("_event") && Entity.Name.EndsWith("_Parms")) { GeneratedEntities.Add(Entity); } else { APIRecord Record = new APIRecord(Parent, Entity); Record.Children.AddRange(CreateChildren(Record, Entity.Members)); Children.Add(Record); } } else if (Entity.Kind == "function") { APIFunctionKey FunctionKey = APIFunctionKey.FromEntity(Parent, Entity); if (!Program.IgnoredFunctionMacros.Contains(FunctionKey.Name)) { List <DoxygenEntity> EntityList; if (!PendingFunctionGroups.TryGetValue(FunctionKey, out EntityList)) { EntityList = new List <DoxygenEntity>(); PendingFunctionGroups.Add(FunctionKey, EntityList); } EntityList.Add(Entity); } } else if (Entity.Kind == "variable") { if (IsConstantVariable(Entity)) { Children.Add(new APIConstantVariable(Parent, Entity)); } else { Children.Add(new APIVariable(Parent, Entity.Node)); } } else if (Entity.Kind == "typedef") { Children.Add(new APITypeDef(Parent, Entity)); } else if (Entity.Kind == "enum") { if (Entity.Name != null && Entity.Name.StartsWith("@")) { // It's an enum constant Children.AddRange(APIConstantEnum.Read(Parent, Entity)); } else { // It's an enum Children.Add(new APIEnum(Parent, Entity, Entity.Name)); } } } // Fixup the functions foreach (KeyValuePair <APIFunctionKey, List <DoxygenEntity> > PendingFunctionGroup in PendingFunctionGroups) { if (PendingFunctionGroup.Value.Count == 1) { APIFunction Function = new APIFunction(Parent, PendingFunctionGroup.Value[0], PendingFunctionGroup.Key); Children.Add(Function); } else { APIFunctionGroup FunctionGroup = new APIFunctionGroup(Parent, PendingFunctionGroup.Key, PendingFunctionGroup.Value); Children.Add(FunctionGroup); } } // Attach all the autogenerated structures to their parent functions foreach (DoxygenEntity Entity in GeneratedEntities) { if (!CreateParametersStruct(Parent, Children, Entity)) { APIRecord Record = new APIRecord(Parent, Entity); Record.Children.AddRange(CreateChildren(Record, Entity.Members)); Children.Add(Record); } } // Sort the children by name Children.Sort((x, y) => String.Compare(x.Name, y.Name)); return(Children); }
public override void Link() { // Get the description ParseBriefAndFullDescription(Node, out BriefDescription, out FullDescription); // Try to link autogenerated exec functions to their original implementation if (Utility.IsNullOrWhitespace(BriefDescription) && Utility.IsNullOrWhitespace(FullDescription) && Name.Length >= 5 && Name.StartsWith("exec") && Char.IsUpper(Name[4])) { APIRecord ParentRecord = Parent as APIRecord; if (ParentRecord != null) { APIMember TargetMember = ParentRecord.Children.OfType <APIFunction>().FirstOrDefault(x => x.Name == Name.Substring(4)); if (TargetMember == null) { TargetMember = ParentRecord.Children.OfType <APIFunctionGroup>().FirstOrDefault(x => x.Name == Name.Substring(4)); } if (TargetMember != null) { BriefDescription = String.Format("Wrapper for [{0}]({1}).", TargetMember.Name, TargetMember.LinkPath); } } } // Get the @see directives ParseSeeAlso(Node, SeeAlso); string RealKeyName = (Entity.Parent != null) ? (Entity.Parent.Name + "::" + Entity.Name) : Entity.Name; SnippetText = APISnippets.LoadSnippetTextForSymbol(RealKeyName); // Get the modifiers IsVirtual = Node.Attributes.GetNamedItem("virt").InnerText == "virtual"; IsStatic = Node.Attributes.GetNamedItem("static").InnerText == "yes"; // Get the metadata MetadataDirective = MetadataCache.FindMetadataForMember(Node, "UFUNCTION"); // Get the template parameters TemplateSignature = ParseTemplateSignature(Node); // If it's a specialization, add it to the parent class if (bIsTemplateSpecialization) { int StripIdx = FullName.LastIndexOf('<'); if (StripIdx != -1) { APIFunction OriginalTemplateFunction; if (TemplateFunctions.TryGetValue(FullName.Substring(0, StripIdx), out OriginalTemplateFunction)) { OriginalTemplateFunction.TemplateSpecializations.Add(this); } } } // Get the parameter declaration nodes XmlNodeList ParameterNodes = Node.SelectNodes("param"); foreach (XmlNode ParameterNode in ParameterNodes) { Parameters.Add(new APIFunctionParam(this, ParameterNode)); } // If the only parameter is "void", don't bother including it if (Parameters.Count == 1 && Parameters[0].Node.SelectSingleNode("type").InnerText == "void") { Parameters.Clear(); } // Get the parameter description nodes XmlNodeList ParameterItemNodes = Node.SelectNodes("detaileddescription/para/parameterlist/parameteritem"); foreach (XmlNode ParameterItemNode in ParameterItemNodes) { ParameterSummaries.Add(new APIFunctionParamSummary(this, ParameterItemNode)); } // Get the return type XmlNode ReturnTypeNode = Node.SelectSingleNode("type"); ReturnType = RemoveElaborations(ConvertToMarkdown(ReturnTypeNode)); // Parse the reimplements list using (XmlNodeList ReimplementsList = Node.SelectNodes("reimplements")) { foreach (XmlNode ReimplementsNode in ReimplementsList) { APIFunction Function = ResolveRefLink(ReimplementsNode.Attributes["refid"].Value) as APIFunction; if (Function != null) { Reimplements.Add(Function); } } } // Parse the reimplemented-by list using (XmlNodeList ReimplementedByList = Node.SelectNodes("reimplementedby")) { foreach (XmlNode ReimplementedByNode in ReimplementedByList) { APIFunction Function = ResolveRefLink(ReimplementedByNode.Attributes["refid"].Value) as APIFunction; if (Function != null) { ReimplementedBy.Add(Function); } } } // Parse any other notes XmlNodeList SimpleNodes = Node.SelectNodes("detaileddescription/para/simplesect"); foreach (XmlNode node in SimpleNodes) { switch (node.Attributes.GetNamedItem("kind").InnerText) { case "return": ReturnDescription = ConvertToMarkdown(node.SelectSingleNode("para")); break; case "warning": Warnings.Add(ConvertToMarkdown(node.SelectSingleNode("para")).TrimStart(':')); break; } } // Parse the source lines /* * XmlNode LocationNode = Node.SelectSingleNode("location"); * if(LocationNode != null) * { * XmlAttribute BodyFileAttribute = LocationNode.Attributes["bodyfile"]; * if(BodyFileAttribute != null) * { * string BodyFile = BodyFileAttribute.Value; * if(!BodyFile.ToLowerInvariant().Split('\\', '/').Any(x => Program.ExcludeSourceDirectoriesHash.Contains(x))) * { * SourceFile File = SourceFileCache.Read(BodyFile); * if (File != null) * { * int BodyStart = Math.Min(Math.Max(Int32.Parse(LocationNode.Attributes["bodystart"].Value) - 1, 0), File.LineOffsets.Length - 1); * int BodyStartOffset = File.LineOffsets[BodyStart]; * * int BodyEnd = Math.Min(Int32.Parse(LocationNode.Attributes["bodyend"].Value), File.LineOffsets.Length - 1); * int BodyEndOffset = File.LineOffsets[BodyEnd]; * * SourceLines = File.Text.Substring(BodyStartOffset, BodyEndOffset - BodyStartOffset).Split('\n'); * } * } * } * } */ }
public APIHierarchyNode AddRoot(APIRecord Record) { // Try to find the "primary" path to a root object; ignoring interfaces and non-UObject base classes List <APIRecord> PrimaryHierarchy = new List <APIRecord>(); for (APIRecord ParentRecord = Record; ParentRecord != null;) { // Add the current record PrimaryHierarchy.Add(ParentRecord); // Try to find a UObject base class List <APIRecord> Candidates = new List <APIRecord>(); foreach (KeyValuePair <XmlNode, APIRecord> BaseRecord in ParentRecord.BaseRecords) { if (BaseRecord.Key.InnerText.StartsWith("U") || BaseRecord.Key.InnerText.StartsWith("A")) { Candidates.Add(BaseRecord.Value); } } // If we didn't get one, add everything else if (Candidates.Count == 0) { foreach (KeyValuePair <XmlNode, APIRecord> BaseRecord in ParentRecord.BaseRecords) { Candidates.Add(BaseRecord.Value); } } // Move to the next record ParentRecord = (Candidates.Count == 1) ? Candidates[0] : null; } // Create the hidden root node of the hierarchy APIHierarchyNode NextNode = this; // Show the list from root; show a flat list of base classes for the last record if (PrimaryHierarchy.Last().BaseRecords.Count > 0) { foreach (KeyValuePair <XmlNode, APIRecord> BaseRecord in PrimaryHierarchy.Last().BaseRecords) { if (BaseRecord.Value == null) { NextNode.Children.Add(new APIHierarchyNode(BaseRecord.Key.InnerText, false)); } else { NextNode.Children.Add(new APIHierarchyNode(BaseRecord.Value.FullName, BaseRecord.Value.LinkPath, false)); } } NextNode = NextNode.Children.Last(); } // Append the rest of the primary hierarchy for (int Idx = PrimaryHierarchy.Count - 1; Idx > 0; Idx--) { APIRecord ParentRecord = PrimaryHierarchy[Idx]; NextNode.Children.Add(new APIHierarchyNode(ParentRecord.FullName, ParentRecord.LinkPath, false)); NextNode = NextNode.Children.Last(); } // Add the current record NextNode.Children.Add(new APIHierarchyNode(Record.FullName, false)); return(NextNode.Children.Last()); }
public APIHierarchyNode AddRoot(APIRecord Record) { // Try to find the "primary" path to a root object; ignoring interfaces and non-UObject base classes List<APIRecord> PrimaryHierarchy = new List<APIRecord>(); for (APIRecord ParentRecord = Record; ParentRecord != null; ) { // Add the current record PrimaryHierarchy.Add(ParentRecord); // Try to find a UObject base class List<APIRecord> Candidates = new List<APIRecord>(); foreach (KeyValuePair<XmlNode, APIRecord> BaseRecord in ParentRecord.BaseRecords) { if (BaseRecord.Key.InnerText.StartsWith("U") || BaseRecord.Key.InnerText.StartsWith("A")) { Candidates.Add(BaseRecord.Value); } } // If we didn't get one, add everything else if (Candidates.Count == 0) { foreach (KeyValuePair<XmlNode, APIRecord> BaseRecord in ParentRecord.BaseRecords) { Candidates.Add(BaseRecord.Value); } } // Move to the next record ParentRecord = (Candidates.Count == 1) ? Candidates[0] : null; } // Create the hidden root node of the hierarchy APIHierarchyNode NextNode = this; // Show the list from root; show a flat list of base classes for the last record if (PrimaryHierarchy.Last().BaseRecords.Count > 0) { foreach (KeyValuePair<XmlNode, APIRecord> BaseRecord in PrimaryHierarchy.Last().BaseRecords) { if (BaseRecord.Value == null) { NextNode.Children.Add(new APIHierarchyNode(BaseRecord.Key.InnerText, false)); } else { NextNode.Children.Add(new APIHierarchyNode(BaseRecord.Value.FullName, BaseRecord.Value.LinkPath, false)); } } NextNode = NextNode.Children.Last(); } // Append the rest of the primary hierarchy for (int Idx = PrimaryHierarchy.Count - 1; Idx > 0; Idx--) { APIRecord ParentRecord = PrimaryHierarchy[Idx]; NextNode.Children.Add(new APIHierarchyNode(ParentRecord.FullName, ParentRecord.LinkPath, false)); NextNode = NextNode.Children.Last(); } // Add the current record NextNode.Children.Add(new APIHierarchyNode(Record.FullName, false)); return NextNode.Children.Last(); }