def _calculate_patterns_and_metrics(
        file_path: str,
        is_decomposition_requested: bool) -> List[Dict[str, Any]]:
    results: List[Dict[str, Any]] = []

    config = Config.get_patterns_config()
    patterns_info = [
        pattern_info for pattern_info in config["patterns"]
        if pattern_info["code"] not in config["patterns_exclude"]
    ]

    metrics_info = [
        metric_info for metric_info in config["metrics"]
        if metric_info["code"] not in config["metrics_exclude"]
    ]

    ast = AST.build_from_javalang(build_ast(file_path))
    classes_ast = [
        ast.get_subtree(node) for node in ast.get_root().types
        if node.node_type == ASTNodeType.CLASS_DECLARATION
    ]

    for class_ast in classes_ast:
        components = (decompose_java_class(
            class_ast, "strong", ignore_getters=True, ignore_setters=True)
                      if is_decomposition_requested else [class_ast])
        for index, component_ast in enumerate(components):
            calculation_result = {
                "filepath": file_path,
                "class_name": class_ast.get_root().name,
                "component_index": index,
            }

            for pattern_info in patterns_info:
                try:
                    pattern = pattern_info["make"]()
                    pattern_result = pattern.value(component_ast)
                    calculation_result[pattern_info["code"]] = len(
                        pattern_result)
                    calculation_result["lines_" +
                                       pattern_info["code"]] = pattern_result
                except Exception as cause:
                    raise FileProcessingError(file_path, pattern_info["name"],
                                              cause)

            for metric_info in metrics_info:
                try:
                    metric = metric_info["make"]()
                    metric_result = metric.value(component_ast)
                    calculation_result[metric_info["code"]] = metric_result
                except Exception as cause:
                    raise FileProcessingError(file_path, metric_info["name"],
                                              cause)

            results.append(calculation_result)

    return results
Esempio n. 2
0
def calculate_patterns_and_metrics_with_decomposition(file_path: str, args):
    error_exc = None
    patterns_to_suppress = args.suppress
    results_for_components = []

    try:
        config = Config.get_patterns_config()
        patterns_info = [
            pattern_info for pattern_info in config["patterns"]
            if pattern_info["code"] not in config["patterns_exclude"]
        ]

        metrics_info = [
            metric_info for metric_info in config["metrics"]
            if metric_info["code"] not in config["metrics_exclude"]
        ]
        ast = AST.build_from_javalang(build_ast(file_path))
        classes_ast = [
            ast.get_subtree(node) for node in ast.get_root().types
            if node.node_type == ASTNodeType.CLASS_DECLARATION
        ]
        for class_ast in classes_ast:
            for index, component_ast in enumerate(
                    decompose_java_class(class_ast, "strong")):
                result_for_component: Dict[Any, Any] = {}
                code_lines_dict: Dict[Any, Any] = OrderedDict()
                input_params = OrderedDict()  # type: ignore

                for pattern_info in patterns_info:
                    if pattern_info['code'] in config['patterns_exclude']:
                        continue
                    if pattern_info['code'] in patterns_to_suppress:
                        input_params[pattern_info["code"]] = 0
                        code_lines_dict["lines_" + pattern_info["code"]] = []
                    else:
                        pattern = pattern_info["make"]()
                        pattern_result = pattern.value(component_ast)
                        input_params[pattern_info["code"]] = len(
                            pattern_result)
                        code_lines_dict["lines_" +
                                        pattern_info["code"]] = pattern_result

                for metric_info in metrics_info:
                    metric = metric_info["make"]()
                    metric_result = metric.value(component_ast)
                    input_params[metric_info["code"]] = metric_result

                result_for_component['code_lines_dict'] = code_lines_dict
                result_for_component['input_params'] = input_params
                result_for_component['index'] = index
                results_for_components.append(result_for_component)
    except Exception as ex:
        error_exc = ex

    return results_for_components, error_exc
 def __decompose_with_setter_functionality(self, ignore_getters=False, ignore_setters=False):
     file = str(Path(self.cur_dir, 'LottieImageAsset.java'))
     ast = AST.build_from_javalang(build_ast(file))
     classes_ast = [
         ast.get_subtree(node)
         for node in ast.get_root().types
         if node.node_type == ASTNodeType.CLASS_DECLARATION
     ]
     components = list(decompose_java_class(
         classes_ast[0],
         "strong",
         ignore_setters=ignore_setters,
         ignore_getters=ignore_getters))
     function_names = flatten([
         [x.name for x in list(c.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION))]
         for c in components])
     return function_names
    def test_ncss(self):
        test_data_folder = self.cur_dir / "ncss"
        for filepath in test_data_folder.glob("*.java"):
            with self.subTest(f"Testing decomposition of {filepath}"):
                ast = AST.build_from_javalang(build_ast(filepath))

                classes_ast = [
                    ast.get_subtree(node)
                    for node in ast.get_root().types
                    if node.node_type == ASTNodeType.CLASS_DECLARATION
                ]

                ncss_metric = NCSSMetric()

                # NCSS of a class may not be equal to sum of ncss of methods and fields
                # due to presence of nested classes. To bypass it we calculate NCSS only
                # of methods and fields.
                methods_ncss = 0
                fields_ncss = 0
                components_ncss = 0
                components_qty = 0

                for class_ast in classes_ast:
                    class_declaration = class_ast.get_root()

                    for method in class_declaration.methods:
                        methods_ncss += ncss_metric.value(class_ast.get_subtree(method))

                    for field in class_declaration.fields:
                        fields_ncss += ncss_metric.value(class_ast.get_subtree(field))

                    for component in decompose_java_class(class_ast, "strong"):
                        components_qty += 1
                        components_ncss += ncss_metric.value(component)

                # Each component has a CLASS_DECLARATION node. It increase NCSS of each component by 1.
                # To achieve equality we add number of components to the sum of NCSS of just methods and fields.
                self.assertEqual(methods_ncss + fields_ncss + components_qty, components_ncss)
Esempio n. 5
0
 def test_weak_decomposition(self):
     class_ast = self._get_class_ast("MethodUseOtherMethodExample.java",
                                     "MethodUseOtherMethod")
     class_components = decompose_java_class(class_ast, "weak")
     self.assertEqual(len(class_components), 5)