#! /usr/bin/env python3 import sys import os import clang.cindex from mako.template import Template def node_children(node): return (c for c in node.get_children() if c.location.file.name == filename) def get_annotations(node): return [c.displayname for c in node.get_children() if c.kind == clang.cindex.CursorKind.ANNOTATE_ATTR] class Variable(object): def __init__(self, cursor): self.name = cursor.spelling self.annotations = get_annotations(cursor) class Parameter(object): def __init__(self, cursor): self.name = cursor.spelling self.type = cursor.type.spelling class Constructor(object): def __init__(self, cursor): self.parameters = [] for c in cursor.get_children(): if c.kind == clang.cindex.CursorKind.PARM_DECL: p = Parameter(c) self.parameters.append(p) class Component(object): def __init__(self, cursor): self.name = cursor.spelling self.variables = [] self.constructors = [] for c in cursor.get_children(): if (c.kind == clang.cindex.CursorKind.CONSTRUCTOR and c.access_specifier == clang.cindex.AccessSpecifier.PUBLIC): con = Constructor(c) # if len(con.parameters) > 0: self.constructors.append(con) if (c.kind == clang.cindex.CursorKind.FIELD_DECL and c.access_specifier == clang.cindex.AccessSpecifier.PUBLIC): v = Variable(c) self.variables.append(v) def build_components(cursor, filename): result = [] for c in cursor.get_children(): if (c.kind == clang.cindex.CursorKind.STRUCT_DECL and c.location.file.name == filename): for d in c.get_children(): if (d.kind == clang.cindex.CursorKind.CXX_BASE_SPECIFIER and d.spelling == "ecs::Component"): a_class = Component(c) result.append(a_class) break elif c.kind == clang.cindex.CursorKind.NAMESPACE: child_components = build_components(c, filename) result.extend(child_components) return result def main(argv): if len(sys.argv) != 3: print("Usage: {} [header filename] [output filename]".format(argv[0])) sys.exit() filename = argv[1] output = argv[2] index = clang.cindex.Index.create() tu = index.parse(filename, ['-x', 'c++', '-std=c++20', f'-Iecs/include', f'-Ibuild/_deps/stduuid-src/include', '-I/lib/gcc/x86_64-pc-linux-gnu/11.1.0/include']) components = build_components(tu.cursor, filename) tpl = Template(filename=f'template.mako') include_file = filename.split('/')[-1] if not os.path.exists(os.path.dirname(output)): try: os.makedirs(os.path.dirname(output)) except OSError as exc: if exc.errno != errno.EEXIST: raise output_file = open(output, "w") output_file.write(tpl.render(components=components, include_file=include_file)) output_file.close() for d in tu.diagnostics: print(d) if __name__ == "__main__": main(sys.argv)