Example #1
0
    def _calculate_class_RFC(self, java_class: AST) -> int:
        class_declaration = java_class.get_root()
        assert class_declaration.node_type == ASTNodeType.CLASS_DECLARATION

        rfc = 0
        invoked_methods: Set[_MethodInvocationParams] = set()
        local_methods_names: Set[str] = set()
        for method_ast in java_class.get_subtrees(
                ASTNodeType.METHOD_DECLARATION):
            method_declaration = method_ast.get_root()
            local_methods_names.add(method_declaration.name)
            if "public" in method_declaration.modifiers:
                rfc += 1
                invoked_methods |= self._get_all_method_invocation_params(
                    method_ast)

        # filter out inherited methods
        # consider local methods with name not found
        # among methods names of current class as inherited
        invoked_methods = {
            invoked_method
            for invoked_method in invoked_methods if not invoked_method.isLocal
            or invoked_method.name in local_methods_names
        }

        rfc += len(invoked_methods)
        return rfc
Example #2
0
def extract_method_statements_semantic(
        method_ast: AST) -> Dict[ASTNode, StatementSemantic]:
    statement_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict()
    for statement in method_ast.get_root().body:
        statement_semantic.update(
            _extract_statement_semantic(statement, method_ast))

    return statement_semantic
Example #3
0
    def _calcalute_diameter(self, ast: AST) -> int:
        distant_node_from_root, _ = self._find_distant_node(
            ast, ast.get_root(), False)

        # traverse undirected graph, because we need to ba able to traverse from child to parent in general
        # it is not needed at previous call, because the most distant node of a tree is anyway a child of root
        # and there is no need to traverse from child to parent, which simply safe time
        _, diameter = self._find_distant_node(ast, distant_node_from_root,
                                              True)
        return diameter
Example #4
0
    def _calculate_class_fan_out(self, java_class: AST) -> int:
        class_declaration = java_class.get_root()
        assert class_declaration.node_type == ASTNodeType.CLASS_DECLARATION

        used_classes_names: Set[str] = set()

        for type_reference in java_class.get_proxy_nodes(
                ASTNodeType.REFERENCE_TYPE):
            used_class_name = self._get_class_name_from_type_reference(
                type_reference)
            if used_class_name not in FanOut._excluded_class_names:
                used_classes_names.add(used_class_name)

        # remove name of the class
        used_classes_names -= {class_declaration.name}
        return len(used_classes_names)
Example #5
0
def find_patterns(tree: AST, patterns: List[Any]) -> Set[str]:
    """
    Searches all setters in a component
    :param patterns: list of patterns to check
    :param tree: ast tree
    :return: list of method name which are setters
    """

    patterns_method_names: Set[str] = set()
    for method_declaration in tree.get_root().methods:
        method_ast = tree.get_subtree(method_declaration)
        for pattern in patterns:
            if is_ast_pattern(method_ast, pattern):
                patterns_method_names.add(method_declaration.name)

    return patterns_method_names
Example #6
0
def _filter_class_methods_and_fields(class_ast: AST,
                                     allowed_fields_names: Set[str],
                                     allowed_methods_names: Set[str]) -> AST:
    class_declaration = class_ast.get_root()
    allowed_nodes = {class_declaration.node_index}

    for field_declaration in class_declaration.fields:
        if len(allowed_fields_names & set(field_declaration.names)) != 0:
            field_ast = class_ast.get_subtree(field_declaration)
            allowed_nodes.update(node.node_index for node in field_ast)

    for method_declaration in class_declaration.methods:
        if method_declaration.name in allowed_methods_names:
            method_ast = class_ast.get_subtree(method_declaration)
            allowed_nodes.update(node.node_index for node in method_ast)

    return AST(class_ast.tree.subgraph(allowed_nodes),
               class_declaration.node_index)
Example #7
0
def _find_fields_usage(method_ast: AST) -> Set[str]:
    local_variables: Set[str] = set()
    for variable_declaration in method_ast.get_proxy_nodes(
            ASTNodeType.LOCAL_VARIABLE_DECLARATION):
        local_variables.update(variable_declaration.name)

    method_declaration = method_ast.get_root()
    for parameter in method_declaration.parameters:
        local_variables.add(parameter.name)

    used_fields: Set[str] = set()
    for member_reference in method_ast.get_proxy_nodes(
            ASTNodeType.MEMBER_REFERENCE):
        if member_reference.qualifier is None and \
                member_reference.member not in local_variables:
            used_fields.add(member_reference.member)

    return used_fields
Example #8
0
def _create_usage_graph(class_ast: AST) -> DiGraph:
    usage_graph = DiGraph()
    fields_ids: Dict[str, int] = {}
    methods_ids: Dict[str, int] = {}

    class_declaration = class_ast.get_root()

    for field_declaration in class_declaration.fields:
        # several fields can be declared at one line
        for field_name in field_declaration.names:
            fields_ids[field_name] = len(fields_ids)
            usage_graph.add_node(fields_ids[field_name],
                                 type="field",
                                 name=field_name)

    for method_declaration in class_declaration.methods:
        method_name = method_declaration.name

        # overloaded methods considered as single node in usage_graph
        if method_name not in methods_ids:
            methods_ids[method_name] = len(fields_ids) + 1 + len(methods_ids)
            usage_graph.add_node(methods_ids[method_name],
                                 type="method",
                                 name=method_name)

    for method_declaration in class_declaration.methods:
        method_ast = class_ast.get_subtree(method_declaration)

        for invoked_method_name in _find_local_method_invocations(method_ast):
            if invoked_method_name in methods_ids:
                usage_graph.add_edge(
                    methods_ids[method_declaration.name],
                    methods_ids[invoked_method_name],
                )

        for used_field_name in _find_fields_usage(method_ast):
            if used_field_name in fields_ids:
                usage_graph.add_edge(methods_ids[method_declaration.name],
                                     fields_ids[used_field_name])

    return usage_graph