def _process_method(self, c: Cursor, class_): 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(), ) for ac in c.get_arguments(): arg = self._process_variable(ac, class_, warn_failed=False) 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, ) self.objects[func.full_name] = func return func
def _process_enum(self, c: Cursor, parent: AnyCxxSymbol): e = Enum(name=c.spelling, parent=parent, location=location_from_cursor(c), type=c.enum_type.spelling, is_strong_typed=c.is_scoped_enum()) 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) self.objects[e.full_name] = e return e
def _process_namespace(self, c: Cursor, n: Namespace, 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) if on_progress: on_progress(i + 1, count) return n
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 _parse_macro_literal_cursor(self, c: Cursor): 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_class_child(self, ac: Cursor, class_: Class): 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_) 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.UNION_DECL or ac.kind == CursorKind.CLASS_TEMPLATE_PARTIAL_SPECIALIZATION ): if not ac.is_anonymous(): child = self._process_class(ac, class_) class_.classes[child.name] = child else: child = self._process_class(ac, class_, store_global=False) class_.extend(child) elif ac.kind == CursorKind.DESTRUCTOR: func = self._process_method(ac, class_) if func.is_virtual: class_.is_polymorphic = True class_.destructor = func elif ac.kind == CursorKind.ENUM_DECL: e = self._process_enum(ac, class_) class_.enums[e.name] = e elif ac.kind == CursorKind.FIELD_DECL: v = self._process_variable(ac, class_) class_.variables[v.name] = v elif ac.kind == CursorKind.CXX_METHOD: func = self._process_method(ac, class_) 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_) class_.typedefs[tp.name] = tp elif ac.kind == CursorKind.TYPE_ALIAS_TEMPLATE_DECL: tp = self._process_template_alias(ac, class_) 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, )
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="") if length == 1: return m m.definition = " ".join([i.spelling for i in tokens[1:]]) return m
def _process_function(self, c: Cursor, parent: Namespace): 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() ], ) self.objects[func.full_name] = func return func
def _process_class(self, c: Cursor, parent: AnyCxxSymbol, store_global=True): # 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_) if store_global: self.objects[class_.full_name] = class_ return class_
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