Beispiel #1
0
    def test_fake_node(self):
        ast = AST.build_from_javalang(
            build_ast(
                Path(__file__).absolute().parent / "MethodUseOtherMethodExample.java"
            )
        )

        fake_node = ast.create_fake_node()

        # fixed public interface
        self.assertTrue(fake_node.is_fake)
        self.assertEqual(list(fake_node.children), [])
        self.assertEqual(fake_node.line, -1)
        self.assertEqual(fake_node.parent, None)
        self.assertEqual(fake_node.node_index, -1)

        # proxy interface
        self.assertEqual(fake_node.node_type, None)

        # interface through standart python function
        self.assertEqual(str(fake_node),
                         "node index: -1\n"
                         "node_type: None")
        self.assertEqual(repr(fake_node), "<ASTNode node_type: None, node_index: -1>")
        self.assertEqual(dir(fake_node), ["children", "is_fake", "line", "node_index", "parent"])

        try:
            hash(fake_node)
        except Exception as e:
            self.fail(f"Failed to hash fake node with following exception {e}.")
Beispiel #2
0
    def test_fake_nodes_equality(self):
        ast1 = AST.build_from_javalang(
            build_ast(
                Path(__file__).absolute().parent /
                "MethodUseOtherMethodExample.java"))

        ast2 = AST.build_from_javalang(
            build_ast(
                Path(__file__).absolute().parent / "LottieImageAsset.java"))

        ast1_fake_node1 = ast1.create_fake_node()
        ast1_fake_node2 = ast1.create_fake_node()
        ast2_fake_node1 = ast2.create_fake_node()

        self.assertFalse(ast1_fake_node1 == ast1_fake_node2)
        self.assertFalse(ast1_fake_node1 == ast2_fake_node1)
Beispiel #3
0
 def _get_lines(self, file, function_name):
     ast = AST.build_from_javalang(build_ast(file))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == function_name
     ][0]
     return method_body_lines(m_decl, file)
Beispiel #4
0
    def test_simple_examples(self):
        filepath = self.current_directory / "BlockStatementGraphExamples.java"
        ast = AST.build_from_javalang(build_ast(filepath))

        try:
            class_declaration = next(
                node for node in ast.get_root().types
                if node.node_type == ASTNodeType.CLASS_DECLARATION
                and node.name == "BlockStatementGraphExamples")
        except StopIteration:
            raise RuntimeError(
                f"Can't find class BlockStatementGraphExamples in file {filepath}"
            )

        for method_declaration in class_declaration.methods:
            with self.subTest(
                    f"Testing method {method_declaration.name} in class {class_declaration.name} in file {filepath}"
            ):
                block_statement_graph = build_block_statement_graph(
                    ast.get_subtree(method_declaration))
                self.assertEqual(
                    BlockStatementTestCase.flatten_block_statement_graph(
                        block_statement_graph),
                    BlockStatementTestCase._expected_flattened_graphs[
                        method_declaration.name],
                )
Beispiel #5
0
    def test_class_computed_fields(self):
        ast = AST.build_from_javalang(
            build_ast(
                Path(__file__).absolute().parent / "MethodUseOtherMethodExample.java"
            )
        )
        package = ast.get_root()
        assert len(package.types) == 1 and \
            package.types[0].node_type == ASTNodeType.CLASS_DECLARATION

        java_class = package.types[0]
        self.assertEqual(java_class.name, "MethodUseOtherMethod")
        self.assertEqual(java_class.modifiers, set())
        self.assertEqual(java_class.documentation, "/**\n* Some documentation\n*/")

        # consider each field declaration declares single field
        fields_names = {field.names[0] for field in java_class.fields}
        self.assertEqual(fields_names, {"connectingField", "redundantField"})

        methods_names = {method.name for method in java_class.methods}
        self.assertEqual(
            methods_names,
            {
                "useOnlyMethods1",
                "useOnlyMethods2",
                "getField",
                "setField",
                "standAloneMethod",
                "shadowing",
            },
        )

        self.assertEqual(set(java_class.constructors), set())
Beispiel #6
0
    def _get_method_ast(self, class_decl):
        with NamedTemporaryFile(delete=False) as f:
            _name = f.name
            f.write('\n'.join(class_decl).encode())
        ast = AST.build_from_javalang(build_ast(_name))
        os.unlink(_name)

        nodes = list(ast)
        _method_decl = ast.get_subtree(nodes[4])
        return _method_decl
Beispiel #7
0
def get_ast_if_possible(file_path: Path) -> Optional[AST]:
    """
    Processing file in order to check
    that its original version can be parsed
    """
    ast = None
    try:
        ast = AST.build_from_javalang(build_ast(str(file_path)))
    except Exception:
        print(f"Processing {file_path} is aborted due to parsing")
    return ast
 def test_is_valid_function_with_return_in_the_middle(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'severalReturns'
     ][0]
     m_inv = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_INVOCATION)
         if x.member == 'severalReturns'
     ][0]
     is_matched = is_match_to_the_conditions(ast, m_inv, m_decl_original)
     self.assertEqual(is_matched, False)
Beispiel #9
0
    def _get_class_ast(self, filename: str, class_name: str) -> AST:
        package_ast = AST.build_from_javalang(
            build_ast(str(Path(__file__).parent.absolute() / filename)))
        package_declaration = package_ast.get_root()
        try:
            class_declaration = next(
                class_declaration
                for class_declaration in package_declaration.types
                if class_declaration.name == class_name)
            return package_ast.get_subtree(class_declaration)

        except StopIteration:
            raise ValueError(
                f"File '{filename}' does not have top level class '{class_name}'."
            )
Beispiel #10
0
def common_cli(main: MainFunction, description: str) -> None:
    parser = ArgumentParser(description=description)
    parser.add_argument(
        "-f",
        "--file",
        required=True,
        help="File path to JAVA source code for extracting semantic")
    parser.add_argument(
        "-c",
        "--class",
        default=None,
        dest="class_name",
        help=
        "Class name of method to parse, if omitted all classes are considered",
    )
    parser.add_argument(
        "-m",
        "--method",
        default=None,
        dest="method_name",
        help="Method name to parse, if omitted all method are considered",
    )
    args = parser.parse_args()

    ast = AST.build_from_javalang(build_ast(args.file))

    classes_declarations = (node for node in ast.get_root().types
                            if node.node_type == ASTNodeType.CLASS_DECLARATION)

    if args.class_name is not None:
        classes_declarations = (node for node in classes_declarations
                                if node.name == args.class_name)

    methods_infos = (MethodInfo(
        ast=ast.get_subtree(method_declaration),
        method_name=method_declaration.name,
        class_name=class_declaration.name,
    ) for class_declaration in classes_declarations
                     for method_declaration in class_declaration.methods)

    if args.method_name is not None:
        methods_infos = (method_info for method_info in methods_infos
                         if method_info.method_name == args.method_name)

    for method_info in methods_infos:
        main(method_info.ast, args.file, method_info.class_name,
             method_info.method_name)
Beispiel #11
0
 def test_invocation_inside_if_not_process(self):
     filepath = self.current_directory / "Example_nested.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'doAction'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'handleAction'
     ][0]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'handleAction'
     ][0]
     is_matched = is_match_to_the_conditions(ast, m_inv, m_decl_original)
     self.assertEqual(is_matched, False)
 def test_is_return_type_not_assigning_value_valid(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'method_decl'
     ][0]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'invocation'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'invocation'
     ][0]
     self.assertFalse(
         is_match_to_the_conditions(ast, m_inv, m_decl_original))
 def test_is_valid_function_with_one_return(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'runDelete'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'delete'
     ][0]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'delete'
     ][0]
     is_matched = is_match_to_the_conditions(ast, m_inv, m_decl_original)
     self.assertEqual(is_matched, True)
 def test_inline_strange_body2(self):
     filepath = self.current_directory / 'InlineExamples' / 'cut.java'
     test_filepath = self.current_directory / 'InlineTestExamples' / 'cut.java'
     temp_filename = self.current_directory / 'temp1.java'
     algorithm_type = InlineTypesAlgorithms.WITHOUT_RETURN_WITHOUT_ARGUMENTS
     algorithm_for_inlining = AlgorithmFactory().create_obj(algorithm_type)
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'copy'
     ][0]
     body_start_line, body_end_line = method_body_lines(m_decl, filepath)
     algorithm_for_inlining().inline_function(filepath, 8, body_start_line,
                                              body_end_line, temp_filename)
     with open(temp_filename, encoding='utf-8') as actual_file, \
             open(test_filepath, encoding='utf-8') as test_ex:
         self.assertEqual(actual_file.read(), test_ex.read())
     temp_filename.unlink()
Beispiel #15
0
def get_method_ast(filename: str, class_name: str, method_name: str,
                   method_decl_line: int) -> AST:
    ast = AST.build_from_javalang(build_ast(str(filename)))

    try:
        class_declaration = next(
            node for node in ast.get_root().types
            if node.node_type == ASTNodeType.CLASS_DECLARATION
            and node.name == class_name)
        method_declaration = next(
            node for node in class_declaration.methods
            if node.name == method_name and node.line == method_decl_line)
    except StopIteration:
        raise RuntimeError(
            f"Failed to find method {method_name} in class {class_name} in file {filepath}"
        )

    return ast.get_subtree(method_declaration)
    def test_inline_without_return_type(self):
        algorithm = InlineWithoutReturnWithoutArguments()
        file = self.current_directory / 'InlineExamples' / 'PlanetDialog.java'
        temp_filename = self.current_directory / 'temp.java'
        test_example = self.current_directory / 'InlineTestExamples' / 'PlanetDialog.java'
        ast = AST.build_from_javalang(build_ast(file))
        m_decl = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'makeBloom'
        ][0]
        body_start_line, body_end_line = method_body_lines(m_decl, file)

        algorithm.inline_function(file, 70, body_start_line, body_end_line,
                                  temp_filename)
        with open(temp_filename, encoding='utf-8') as actual_file, \
                open(test_example, encoding='utf-8') as test_ex:
            self.assertEqual(actual_file.read(), test_ex.read())
        temp_filename.unlink()
    def test_is_invocation_in_if_with_single_statement_valid(self):
        filepath = self.current_directory / "Example.java"
        ast = AST.build_from_javalang(build_ast(filepath))
        m_decl = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'test_single_stat_in_if'
        ][0]
        m_decl_original = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'intersected_var'
        ][0]
        m_inv = [
            x for x in ast.get_subtree(m_decl).get_proxy_nodes(
                ASTNodeType.METHOD_INVOCATION) if x.member == 'intersected_var'
        ][0]

        self.assertFalse(
            is_match_to_the_conditions(ast, m_inv, m_decl_original))
 def test_determine_type_with_overridden_functions(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'invoke_overridden'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'overridden_func'
     ]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'overridden_func'
     ][0]
     d = {'overridden_func': m_decl_original}
     type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)
     self.assertEqual(type, InlineTypesAlgorithms.DO_NOTHING)
Beispiel #19
0
 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
Beispiel #20
0
def get_method_ast(filename: str, class_name: str, method_name: str) -> AST:
    current_directory = Path(__file__).absolute().parent
    filepath = current_directory / filename
    ast = AST.build_from_javalang(build_ast(str(filepath)))

    try:
        class_declaration = next(
            node for node in ast.get_root().types
            if node.node_type == ASTNodeType.CLASS_DECLARATION
            and node.name == class_name)

        method_declaration = next(node for node in class_declaration.methods
                                  if node.name == method_name)
    except StopIteration:
        raise RuntimeError(
            f"Failed to find method {method_name} in class {class_name} in file {filepath}"
        )

    return ast.get_subtree(method_declaration)
Beispiel #21
0
def _get_method_subtree(class_decl: List[str]) -> AST:
    with NamedTemporaryFile(delete=False) as f:
        _name = f.name
        f.write('\n'.join(class_decl).encode())
    try:
        javalang_ast = build_ast(_name)
        ast = AST.build_from_javalang(javalang_ast)
        os.unlink(_name)
    except JavaSyntaxError as e:
        os.unlink(_name)
        raise e

    class_node = list(ast.get_proxy_nodes(ASTNodeType.CLASS_DECLARATION))[0]
    objects_to_consider = list(class_node.methods) + \
        list(class_node.constructors)

    method_node = objects_to_consider[0]
    ast_subtree = ast.get_subtree(method_node)
    return ast_subtree
Beispiel #22
0
    def _get_method_ast(self, method_name) -> AST:
        path = str(Path(__file__).absolute().parent / "ScopeTest.java")
        ast = AST.build_from_javalang(build_ast(path))
        package_declaration = ast.get_root()

        assert len(package_declaration.types) == 1 and \
            package_declaration.types[0].node_type == ASTNodeType.CLASS_DECLARATION

        class_declaration = package_declaration.types[0]

        try:
            return next(
                ast.get_subtree(method_declaration)
                for method_declaration in class_declaration.methods
                if method_declaration.name == method_name)
        except StopIteration:
            raise ValueError(
                f"There is no method {method_name} in class {class_declaration.name}"
            )
    def test_determine_type_without_variables_declaration(self):
        filepath = self.current_directory / "Example.java"
        ast = AST.build_from_javalang(build_ast(filepath))
        m_decl = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'method'
        ][0]
        m_decl_original = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'method_without_params'
        ][0]
        m_inv = [
            x for x in ast.get_subtree(m_decl).get_proxy_nodes(
                ASTNodeType.METHOD_INVOCATION)
            if x.member == 'method_without_params'
        ][0]
        d = {'method_without_params': [m_decl_original]}
        type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)
        self.assertEqual(
            type, InlineTypesAlgorithms.WITHOUT_RETURN_WITHOUT_ARGUMENTS)

        # We consider all cases (with or without return)
        # if there are no variables, declared in invoked function

        m_decl = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'method_with_return_not_var_decl'
        ][0]
        m_decl_original = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'closeServer_return'
        ][0]
        m_inv = [
            x for x in ast.get_subtree(m_decl).get_proxy_nodes(
                ASTNodeType.METHOD_INVOCATION)
            if x.member == 'closeServer_return'
        ][0]
        d = {'closeServer_return': [m_decl_original]}
        type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)

        self.assertEqual(type,
                         InlineTypesAlgorithms.WITH_RETURN_WITHOUT_ARGUMENTS)
 def test_determine_type_with_return_without_parameters(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'reset_return_var_decl'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'closeServer_return'
     ][0]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION)
         if x.member == 'closeServer_return'
     ][0]
     d = {'closeServer_return': [m_decl_original]}
     type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)
     self.assertEqual(type,
                      InlineTypesAlgorithms.WITH_RETURN_WITHOUT_ARGUMENTS)
 def test_determine_type_with_non_intersected_variables_declaration(self):
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'test_not_intersected_var_decl'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'intersected_var'
     ][0]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'intersected_var'
     ][0]
     d = {'intersected_var': [m_decl_original]}
     type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)
     self.assertTrue(type in [
         InlineTypesAlgorithms.WITH_RETURN_WITHOUT_ARGUMENTS,
         InlineTypesAlgorithms.WITHOUT_RETURN_WITHOUT_ARGUMENTS
     ])
 def test_determine_type_with_invalid_functions(self):
     """Tests if we have invocation,
     but we didn't find it in the list of method declarations
     in current class."""
     filepath = self.current_directory / "Example.java"
     ast = AST.build_from_javalang(build_ast(filepath))
     m_decl = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'invoke_overridden'
     ][0]
     m_decl_original = [
         x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
         if x.name == 'overridden_func'
     ]
     m_inv = [
         x for x in ast.get_subtree(m_decl).get_proxy_nodes(
             ASTNodeType.METHOD_INVOCATION) if x.member == 'overridden_func'
     ][0]
     d = {'SOME_RANDOM_NAME': m_decl_original}
     type = determine_algorithm_insertion_type(ast, m_decl, m_inv, d)
     self.assertEqual(type, InlineTypesAlgorithms.DO_NOTHING)
Beispiel #27
0
    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)
    def test_inline_with_return_type_but_not_returning(self):
        """
        Test check whether we can inline code function with return type, but actually
        this function is not saving return value,
        so we do not need to declare a variable

        """
        algorithm = InlineWithReturnWithoutArguments()
        file = self.current_directory / 'InlineExamples' / 'ReturnTypeUseless.java'
        temp_filename = self.current_directory / 'temp.java'
        test_example = self.current_directory / 'InlineTestExamples' / 'ReturnTypeUseless.java'
        ast = AST.build_from_javalang(build_ast(file))
        m_decl = [
            x for x in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION)
            if x.name == 'invocation'
        ][0]
        body_start_line, body_end_line = method_body_lines(m_decl, file)

        algorithm.inline_function(file, 36, body_start_line, body_end_line,
                                  temp_filename)
        with open(temp_filename, encoding='utf-8') as actual_file, \
                open(test_example, encoding='utf-8') as test_ex:
            self.assertEqual(actual_file.read(), test_ex.read())
        temp_filename.unlink()
Beispiel #29
0
 def _build_ast(self, filename: str):
     javalang_ast = build_ast(
         str(Path(__file__).parent.absolute() / filename))
     return AST.build_from_javalang(javalang_ast)
Beispiel #30
0
def count_all_class_declarations(filename: str) -> int:
    ast = AST.build_from_javalang(build_ast(str(filename)))
    return len(list(ast.get_proxy_nodes(ASTNodeType.CLASS_DECLARATION)))