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
def test_anonymous(self): filepath = str(Path(self.current_directory, "Anonymous.java")) ast = AST.build_from_javalang(build_ast(filepath)) pattern = EmptyRethrow() ast = AST.build_from_javalang(build_ast(filepath)) pattern = EmptyRethrow() self.assertEqual(pattern.value(ast), [19, 25])
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 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 _create_logical_operators_sequence(self, ast: AST, binary_operation_node: int) -> List[str]: if ast.get_type(binary_operation_node) != ASTNodeType.BINARY_OPERATION: return [] operator, left_side_node, right_side_node = ast.get_binary_operation_params(binary_operation_node) if operator not in logical_operators: return [] left_sequence = self._create_logical_operators_sequence(ast, left_side_node) right_sequence = self._create_logical_operators_sequence(ast, right_side_node) return left_sequence + [operator] + right_sequence
def value(self, ast: AST): lines: List[int] = [] for binary_operator in ast.get_proxy_nodes(ASTNodeType.BINARY_OPERATION): if binary_operator.operator == 'instanceof': lines.append(binary_operator.line) for method_invocation in ast.get_proxy_nodes(ASTNodeType.METHOD_INVOCATION): if method_invocation.member == 'isInstance': lines.append(method_invocation.line) return lines
def test_multiple_catch(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/MultipleCatch.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [3])
def test_fake(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/TrickyFake.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [])
def test_try_in_constructor(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/ExcelAnalyserImpl.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [43])
def test_try_without_throws(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/ExcelReader.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [])
def test_catch_with_similar_name(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/NotThrow.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [256])
def _get_all_method_invocation_params( self, ast: AST) -> Set[_MethodInvocationParams]: return { self._create_method_invocation_params(method_invocation) for method_invocation in ast.get_proxy_nodes( ASTNodeType.METHOD_INVOCATION) }
def test_find_protected_method(self): filepath = self.current_directory / "ProtectedMethod.java" ast = AST.build_from_javalang(build_ast(filepath)) pattern = ProtectedMethod() lines = pattern.value(ast) self.assertEqual(lines, [2, 6], "Should match pattern protected method")
def test_more_method_invocations(self): filepath = self.current_directory / "SequenceFile.java" ast = AST.build_from_javalang(build_ast(filepath)) pattern = SendNull() lines = pattern.value(ast) self.assertEqual( lines, [1097, 1186, 1201, 1217, 3285, 3298, 3367, 3537, 3550])
def value(self, filename: str) -> int: metric = 0 ast = AST.build_from_javalang(build_ast(filename)) for class_node in ast.get_proxy_nodes(ASTNodeType.CLASS_DECLARATION): for method_node in class_node.methods: metric += 1 return metric
def value(self, ast: AST) -> int: complexity = 0 for method_ast in ast.get_subtrees(ASTNodeType.METHOD_DECLARATION): method_declaration_index = method_ast.get_root().node_index self.__method_name = self._get_node_name(method_ast, method_declaration_index) complexity += self._get_complexity(method_ast, method_declaration_index, 0) return complexity
def value(self, ast: AST) -> List[int]: lines: List[int] = [] for method_declaration in ast.get_proxy_nodes( ASTNodeType.METHOD_DECLARATION): if 'protected' in method_declaration.modifiers: lines.append(method_declaration.line) return lines
def test_chained_exceptions3(self): filepath = str( Path(self.current_directory, "DatabaseNavigatorSourceContainer.java")) ast = AST.build_from_javalang(build_ast(filepath)) pattern = EmptyRethrow() self.assertEqual(pattern.value(ast), [])
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)
def value(self, ast: AST) -> int: fan_out = 0 for class_declaration in ast.get_subtrees( ASTNodeType.CLASS_DECLARATION): fan_out += self._calculate_class_fan_out(class_declaration) return fan_out
def test_sequential_catch_try(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/SequentialCatchTry.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [3, 10])
def test_try_inside_finally(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/TryInsideFinally.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [8])
def test_catch_with_functions(self): pattern = RedundantCatch() filepath = os.path.dirname( os.path.realpath(__file__)) + "/CatchWithFunctions.java" ast = AST.build_from_javalang(build_ast(filepath)) lines = pattern.value(ast) self.assertEqual(lines, [6])
def __count_value(value_dict, input_params, code_lines_dict, java_file: str, is_metric=False): """ Count value for input dict :param value_dict: Pattern item or Metric item from CONFIG :param input_params: list with calculated patterns/metrics :param code_lines_dict: list with found code lines of patterns/metrics :param java_file: full path for java file :is_metric: is item metric? :return: None, it has side-effect """ acronym = value_dict['code'] try: ast = AST.build_from_javalang(build_ast(java_file)) val = value_dict['make']().value(ast) if not is_metric: input_params[acronym] = len(val) code_lines_dict['lines_' + acronym] = val else: input_params[acronym] = val except Exception: exc_type, exc_value, exc_tb = sys.exc_info() raise Exception("Can't count {} metric: {}".format( acronym, str(type(exc_value))))
def value(self, ast: AST) -> List[int]: lines: List[int] = [] for if_statement in ast.get_proxy_nodes(ASTNodeType.IF_STATEMENT): if self._is_logical_or_used_in_expression(if_statement.condition) and \ self._is_block_consist_of_single_throw(if_statement.then_statement): lines.append(if_statement.line) return lines
def value(self, filename: str) -> List[int]: lines: List[int] = [] ast = AST.build_from_javalang(build_ast(filename)) for method_declaration in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION): if 'protected' in method_declaration.modifiers: lines.append(method_declaration.line) return lines
def value(self, ast: AST) -> int: method_diameters: List[int] = [ self._calcalute_diameter(method_ast) for method_ast in ast.get_subtrees(ASTNodeType.METHOD_DECLARATION) ] return max(method_diameters, default=0)
def test_several(self): # It has 2 matches in anonymous class! filepath = self.current_directory / "Several.java" ast = AST.build_from_javalang(build_ast(filepath)) pattern = SuperMethod() lines = pattern.value(ast) self.assertEqual(len(lines), 6)
def _get_complexity(self, ast: AST, each_block: int, nested_level: int) -> int: each_block_name = self._get_node_name(ast, each_block) each_block_type = ast.get_type(each_block) complexity = 0 if each_block_type == ASTNodeType.METHOD_DECLARATION and each_block_name != self.__method_name: complexity += self._nested_methods(ast, each_block, nested_level) elif each_block_type == ASTNodeType.IF_STATEMENT: complexity += self._check_if_statement(ast, each_block, nested_level) elif each_block_type in increment_and_nested_for: complexity += 1 + nested_level complexity += self._traverse_childs(ast, each_block, nested_level + 1) elif each_block_type in only_increment_for: complexity += self._process_not_nested_structure( ast, each_block, nested_level) else: complexity += self._traverse_childs(ast, each_block, nested_level) return complexity