Git commit 73fc386ca303604a23bf0ef56d3e4bc7217585c9 by Shaheed Haque. Committed on 31/03/2016 at 21:37. Pushed by shaheed into branch 'srhaque-new-sip-generator'. Overhaul the implementation of typedefs. M +65 -22 sip_generation/generator.py http://commits.kde.org/pykde5/73fc386ca303604a23bf0ef56d3e4bc7217585c9 diff --git a/sip_generation/generator.py b/sip_generation/generator.py index 3f91f36..3dbb676 100755 --- a/sip_generation/generator.py +++ b/sip_generation/generator.py @@ -30,7 +30,7 @@ import subprocess import sys import traceback from clang import cindex -from clang.cindex import AccessSpecifier, CursorKind, SourceRange, Storage= Class, TokenKind +from clang.cindex import AccessSpecifier, CursorKind, SourceRange, Storage= Class, TokenKind, TypeKind = from rules import rule_set = @@ -115,7 +115,9 @@ class Generator(object): for line in f: self.unpreprocessed_source.append(line) # - # Create and populate the index. + # Create and populate the index. To run the actual compiler in pro= process-only mode: + # + # ["clang-3.9"] + includes + ["-x", "c++", "-std=3Dc++11", "-ferro= r-limit=3D0", "-D__CODE_GENERATOR__", "-E"] + [source] # includes =3D ["-I" + i for i in self.includes] index =3D cindex.Index.create() @@ -180,6 +182,7 @@ class Generator(object): CONTAINER_IS_VISIBLE_BY_ATTR =3D re.compile("_EXPORT|default") FN_IS_VISIBLE_BY_ATTR =3D re.compile("_EXPORT|default") VAR_IS_VISIBLE_BY_ATTR =3D re.compile("_EXPORT|default") + TYPEDEF_IS_VISIBLE_BY_ATTR =3D re.compile("_EXPORT") = def _container_get(self, container, level, h_file): """ @@ -286,14 +289,14 @@ class Generator(object): # There does not seem to be an obvious way to tell a class= from a struct. That should matter... # if container.kind =3D=3D CursorKind.NAMESPACE: - container_type =3D pad + "namespace" + container_type =3D pad + "namespace " + name else: - container_type =3D pad + "class" + container_type =3D pad + "struct {}".format(name or "_= _struct{}".format(container.extent.start.line)) if level =3D=3D 0: h_file =3D "%TypeHeaderCode\n#include <{}>\n%End\n".fo= rmat(h_file) else: h_file =3D "" - prefix =3D "{}{} {}{}\n{}{{\n{}".format(template_type_para= meters, container_type, name, base_specifiers, pad, h_file) + prefix =3D "{}{}{}\n{}{{\n{}".format(template_type_paramet= ers, container_type, base_specifiers, pad, h_file) if container.sip_annotations: suffix =3D "} /" + ",".join(container.sip_annotations)= + "/;\n" else: @@ -327,7 +330,7 @@ class Generator(object): = def _enum_get(self, container, enum, level): pad =3D " " * (level * 4) - decl =3D pad + "enum {} {{\n".format(enum.displayname) + decl =3D pad + "enum {} {{\n".format(enum.displayname or "__enum{}= ".format(enum.extent.start.line)) enumerations =3D [] for enum in enum.get_children(): enumerations.append(pad + " {}".format(enum.displayname)) @@ -505,25 +508,56 @@ class Generator(object): return "" = def _typedef_get(self, container, typedef, level): + def skippable_visibility_attr(member, text): + """We don't seem to have access to the __attribute__(())s, but= at least we can look for stuff we care about.""" + if text.find("_DEPRECATED") !=3D -1: + typedef.sip_annotations.add("Deprecated") + return True + if Generator.TYPEDEF_IS_VISIBLE_BY_ATTR.search(text): + return True + logger.debug(_("Ignoring {} child {}[{}]::{} {}").format(typed= ef.kind, typedef.spelling, + membe= r.extent.start.line, text, member.kind)) + + pad =3D " " * (level * 4) - alias =3D typedef.displayname - template =3D "" + setattr(typedef, "sip_annotations", set()) args =3D [] - parameters =3D [] + result_type =3D "" for child in typedef.get_children(): if child.kind =3D=3D CursorKind.TEMPLATE_REF: - template =3D child.displayname + result_type =3D child.displayname elif child.kind =3D=3D CursorKind.TYPE_REF: - args.append(child.displayname) + # + # Sigh. For results which are pointers, we dont have a way= of detecting the need for the "*". + # + result_type =3D child.type.spelling elif child.kind =3D=3D CursorKind.ENUM_DECL: - args.append(self._enum_get(container, child, level)) + if child.underlying_typedef_type: + # + # Typedefs for inlined enums seem to be emitted twice.= Refer back to original. + # + enum =3D child.type.get_declaration() + decl =3D "enum {}".format("__enum{}".format(enum.exten= t.start.line)) + else: + decl =3D self._enum_get(container, child, level) + args.append(decl) + elif child.kind =3D=3D CursorKind.STRUCT_DECL: + if child.underlying_typedef_type: + # + # Typedefs for inlined structs seem to be emitted twic= e. Refer back to original. + # + struct =3D child.type.get_declaration() + decl =3D "struct {}".format("__struct{}".format(struct= .extent.start.line)) + else: + decl =3D self._container_get(child, level, None) + args.append(decl) elif child.kind =3D=3D CursorKind.PARM_DECL: - parameter =3D child.displayname or "__{}".format(len(param= eters)) + decl =3D child.displayname or "__{}".format(len(args)) # # So far so good, but we need any default value. # - decl =3D "{} {}".format(child.type.spelling, parameter) - parameters.append(decl) + decl =3D "{} {}".format(child.type.spelling, decl) + args.append(decl) elif child.kind in EXPR_KINDS: # # Ignore: @@ -532,15 +566,24 @@ class Generator(object): # pass else: - Generator._report_ignoring(typedef, child) - if parameters: - decl =3D pad + self._read_source(typedef.extent) + ";\n" + text =3D self._read_source(child.extent) + if child.kind in [CursorKind.UNEXPOSED_ATTR, CursorKind.VI= SIBILITY_ATTR] and skippable_visibility_attr(child, text): + pass + elif child.kind =3D=3D CursorKind.UNEXPOSED_DECL and skipp= able_unexposed_decl(child, text): + pass + else: + Generator._report_ignoring(typedef, child) + alias =3D typedef.displayname + if typedef.underlying_typedef_type.kind =3D=3D TypeKind.MEMBERPOIN= TER: + decl =3D pad + "typedef {}(*{})({})".format(result_type, alias= , ", ".join(args), alias) decl =3D decl.replace("* ", "*").replace("& ", "&") - elif template: - decl =3D pad + "typedef {}<{}> {};\n".format(template, ", ".jo= in(args), alias) + elif typedef.underlying_typedef_type.kind =3D=3D TypeKind.RECORD: + decl =3D pad + "typedef {} {}".format(result_type, alias) else: - decl =3D pad + "typedef {} {};\n".format("::".join(args), alia= s) - return decl + decl =3D pad + "typedef {} {}".format(typedef.underlying_typed= ef_type.spelling, alias) + if typedef.sip_annotations: + decl +=3D " /" + ",".join(typedef.sip_annotations) + "/" + return decl + ";\n" = def _var_get(self, container, variable, level): """