def _process_method(self, c: Cursor, class_, store_global: bool): func = Method( parent=class_, name=c.spelling, location=location_from_cursor(c), ret_type=c.result_type.spelling, access=c.access_specifier.name.lower(), is_virtual=c.is_virtual_method(), is_pure_virtual=c.is_pure_virtual_method(), is_static=c.is_static_method(), brief_comment=c.brief_comment, ) for ac in c.get_arguments(): arg = self._process_variable(ac, class_, warn_failed=False, store_global=store_global) func.args.append(arg) for ac in c.get_children(): if ac.kind == CursorKind.CXX_FINAL_ATTR: func.is_final = True elif ac.kind in METHOD_UNSUPPORTED_CURSORS: pass else: logger.warning( "unknown kind in cxx_method child: %s %s", ac.kind, ac.extent, ) if store_global: self.objects[func.full_name] = func return func
def _parse_literal_cursor(self, c: Cursor, warn_failed: bool = False) \ -> Tuple[Optional[str], Optional[Union[str, float, int]]]: """ used to parse variable :return: literal, value """ tokens: List[Token] = list(c.get_tokens()) has_assign = False for i, t in enumerate(tokens): if has_assign: if t.kind == TokenKind.IDENTIFIER: if t.cursor.kind == CursorKind.MACRO_INSTANTIATION: return self._parse_macro_literal_cursor(c) if t.kind == TokenKind.LITERAL: spelling = t.spelling val = self._try_parse_literal(t.cursor.kind, t.spelling) last_t = tokens[i - 1] if last_t.kind == TokenKind.PUNCTUATION and last_t.spelling == '-': return spelling, -val return spelling, val elif t.spelling == '=': has_assign = True if has_assign: if warn_failed: logger.warning("unknown literal, kind:%s, spelling:%s, %s", c.kind, c.spelling, c.extent) return None, None
def _process_namespace( self, c: Cursor, n: Namespace, store_global: bool, on_progress: on_progress_type = None, ): """All result will append in parameter n""" n.location = location_from_cursor(c) self.objects[n.full_name] = n if c.kind == CursorKind.NAMESPACE and c.spelling: n.name = c.spelling children = list(c.get_children()) count = len(children) passed = False for i, ac in enumerate(children): # log cursor kind if ac.kind != CursorKind.MACRO_DEFINITION: logger.debug("%s", ac.kind) if passed or ac.spelling == 'A': passed = True print(ac.kind) # skip macros if ac.kind == CursorKind.MACRO_DEFINITION: continue self._process_namespace_child(ac, n, store_global=store_global) if on_progress: on_progress(i + 1, count) return n
def _process_enum(self, c: Cursor, parent: AnyCxxSymbol, store_global: bool): e = Enum(name=c.spelling, parent=parent, location=location_from_cursor(c), type=c.enum_type.spelling, is_strong_typed=c.is_scoped_enum(), brief_comment=c.brief_comment, ) for i in list(c.get_children()): e.variables[i.spelling] = Variable( parent=e, name=i.spelling, location=location_from_cursor(i), type=e.name, value=i.enum_value, brief_comment=c.brief_comment, ) if store_global: self.objects[e.full_name] = e return e
def _parse_macro_literal_cursor(self, c: Cursor): """ parse macro instantiation cursor. :param c: :return: """ for child in c.walk_preorder(): if self._is_literal_cursor(child): tokens = [t for t in child.get_tokens()] for t in tokens: if t.kind == TokenKind.LITERAL: return t.spelling, self._try_parse_literal(child.kind, t.spelling)
def _process_macro_definition(c: Cursor): name = c.spelling tokens = list(c.get_tokens()) length = len(tokens) m = Macro(name=name, parent=None, # macro has no parent location=location_from_cursor(c), definition="", brief_comment=c.brief_comment, ) if length == 1: return m m.definition = " ".join([i.spelling for i in tokens[1:]]) return m
def _process_class(self, c: Cursor, parent: AnyCxxSymbol, store_global: bool): # noinspection PyArgumentList name = c.spelling class_ = Class(name=name, parent=parent, location=location_from_cursor(c), brief_comment=c.brief_comment, ) for ac in c.get_children(): self._process_class_child(ac, class_, store_global=store_global) if store_global: self.objects[class_.full_name] = class_ return class_
def _process_function(self, c: Cursor, parent: Namespace, store_global: bool): func = Function( name=c.spelling, parent=parent, location=location_from_cursor(c), ret_type=c.result_type.spelling, args=[ Variable(name=ac.spelling, type=ac.type.spelling) for ac in c.get_arguments() ], brief_comment=c.brief_comment, ) if store_global: self.objects[func.full_name] = func return func
def _process_typedef(self, c: Cursor, ns: Namespace, store_global: bool): name = c.spelling target_cursor = c.underlying_typedef_type target_name: str = self._qualified_name(target_cursor) for ac in c.get_children(): kind = ac.kind if kind == CursorKind.STRUCT_DECL: class_ = self._process_class(ac, ns, store_global, name=name) return class_ # ns.classes[class_.name] = class_ elif kind in TYPEDEF_UNSUPPORTED_CURSORS: pass else: logger.warning("unknown cursor kind in typedef:%s", kind) if target_name != '::': return self.save_typedef(c, ns, name, target_name, store_global=store_global)
def _get_template_alias_target(self, c: Cursor): children = list(c.get_children()) for child in children: if child.kind == CursorKind.TYPE_ALIAS_DECL: return child.underlying_typedef_type return None
def _process_class_child(self, ac: Cursor, class_: Class, store_global: bool): if ac.kind == CursorKind.CXX_BASE_SPECIFIER: super_name = self._qualified_name(ac) if super_name in self.objects: # if parent class is a template class, it will not be parsed s = self.objects[super_name] class_.super.append(s) else: pass elif ac.kind == CursorKind.CONSTRUCTOR: func = self._process_method(ac, class_, store_global=store_global) if func.is_virtual: class_.is_polymorphic = True class_.constructors.append(func) elif (ac.kind == CursorKind.CLASS_DECL or ac.kind == CursorKind.STRUCT_DECL or ac.kind == CursorKind.CLASS_TEMPLATE or ac.kind == CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION): child = self._process_class(c=ac, parent=class_, store_global=store_global) class_.classes[child.name] = child elif ac.kind == CursorKind.UNION_DECL: # for type first scope_name = self._union_scope_name(ac) child = self._process_union(ac, scope_name, class_, store_global=True) anonymous = ac.is_anonymous() if scope_name and not anonymous: class_.classes[child.name] = child return if scope_name and anonymous: class_.classes[child.name] = child return if not scope_name and anonymous: class_.extend(child) return if not scope_name and not anonymous: class_.classes[child.name] = child class_.extend(child) return elif ac.kind == CursorKind.DESTRUCTOR: func = self._process_method(ac, class_, store_global=store_global) if func.is_virtual: class_.is_polymorphic = True class_.destructor = func elif ac.kind == CursorKind.ENUM_DECL: e = self._process_enum(ac, class_, store_global=store_global) class_.enums[e.name] = e elif ac.kind == CursorKind.FIELD_DECL: v = self._process_variable(ac, class_, store_global=store_global) class_.variables[v.name] = v elif ac.kind == CursorKind.CXX_METHOD: func = self._process_method(ac, class_, store_global=store_global) if func.is_virtual: class_.is_polymorphic = True class_.functions[func.name].append(func) elif (ac.kind == CursorKind.TYPEDEF_DECL or ac.kind == CursorKind.TYPE_ALIAS_DECL): tp = self._process_typedef(ac, class_, store_global=store_global) class_.typedefs[tp.name] = tp elif ac.kind == CursorKind.TYPE_ALIAS_TEMPLATE_DECL: tp = self._process_template_alias(ac, class_, store_global=store_global) class_.typedefs[tp.name] = tp elif ac.kind in CLASS_UNSUPPORTED_CURSORS: pass else: logger.warning( "unknown kind in class child, and not handled: %s %s", ac.kind, ac.extent, )