예제 #1
0
def determine_algorithm_insertion_type(
        ast: AST, method_node: ASTNode, invocation_node: ASTNode,
        dict_original_nodes: Dict[str,
                                  List[ASTNode]]) -> InlineTypesAlgorithms:
    """

    :param ast: ast tree
    :param dict_original_nodes: dict with names of function as key
    and list of ASTNode as values
    :param method_node: Method declaration. In this method invocation occurred
    :param invocation_node: invocation node
    :return: InlineTypesAlgorithms enum
    """

    original_invoked_method = dict_original_nodes.get(invocation_node.member,
                                                      [])
    # ignore overridden functions
    if (len(original_invoked_method)
            == 0) or (len(original_invoked_method) > 1):
        return InlineTypesAlgorithms.DO_NOTHING
    else:
        original_method = original_invoked_method[0]
        if not original_method.parameters:
            if not original_method.return_type:
                # Find the original method declaration by the name of method invocation
                var_decls = set(
                    get_variables_decl_in_node(
                        ast.get_subtree(original_method)))
                return check_whether_method_has_return_type(
                    ast.get_subtree(method_node), var_decls)
            else:
                return InlineTypesAlgorithms.WITH_RETURN_WITHOUT_ARGUMENTS
        else:
            return InlineTypesAlgorithms.DO_NOTHING
예제 #2
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
예제 #3
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)
예제 #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],
                )
예제 #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())
예제 #6
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)
예제 #7
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}.")
예제 #8
0
def _find_local_method_invocations(method_ast: AST) -> Set[str]:
    invoked_methods: Set[str] = set()
    for method_invocation in method_ast.get_proxy_nodes(
            ASTNodeType.METHOD_INVOCATION):
        if method_invocation.qualifier is None:
            invoked_methods.add(method_invocation.member)

    return invoked_methods
예제 #9
0
 def value(self, ast: AST) -> List[int]:
     lines: List[int] = []
     for node in ast.get_proxy_nodes(ASTNodeType.METHOD_DECLARATION):
         method_name = node.name
         if method_name.startswith('get') and self._check_body_nodes(
                 node.body):
             lines.append(node.line)
     return sorted(lines)
예제 #10
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)
예제 #11
0
def get_variables_decl_in_node(method_decl: AST) -> List[str]:
    names = []
    for x in method_decl.get_proxy_nodes(ASTNodeType.VARIABLE_DECLARATOR):
        if hasattr(x, 'name'):
            names.append(x.name)
        elif hasattr(x, 'names'):
            names.extend(x.names)

    for x in method_decl.get_proxy_nodes(ASTNodeType.VARIABLE_DECLARATION):
        if hasattr(x, 'name'):
            names.append(x.name)
        elif hasattr(x, 'names'):
            names.extend(x.names)

    for x in method_decl.get_proxy_nodes(ASTNodeType.TRY_RESOURCE):
        names.append(x.name)

    return names
예제 #12
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.names)

    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
예제 #13
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
예제 #14
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
예제 #15
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
예제 #16
0
 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)
예제 #17
0
    def parameters(self) -> Dict[str, AST]:
        parameters: Dict[str, AST] = {}
        for parameter_node in self.children_with_type(
                self.root, ASTNodeType.FORMAL_PARAMETER):
            parameter_name_node = next(
                iter(
                    self.children_with_type(parameter_node,
                                            ASTNodeType.STRING)))
            parameter_name = self.get_attr(parameter_name_node, 'string')
            parameters[parameter_name] = AST(
                dfs_tree(self.tree, parameter_node), parameter_node)

        return parameters
예제 #18
0
파일: ncss.py 프로젝트: lyriccoder/veniq
    def value(self, ast: AST) -> int:
        metric = 0
        for node in ast.get_proxy_nodes(*NCSSMetric._keyword_node_types,
                                        *NCSSMetric._declarations_node_types,
                                        *NCSSMetric._misc_node_types):
            metric += 1

            if node.node_type == ASTNodeType.IF_STATEMENT and self._has_pure_else_statements(
                    node):
                metric += 1
            elif node.node_type == ASTNodeType.TRY_STATEMENT and self._has_finally_block(
                    node):
                metric += 1

        return metric
예제 #19
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}'."
            )
예제 #20
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)
예제 #21
0
 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)
예제 #22
0
 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))
예제 #23
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)
예제 #24
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)
예제 #25
0
 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)
예제 #26
0
 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()
예제 #27
0
    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))
예제 #28
0
    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()
예제 #29
0
파일: recommend.py 프로젝트: aiovlev/veniq
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
예제 #30
0
파일: utils.py 프로젝트: lyriccoder/veniq
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)