def flag_instantiatable_class(dependency_tree, main_classes): """determine if the class can be instantiated""" main_classes_by_name_namespace = {make_namespace_class(c["namespace"], c["name"]): c for classes in main_classes.values() for c in classes} for module, header_name in main_classes: for class_ in main_classes[(module, header_name)]: can_be_instantiated = True if class_["abstract"]: can_be_instantiated = False else: # check if any pure virtual method is not implemented all_implemented_inherited_methods = get_all_class_methods_not_pure_virtual(class_) namespace_class = make_namespace_class(class_["namespace"], class_["name"]) for base_name_nsp in dependency_tree.breadth_first_iterator(namespace_class): base_class = main_classes_by_name_namespace.get(base_name_nsp) if base_class: base_class_methods = get_all_class_methods_not_pure_virtual(base_class) all_implemented_inherited_methods.update(base_class_methods) for base_name_nsp in dependency_tree.breadth_first_iterator(namespace_class): base_class = main_classes_by_name_namespace.get(base_name_nsp) if base_class and base_class["abstract"]: base_pure_virtual_methods = get_pure_virtual_methods(base_class) if base_pure_virtual_methods - all_implemented_inherited_methods: can_be_instantiated = False class_["can_be_instantiated"] = can_be_instantiated
def flag_instantiatable_class(dependency_tree, main_classes): # determine if the class can be instantiated main_classes_by_name_namespace = { make_namespace_class(c["namespace"], c["name"]): c for classes in main_classes.values() for c in classes } for module, header_name in main_classes: for class_ in main_classes[(module, header_name)]: can_be_instantiated = True if class_["abstract"]: can_be_instantiated = False else: # check for inherited abstract base classes methods = set([ m["name"] for access in "private protected public".split() for m in class_["methods"][access] ]) namespace_class = make_namespace_class(class_["namespace"], class_["name"]) for base_name_nsp in dependency_tree.breadth_first_iterator( namespace_class): base_class = main_classes_by_name_namespace.get( base_name_nsp) if base_class and base_class["abstract"]: base_pure_virtual_methods = set( get_pure_virtual_methods(base_class)) if base_pure_virtual_methods - methods: can_be_instantiated = False class_["can_be_instantiated"] = can_be_instantiated
def leaf_iterator(self): stack = list(sorted( self.tree.keys())) # sort to output same result everytime seen = set() while stack: for class_name in stack: inheritance = set(self.tree.get(class_name).keys()) inheritance = set( (i[:i.find("<")] if "<" in i else i for i in inheritance)) inheritance_current_namespace = set([ make_namespace_class(class_name[:class_name.rfind("::")], i) for i in inheritance ]) is_base_class = not inheritance inheritance_is_seen = not inheritance - seen or not ( inheritance_current_namespace - seen) all_external = all( any(i.startswith(e) for e in EXTERNAL_INHERITANCE) for i in inheritance) if any([is_base_class, inheritance_is_seen, all_external]): yield class_name seen.add(class_name) stack.remove(class_name) break else: raise ValueError("Couldn't find base classes for: %s" % stack)
def list_parameter_types(self, prefix, template_types): if len(self.cppmethod["parameters"]): types = [] for param in self.cppmethod["parameters"]: if param["name"] == "&": # fix for CppHeaderParser bug param["type"] += " &" param["reference"] = 1 type_ = param["type"] if not param["unresolved"] else param["raw_type"] if template_types: for name, template_type in template_types: type_ = type_.replace(name, template_type) raw_type_no_pcl = param["raw_type"].replace("pcl::", "") if param["unresolved"]: type_ = self.clean_unresolved_type(param, type_, prefix) elif type_ in GLOBAL_PCL_IMPORTS: type_ = make_namespace_class("pcl", type_) elif raw_type_no_pcl in GLOBAL_PCL_IMPORTS: # ensure pcl namespace in type pos = type_.find(raw_type_no_pcl) if not type_[pos - 5:pos] == "pcl::": type_ = type_.replace(raw_type_no_pcl, "pcl::" + raw_type_no_pcl) if param.get("array_size"): type_ += "[%s]" % param.get("array_size") types.append(type_) type_ = ", ".join(types) else: type_ = "" return type_
def format_type_with_namespace(type_, base_namespace, namespace_by_class_name, template_typenames_defaults, replace_with_templated_typename): typename_default = template_typenames_defaults.get(type_) has_default_and_replace = typename_default and replace_with_templated_typename if has_default_and_replace: type_ = typename_default keep_asis = any(type_.startswith(i) for i in KEEP_ASIS_TYPES) if not keep_asis and not typename_default or has_default_and_replace: if type_ in GLOBAL_PCL_IMPORTS: base_namespace = "pcl" is_external_inheritance = any( type_.startswith(i) for i in EXTERNAL_INHERITANCE) if not is_external_inheritance: namespaces = namespace_by_class_name and namespace_by_class_name.get( type_) if namespaces: base_namespace = namespaces[0] type_ = make_namespace_class(base_namespace, type_) return type_
def clean_unresolved_type(self, param, type_, prefix): const = "const " if param["constant"] or "const" in param[ "type"] else "" type_ = type_.replace("typename ", "") if "const" in type_: # fix for CppHeaderParser parsing error 'std::vector<double>const' (no space) const = "" ref = " &" if param["reference"] else "" parent_name = param["method"].get("parent", {}).get("name") custom = None if parent_name: custom = CUSTOM_OVERLOAD_TYPES.get((parent_name, type_)) type_no_template = type_[:type_.find("<")] if "<" in type_ else type_ template_string = self.cppmethod.get("parent", {}).get("template", "") if type_ == "pcl::PCLPointCloud2::" and param["name"].startswith( "Const"): type_ = type_ + param["name"] # fix for CppHeaderParser bug elif type_.startswith("pcl::"): type_ = make_namespace_class("pcl", type_) elif any(type_.startswith(base) for base in KEEP_ASIS_TYPES): pass elif type_ in template_string: # templated argument pass elif type_no_template in EXPLICIT_IMPORTED_TYPES: pass elif type_no_template in GLOBAL_PCL_IMPORTS: pass elif custom: type_ = custom elif any(type_.startswith(t) for t in EXTERNAL_INHERITANCE): pass elif prefix == "pcl": type_ = make_namespace_class("pcl", type_) else: type_ = "%s::%s" % (prefix, type_) for global_pcl in GLOBAL_PCL_IMPORTS: pos = type_.find(global_pcl) if not type_[pos - 5:pos] == "pcl::": type_ = type_.replace(global_pcl, "pcl::" + global_pcl) type_ = const + type_ + ref if param.get("pointer"): type_ = type_.strip() + "*" type_ = type_.replace( "constpcl::", "const pcl::") # parser error for this expression return type_
def breadth_first_iterator(self, start_class=None): all_inheritances = [make_namespace_class(get_class_namespace(class_), i) for class_, inheritance in self.tree.items() for i in inheritance] if start_class is None: queue = deque(elem for elem in self.tree if elem not in all_inheritances) else: queue = deque([start_class]) while queue: class_ = queue.popleft() yield class_ for inherits in self.tree.get(class_, []): queue.append(inherits)
def list_parameter_types(self, prefix, template_types): if len(self.cppmethod["parameters"]): types = [] for param in self.cppmethod["parameters"]: if param["name"] == "&": # fix for CppHeaderParser bug param["type"] += " &" param["reference"] = 1 type_ = param["type"] if not param["unresolved"] else param[ "raw_type"] if "boost::function<double(constdouble)" in type_: # fix for CppHeaderParser bug type_ = type_.replace('constdouble', 'const double') if template_types: for name, template_type in template_types: type_ = type_.replace(name, template_type) raw_type_no_pcl = param["raw_type"].replace("pcl::", "") if type_ in GLOBAL_PCL_IMPORTS: type_ = make_namespace_class("pcl", type_) elif param["unresolved"]: type_ = self.clean_unresolved_type(param, type_, prefix) elif raw_type_no_pcl in GLOBAL_PCL_IMPORTS: # ensure pcl namespace in type pos = type_.find(raw_type_no_pcl) if not type_[pos - 5:pos] == "pcl::": type_ = type_.replace(raw_type_no_pcl, "pcl::" + raw_type_no_pcl) if param["constant"] and not type_.startswith("const"): type_ = "const " + type_ if all(c in type_ for c in "<>"): if type_.startswith("const"): type_ = "const typename " + type_.replace( "const ", "", 1) else: type_ = "typename " + type_ if param["reference"] and "&" not in type_: type_ += " &" if param.get("array_size"): type_ += "[%s]" % param.get("array_size") types.append(type_) type_ = ", ".join(types) else: type_ = "" return type_
def __init__(self, classes: List[CppClass]): """ :param classes: """ self.namespace_by_class_name = defaultdict(list) for c in classes: self.namespace_by_class_name[c["name"]].append(c["namespace"]) self.tree = {} for c in classes: class_name = make_namespace_class(c["namespace"], c["name"]) inheritance = dict(clean_inheritance(c, self.namespace_by_class_name)) self.tree[class_name] = inheritance self.n_template_point_types = {k: len(v) for inheritance in self.tree.values() for k, v in inheritance.items()}
def breadth_first_iterator(self, start_class=None) -> Generator[str, None, None]: """ Yields every class that aren't inherited elsewhere, then all their first inherited classes, etc. :param start_class: class name to start from. If None, start from all classes that aren't inherited by any other class. """ all_inheritances = { make_namespace_class(get_class_namespace(class_), i) for class_, inheritance in self.tree.items() for i in inheritance } if start_class is None: queue = deque(elem for elem in self.tree if elem not in all_inheritances) else: queue = deque([start_class]) while queue: class_ = queue.popleft() if class_ != start_class: yield class_ for inherits in self.tree.get(class_, []): queue.append(inherits)
def format_type_with_namespace(type_, base_namespace, namespace_by_class_name, template_typenames_defaults, replace_with_templated_typename): # handle const prefix const = "" if type_.startswith("const "): type_ = type_.replace("const ", "", 1) const = "const " is_template_name = type_ in template_typenames_defaults typename_default = template_typenames_defaults.get(type_) has_default_and_replace = typename_default and replace_with_templated_typename if has_default_and_replace: type_ = typename_default keep_asis = any(type_.startswith(i) for i in KEEP_ASIS_TYPES) if keep_asis: pass elif is_template_name: pass elif not is_template_name or has_default_and_replace: if type_ in GLOBAL_PCL_IMPORTS: base_namespace = "pcl" is_external_inheritance = any( type_.startswith(i) for i in EXTERNAL_INHERITANCE) if not is_external_inheritance: namespaces = namespace_by_class_name and namespace_by_class_name.get( type_) if namespaces: base_namespace = namespaces[0] type_ = make_namespace_class(base_namespace, type_) type_ = const + type_ return type_
def key(class_): return classes_sorted_base_first.index(make_namespace_class(class_["namespace"], class_["name"]))