diff --git a/exhale/graph.py b/exhale/graph.py index 174e3b24..9e2b7cc9 100644 --- a/exhale/graph.py +++ b/exhale/graph.py @@ -199,6 +199,9 @@ def __init__(self, name, kind, refid): self.parameters = [] # list of strings: ["int", "int"] for foo(int x, int y) self.template = None # list of strings + if self.kind == "concept": + self.template = None # list of strings + def __lt__(self, other): ''' The ``ExhaleRoot`` class stores a bunch of lists of ``ExhaleNode`` objects. @@ -296,8 +299,13 @@ def full_signature(self): name=self.name, parameters=", ".join(self.parameters) ) + if self.kind == "concept": + return "{template} {name}".format( + template="template <{0}> ".format(", ".join(self.template)) if self.template is not None else "", + name=self.name) + raise RuntimeError( - "full_signature may only be called for a 'function', but {name} is a '{kind}' node.".format( + "full_signature may only be called for a 'function' or 'concept', but {name} is a '{kind}' node.".format( name=self.name, kind=self.kind ) ) @@ -995,6 +1003,9 @@ class ExhaleRoot(object): ExhaleNode it came from. Storing it this way is convenient for when the Doxygen xml file is being parsed. + ``concepts`` (list) + The full list of ExhaleNodes of kind ``concept`` + ``class_like`` (list) The full list of ExhaleNodes of kind ``struct`` or ``class`` @@ -1071,6 +1082,8 @@ def __init__(self): # doxygenindex <-+-> IGNORE | # autodoxygenindex <-+-> IGNORE | # -------------------+----------------+ + # doxygenconcept <-+-> "concept" | + self.concepts = [] # | # doxygenclass <-+-> "class" | # doxygenstruct <-+-> "struct" | self.class_like = [] # | @@ -1655,6 +1668,8 @@ def trackNodeIfUnseen(self, node): node.set_owner(self) self.all_nodes.append(node) self.node_by_refid[node.refid] = node + if node.kind == "concept": + self.concepts.append(node) if node.kind == "class" or node.kind == "struct": self.class_like.append(node) elif node.kind == "namespace": @@ -2200,6 +2215,7 @@ def sortInternals(self): # have each node sort its children # leaf-like lists: no child sort self.defines.sort() + self.concepts.sort() self.enums.sort() self.enum_values.sort() self.functions.sort() @@ -3009,6 +3025,7 @@ def generateNamespaceChildrenString(self, nspace): # sort the children nsp_namespaces = [] nsp_nested_class_like = [] + nsp_concepts = [] nsp_enums = [] nsp_functions = [] nsp_typedefs = [] @@ -3029,6 +3046,8 @@ def generateNamespaceChildrenString(self, nspace): child.findNestedClassLike(nsp_nested_class_like) child.findNestedEnums(nsp_enums) child.findNestedUnions(nsp_unions) + elif child.kind == "concept": + nsp_concepts.append(child) elif child.kind == "enum": nsp_enums.append(child) elif child.kind == "function": @@ -3043,6 +3062,7 @@ def generateNamespaceChildrenString(self, nspace): # generate their headings if they exist (no Defines...that's not a C++ thing...) children_stream = StringIO() self.generateSortedChildListString(children_stream, "Namespaces", nsp_namespaces) + self.generateSortedChildListString(children_stream, "Concepts", nsp_concepts) self.generateSortedChildListString(children_stream, "Classes", nsp_nested_class_like) self.generateSortedChildListString(children_stream, "Enums", nsp_enums) self.generateSortedChildListString(children_stream, "Functions", nsp_functions) @@ -3255,6 +3275,7 @@ def generateFileNodeDocuments(self): # generate their headings if they exist --- DO NOT USE findNested*, these are included recursively file_structs = [] + file_concepts = [] file_classes = [] file_enums = [] file_functions = [] @@ -3265,6 +3286,8 @@ def generateFileNodeDocuments(self): for child in f.children: if child.kind == "struct": file_structs.append(child) + elif child.kind == "concept": + file_concepts.append(child) elif child.kind == "class": file_classes.append(child) elif child.kind == "enum": @@ -3283,6 +3306,7 @@ def generateFileNodeDocuments(self): # generate the listing of children referenced to from this file children_stream = StringIO() self.generateSortedChildListString(children_stream, "Namespaces", f.namespaces_used) + self.generateSortedChildListString(children_stream, "Concepts", file_concepts) self.generateSortedChildListString(children_stream, "Classes", file_structs + file_classes) self.generateSortedChildListString(children_stream, "Enums", file_enums) self.generateSortedChildListString(children_stream, "Functions", file_functions) @@ -3936,6 +3960,7 @@ class view hierarchy. It will be present in the file page it was declared in Currently, the API is generated in the following (somewhat arbitrary) order: - Namespaces + - Concepts - Classes and Structs - Enums - Unions @@ -4013,6 +4038,7 @@ def __len__(self): dump_order = [ ("Namespaces", "namespace"), + ("Concepts", "concept"), ("Classes and Structs", "class"), # NOTE: class/struct stored together! ("Enums", "enum"), ("Unions", "union"), @@ -4105,6 +4131,7 @@ def toConsole(self): console. Unused in the release, but is helpful for debugging ;) ''' fmt_spec = { + "concept": utils.AnsiColors.BOLD_MAGENTA, "class": utils.AnsiColors.BOLD_MAGENTA, "struct": utils.AnsiColors.BOLD_CYAN, "define": utils.AnsiColors.BOLD_YELLOW, @@ -4123,6 +4150,7 @@ def toConsole(self): self.consoleFormat( "{0} and {1}".format( + utils._use_color("Concepts", fmt_spec["concept"], sys.stderr), utils._use_color("Classes", fmt_spec["class"], sys.stderr), utils._use_color("Structs", fmt_spec["struct"], sys.stderr), ), diff --git a/exhale/utils.py b/exhale/utils.py index 88d344e2..7e8165c7 100644 --- a/exhale/utils.py +++ b/exhale/utils.py @@ -102,6 +102,7 @@ def get_time(): AVAILABLE_KINDS = [ + "concept", "class", "define", "dir", @@ -127,6 +128,7 @@ def get_time(): "define", "enum", "function", + "concept", "class", "struct", "typedef", @@ -401,6 +403,8 @@ def qualifyKind(kind): +=============+==================+ | "class" | "Class" | +-------------+------------------+ + | "concept" | "Concept" | + +-------------+------------------+ | "define" | "Define" | +-------------+------------------+ | "enum" | "Enum" | @@ -456,6 +460,8 @@ def kindAsBreatheDirective(kind): +-------------+--------------------+ | Input Kind | Output Directive | +=============+====================+ + | "concept" | "doxygenconcept" | + +-------------+--------------------+ | "class" | "doxygenclass" | +-------------+--------------------+ | "define" | "doxygendefine" |