def _get_lambda_try_nodes(self, ast: AST, lambda_node: ASTNode) -> List[int]: assert lambda_node.node_type == ASTNodeType.LAMBDA_EXPRESSION return [ try_node.line for try_node in ast.get_subtree( lambda_node).get_proxy_nodes(ASTNodeType.TRY_STATEMENT) ]
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 class_item in class_declaration.body: if class_item.node_type == ASTNodeType.METHOD_DECLARATION: local_methods_names.add(class_item.name) if "public" in class_item.modifiers: rfc += 1 invoked_methods |= self._get_all_method_invocation_params( java_class.get_subtree(class_item) ) # 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
def value(self, ast: AST) -> int: rfc = 0 for class_declaration in ast.get_proxy_nodes( ASTNodeType.CLASS_DECLARATION): rfc += self._calculate_class_RFC( ast.get_subtree(class_declaration)) return rfc
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)
def _check_this_statements(self, ast: AST, node: ASTNode) -> bool: for child_this in ast.get_subtree(node).get_proxy_nodes( ASTNodeType.THIS): child_membref = child_this.selectors if len(child_membref): mem_referenced_name = child_membref[0].member if node.name.lower() == 'set' + mem_referenced_name.lower(): return True return False
def _process_catch(self, ast: AST, catch_clauses: List[ASTNode]): lines: List[int] = [] for catch_clause in catch_clauses: throw_statements = ast.get_subtree(catch_clause).get_proxy_nodes( ASTNodeType.THROW_STATEMENT) for throw_stat in throw_statements: if throw_stat.expression.node_type == ASTNodeType.MEMBER_REFERENCE \ and throw_stat.expression.member == catch_clause.parameter.name: lines.append(throw_stat.line) return lines
def __check_primary(self, ast: AST, node: Union[ASTNode, List[ASTNode]]) -> bool: if isinstance( node, ASTNode ) and node.node_type == ASTNodeType.CONSTRUCTOR_DECLARATION: for assignment in ast.get_subtree(node).get_proxy_nodes( ASTNodeType.ASSIGNMENT): if assignment.expressionl.node_type == ASTNodeType.THIS: return True return False
def value(self, ast: AST) -> List[int]: lines: List[int] = list() for method_declaration in ast.get_proxy_nodes( ASTNodeType.METHOD_DECLARATION): for bin_operation in ast.get_subtree( method_declaration).get_proxy_nodes( ASTNodeType.BINARY_OPERATION): if self._check_null(bin_operation): lines.append(bin_operation.operandr.line) return lines
def value(self, ast: AST) -> List[int]: total_code_lines: List[int] = [] for method_declaration in ast.get_proxy_nodes( ASTNodeType.METHOD_DECLARATION): try_nodes = list( ast.get_subtree(method_declaration).get_proxy_nodes( ASTNodeType.TRY_STATEMENT)) if len(try_nodes) > 1: total_code_lines.append(method_declaration.line) return total_code_lines
def _extract_synchronized_block_semantic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: lock_subtree = method_ast.get_subtree(statement.lock) statements_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict([ (statement, _extract_semantic_from_ast(lock_subtree)) ]) for inner_statement in statement.block: statements_semantic.update( _extract_statement_semantic(inner_statement, method_ast)) return statements_semantic
def _extract_for_cycle_semantic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: control_subtree = method_ast.get_subtree(statement.control) statements_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict([ (statement, _extract_semantic_from_ast(control_subtree)) ]) statements_semantic.update( _extract_statement_semantic(statement.body, method_ast)) return statements_semantic
def value(self, ast: AST) -> List[int]: lines: List[int] = [] excluded_nodes: List[int] = [] for method_declaration in ast.get_proxy_nodes( ASTNodeType.METHOD_DECLARATION, ASTNodeType.CONSTRUCTOR_DECLARATION): method_throw_names = method_declaration.throws for try_node in ast.get_subtree( method_declaration).get_proxy_nodes( ASTNodeType.TRY_STATEMENT): if method_throw_names is not None and \ try_node.catches is not None and \ self._is_redundant(method_throw_names, try_node): lines.append(try_node.line) for lambda_node in ast.get_subtree( method_declaration).get_proxy_nodes( ASTNodeType.LAMBDA_EXPRESSION): excluded_nodes.extend( self._get_lambda_try_nodes(ast, lambda_node)) return sorted(list(set(lines).difference(set(excluded_nodes))))
def _extract_switch_branching_semantic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: expression_subtree = method_ast.get_subtree(statement.expression) statements_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict([ (statement, _extract_semantic_from_ast(expression_subtree)) ]) for case in statement.cases: for inner_statement in case.statements: statements_semantic.update( _extract_statement_semantic(inner_statement, method_ast)) return statements_semantic
def _extract_if_branching_sematic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: condition_subtree = method_ast.get_subtree(statement.condition) statements_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict([ (statement, _extract_semantic_from_ast(condition_subtree)) ]) statements_semantic.update( _extract_statement_semantic(statement.then_statement, method_ast)) if statement.else_statement is not None: statements_semantic.update( _extract_statement_semantic(statement.else_statement, method_ast)) return statements_semantic
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
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
def _extract_try_block_semantic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: statements_semantic: Dict[ASTNode, StatementSemantic] = OrderedDict() for resource in statement.resources or []: resource_ast = method_ast.get_subtree(resource) statements_semantic[resource] = _extract_semantic_from_ast( resource_ast) for node in statement.block: statements_semantic.update( _extract_statement_semantic(node, method_ast)) for catch_clause in statement.catches or []: for inner_statement in catch_clause.block: statements_semantic.update( _extract_statement_semantic(inner_statement, method_ast)) for node in statement.finally_block or []: statements_semantic.update( _extract_statement_semantic(node, method_ast)) return statements_semantic
def _extract_plain_statement_semantic( statement: ASTNode, method_ast: AST) -> Dict[ASTNode, StatementSemantic]: statement_ast = method_ast.get_subtree(statement) return OrderedDict([(statement, _extract_semantic_from_ast(statement_ast)) ])