Пример #1
0
    def testToStringStartStop(self):
        input = InputStream('x = 3 * 0;')
        lexer = TestLexer2(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceRange(4, 8, '0')

        self.assertEquals(rewriter.getDefaultText(), 'x = 0;')
        self.assertEquals(rewriter.getText('default', Interval(0, 9)),
                          'x = 0;')
        self.assertEquals(rewriter.getText('default', Interval(4, 8)), '0')
Пример #2
0
    def testToStringStartStop(self):
        input = InputStream('x = 3 * 0;')
        lexer = TestLexer2(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceRange(4, 8, '0')

        self.assertEqual(rewriter.getDefaultText(), 'x = 0;')
        self.assertEqual(rewriter.getText('default', 0, 9), 'x = 0;')
        self.assertEqual(rewriter.getText('default', 4, 8), '0')
Пример #3
0
class GetMethodTextPullUpMethodRefactoringListener(JavaParserLabeledListener):

    def __init__(self, common_token_stream: CommonTokenStream = None, child_class=None, moved_methods=None):

        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if child_class is None:
            self.moved_methods = []
        else:
            self.children_class = child_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        self.is_children_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.tempdeclarationcode = ""
        self.method_text = ""

    def enterMethodDeclaration(self, ctx: JavaParserLabeled.MethodDeclarationContext):

        if self.is_children_class:

            method_identifier = ctx.IDENTIFIER().getText()
            if self.moved_methods == method_identifier:
                methodDefctx = ctx.parentCtx.parentCtx
                start_index = methodDefctx.start.tokenIndex
                stop_index = methodDefctx.stop.tokenIndex
                self.method_text = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    start=start_index,
                    stop=stop_index)

        else:
            return None

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        print("children class in get text refactor:", self.children_class)
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier in self.children_class:
            self.is_children_class = True

        else:
            print("enter other class")
            self.is_children_class = False
Пример #4
0
def main(_):
    subject = """<?php

$heredocString = <<<TXT
HEREDOC TEXT
TXT;
 
$heredocString = <<<TXT
HEREDOC TEXT
TXT
;

"""
    lexer = PhpLexer(InputStream(subject))
    stream = CommonTokenStream(lexer)

    writer = TokenStreamRewriter(stream)
    sys.stdout.write(
        writer.getText(TokenStreamRewriter.DEFAULT_PROGRAM_NAME, (0, 100)))
Пример #5
0
class PullUpFieldGetTextFieldListener(JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream,
                 child=None,
                 field=None):
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        if child is None:
            raise ValueError("source_class is None")
        else:
            self.child = child

        if field is None:
            raise ValueError("field is None")
        else:
            self.field = field

        self.field_text = ""

    def enterFieldDeclaration(self,
                              ctx: JavaParserLabeled.FieldDeclarationContext):
        ctx1 = ctx.parentCtx.parentCtx.parentCtx.parentCtx
        class_identifier = ctx1.IDENTIFIER().getText()
        if class_identifier in self.child:
            # field_identifier = ctx.variableDeclarators().getText().split(",")
            field_identifier = ctx.variableDeclarators().variableDeclarator(
                0).variableDeclaratorId().IDENTIFIER().getText()
            if self.field in field_identifier:
                ctx1 = ctx.parentCtx.parentCtx
                start_index = ctx1.start.tokenIndex
                stop_index = ctx1.stop.tokenIndex
                self.field_text = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=start_index,
                    stop=stop_index)
Пример #6
0
    def testToStringStartStop2(self):
        input = InputStream('x = 3 * 0 + 2 * 0;')
        lexer = TestLexer2(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        self.assertEquals('x = 3 * 0 + 2 * 0;', rewriter.getDefaultText())

        # replace 3 * 0 with 0
        rewriter.replaceRange(4, 8, '0')
        self.assertEquals('x = 0 + 2 * 0;', rewriter.getDefaultText())
        self.assertEquals('x = 0 + 2 * 0;', rewriter.getText('default', Interval(0, 17)))
        self.assertEquals('0', rewriter.getText('default', Interval(4, 8)))
        self.assertEquals('x = 0', rewriter.getText('default', Interval(0, 8)))
        self.assertEquals('2 * 0', rewriter.getText('default', Interval(12, 16)))

        rewriter.insertAfter(17, "// comment")
        self.assertEquals('2 * 0;// comment', rewriter.getText('default', Interval(12, 18)))

        self.assertEquals('x = 0', rewriter.getText('default', Interval(0, 8)))
Пример #7
0
    def testToStringStartStop2(self):
        input = InputStream('x = 3 * 0 + 2 * 0;')
        lexer = TestLexer2(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        self.assertEqual('x = 3 * 0 + 2 * 0;', rewriter.getDefaultText())

        # replace 3 * 0 with 0
        rewriter.replaceRange(4, 8, '0')
        self.assertEqual('x = 0 + 2 * 0;', rewriter.getDefaultText())
        self.assertEqual('x = 0 + 2 * 0;', rewriter.getText('default', 0, 17))
        self.assertEqual('0', rewriter.getText('default', 4, 8))
        self.assertEqual('x = 0', rewriter.getText('default', 0, 8))
        self.assertEqual('2 * 0', rewriter.getText('default', 12, 16))

        rewriter.insertAfter(17, "// comment")
        self.assertEqual('2 * 0;// comment', rewriter.getText('default', 12, 18))

        self.assertEqual('x = 0', rewriter.getText('default', 0, 8))
Пример #8
0
class MakeMethodNonStaticRefactoringListener(JavaParserLabeledListener):
    """

    To implement Make Method None-Static refactoring based on its actors.

    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 target_class: str = None,
                 target_methods: list = None):
        """


        """

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if target_class is None:
            raise ValueError("source_class is None")
        else:
            self.target_class = target_class
        if target_methods is None or len(target_methods) == 0:
            raise ValueError("target method must have one method name")
        else:
            self.target_methods = target_methods

        self.target_class_data = None
        self.is_target_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.target_class:
            self.is_target_class = True
            self.target_class_data = {'constructors': []}
        else:
            self.is_target_class = False

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_target_class:
            have_default_constructor = False
            for constructor in self.target_class_data['constructor']:
                if len(constructor.parameters) == 0:
                    have_default_constructor = True
                    break
            if not have_default_constructor:
                self.token_stream_rewriter.insertBeforeIndex(
                    index=ctx.stop.tokenIndex - 1,
                    text=
                    f'\n\t public {self.target_class_data["constructors"][0]} ()\n\t{{}}\n'
                )
            self.is_target_class = False

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.is_target_class:
            if ctx.IDENTIFIER().getText() in self.target_methods:
                grand_parent_ctx = ctx.parentCtx.parentCtx
                if grand_parent_ctx.modifier():
                    if len(grand_parent_ctx.modifier()) == 2:
                        self.token_stream_rewriter.delete(
                            program_name=self.token_stream_rewriter.
                            DEFAULT_PROGRAM_NAME,
                            from_idx=grand_parent_ctx.modifier(
                                1).start.tokenIndex - 1,
                            to_idx=grand_parent_ctx.modifier(
                                1).stop.tokenIndex)
                    else:
                        if grand_parent_ctx.modifier(0).getText() == 'static':
                            self.token_stream_rewriter.delete(
                                program_name=self.token_stream_rewriter.
                                DEFAULT_PROGRAM_NAME,
                                from_idx=grand_parent_ctx.modifier(
                                    0).start.tokenIndex - 1,
                                to_idx=grand_parent_ctx.modifier(
                                    0).stop.tokenIndex)
                else:
                    return None

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_target_class:
            if ctx.formalParameters().formalParameterList():
                constructor_parameters = [
                    ctx.formalParameters().formalParameterList().children[i]
                    for i in range(
                        len(ctx.formalParameters().formalParameterList().
                            children)) if i % 2 == 0
                ]
            else:
                constructor_parameters = []
            constructor_text = ''
            for modifier in ctx.parentCtx.parentCtx.modifier():
                constructor_text += modifier.getText() + ' '
                constructor_text += ctx.IDENTIFIER().getText()
            constructor_text += ' ( '
            for parameter in constructor_parameters:
                constructor_text += parameter.typeType().getText() + ' '
                constructor_text += parameter.variableDeclaratorId().getText(
                ) + ', '
            if constructor_parameters:
                constructor_text = constructor_text[:len(constructor_text) - 2]
            constructor_text += ')\n\t{'
            constructor_text += self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.block().start.tokenIndex + 1,
                stop=ctx.block().stop.tokenIndex - 1)
            constructor_text += '}\n'
            self.target_class_data['constructors'].append(
                ConstructorOrMethod(
                    name=self.target_class,
                    parameters=[
                        Parameter(parameterType=p.typeType().getText(),
                                  name=p.variableDeclaratorId().IDENTIFIER().
                                  getText()) for p in constructor_parameters
                    ],
                    text=constructor_text))
Пример #9
0
    def do_refactor(self):
        program = get_program(
            self.source_filenames)  # getting the program packages
        _sourceclass = program.packages[self.package_name].classes[
            self.class_name]
        target_class_name = _sourceclass.superclass_name
        removemethod, removemethod1 = get_cons(
            program, self.package_name, target_class_name,
            self.class_name)  # Similar cons in other classes
        _targetclass = program.packages[
            self.package_name].classes[target_class_name]
        mets = program.packages[self.package_name].classes[
            self.class_name].methods
        _method_name = []
        for methodName, method in mets.items():
            if method.is_constructor:
                _method_name = method
                break
        tokens_info = TokensInfo(_method_name.parser_context)

        if not _method_name.is_constructor:
            return False
        param_dict = {}
        len_params = {}

        Rewriter_ = Rewriter(program, self.filename_mapping)
        for remove in removemethod:
            flag2 = False
            _methodd = removemethod[remove]
            len_params[remove] = len(_methodd[0].split(","))
            not_present = removemethod1
            if _methodd is not None:
                _methodds = _methodd[0]
                _method = program.packages[
                    self.package_name].classes[remove].methods[str(_methodds)]
                params = ""
                params2 = ""
                for param in _method.parameters:
                    flag = False
                    for x in not_present:
                        for y in x:
                            if param[1] in y:
                                flag = True
                                flag2 = True
                    if not flag:
                        params += param[1] + ","
                    params2 += param[0] + " " + param[1] + ","
                    flag = False
                param_dict[remove] = params2[:-1]
                _method_token_info = TokensInfo(_method.parser_context)
                if flag2:
                    str1 = ""
                    for x in not_present:
                        for y in x:
                            str1 += y + ";" + "\n\t"
                    Rewriter_.replace(
                        _method_token_info, "public " + remove + "(" +
                        params2[:-1] + ")" + "{\n\t" + "super(" + params[:-1] +
                        ");" + "\n\t " + str1 + "}")
                else:
                    Rewriter_.replace(
                        _method_token_info,
                        "public " + remove + "(" + params2[:-1] + ")" +
                        "{\n\t" + "super(" + params[:-1] + ");" + "\n\t}")

        class_tokens_info = TokensInfo(_targetclass.parser_context.classBody())
        class_tokens_info.stop = class_tokens_info.start
        key = min(len_params, key=len_params.get)
        _method_name1 = program.packages[
            self.package_name].classes[key].methods[removemethod[key][0]]
        tokens_info = TokensInfo(_method_name1.parser_context)
        singlefileelement = SingleFileElement(_method_name1.parser_context,
                                              _method_name1.filename)
        token_stream_rewriter = TokenStreamRewriter(
            singlefileelement.get_token_stream())
        strofmethod = token_stream_rewriter.getText(
            program_name=token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            start=tokens_info.start,
            stop=tokens_info.stop)
        strofmethod = strofmethod.replace(_method_name1.class_name,
                                          target_class_name)

        Rewriter_.insert_after(tokens_info=class_tokens_info, text=strofmethod)
        Rewriter_.apply()

        return True
Пример #10
0
class ExtractSubClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None):

        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if moved_fields is None:
            self.moved_fields = []
        else:
            self.moved_fields = moved_fields

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        if new_class is None:
            raise ValueError("new_class is None")
        else:
            self.new_class = new_class

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
            self.code += self.NEW_LINE * 2
            self.code += f"// New class({self.new_class}) generated by CodART" + self.NEW_LINE
            self.code += f"class {self.new_class} extends {self.source_class}{self.NEW_LINE}" + "{" + self.NEW_LINE
        else:
            self.is_source_class = False

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_source_class:
            self.code += "}"
            self.is_source_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):

        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.code)

    def enterVariableDeclaratorId(
            self, ctx: JavaParserLabeled.VariableDeclaratorIdContext):
        if not self.is_source_class:
            return None
        field_identifier = ctx.IDENTIFIER().getText()
        if field_identifier in self.moved_fields:
            self.detected_field = field_identifier

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        # field_names = ctx.variableDeclarators().getText().split(",")
        field_identifier = ctx.variableDeclarators().variableDeclarator(
            0).variableDeclaratorId().IDENTIFIER().getText()
        field_names = list()
        field_names.append(field_identifier)
        print("field_names=", field_names)
        print("Here")
        grand_parent_ctx = ctx.parentCtx.parentCtx
        if self.detected_field in field_names:
            if (not grand_parent_ctx.modifier()):
                # print("******************************************")
                modifier = ""
            else:
                modifier = grand_parent_ctx.modifier(0).getText()
            field_type = ctx.typeType().getText()
            self.code += f"{self.TAB}{modifier} {field_type} {self.detected_field};{self.NEW_LINE}"
            # delete field from source class
            # field_names.remove(self.detected_field)
            # if field_names:
            #     self.token_stream_rewriter.replaceRange(
            #         from_idx=grand_parent_ctx.start.tokenIndex,
            #         to_idx=grand_parent_ctx.stop.tokenIndex,
            #         text=f"{modifier} {field_type} {','.join(field_names)};"
            #     )
            # else:
            # self.token_stream_rewriter.delete(
            #     program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            #     from_idx=grand_parent_ctx.start.tokenIndex,
            #     to_idx=grand_parent_ctx.stop.tokenIndex
            # )
            self.detected_field = None

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if method_identifier in self.moved_methods:
            self.detected_method = method_identifier

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if self.detected_method == method_identifier:
            start_index = ctx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex
            method_text = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index)
            self.code += (self.NEW_LINE + self.TAB + method_text +
                          self.NEW_LINE)
            # delete method from source class
            # self.token_stream_rewriter.delete(
            #     program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            #     from_idx=start_index,
            #     to_idx=stop_index
            # )
            self.detected_method = None
Пример #11
0
class MoveClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement the move class refactoring
    a stream of tokens is sent to the listener, to build an object token_stream_rewriter
    and we move all class methods and fields from the source package to the target package
    """

    def __init__(self, common_token_stream: CommonTokenStream = None, class_identifier: str = None,
                 source_package: str = None, target_package: str = None, filename: str = None, dirname: str = None):
        """
        :param common_token_stream: used to edit the content of the parsers
        """
        self.enter_class = False
        self.token_stream = common_token_stream
        self.class_found = False
        self.class_fields = []
        self.class_methods = []

        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

        if class_identifier is not None:
            self.class_identifier = class_identifier
        else:
            raise ValueError("class_identifier is None")

        if filename is not None:
            self.filename = filename
        else:
            raise ValueError("filename is None")

        if dirname is not None:
            self.dirname = dirname
        else:
            raise ValueError("dirname is None")

        if source_package is not None:
            self.source_package = source_package
        else:
            raise ValueError("source_package is None")

        if target_package is not None:
            self.target_package = target_package
        else:
            raise ValueError("target_package is None")

        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = f"package {self.target_package};{self.NEW_LINE}{self.NEW_LINE}"

    # Exit a parse tree produced by JavaParserLabeled#importDeclaration.
    def exitImportDeclaration(self, ctx: JavaParserLabeled.ImportDeclarationContext):
        text_to_replace = "import " + ctx.qualifiedName().getText() + ';'
        if ctx.STATIC() is not None:
            text_to_replace = text_to_replace.replace("import", "import static")

        self.code += text_to_replace + self.NEW_LINE

    # Enter a parse tree produced by JavaParserLabeled#packageDeclaration.
    def enterPackageDeclaration(self, ctx: JavaParserLabeled.PackageDeclarationContext):
        package_name = ctx.getText()[7:-1]
        print(package_name)
        if package_name != self.source_package:
            raise ValueError(f"The package {package_name} in the file isn't equal to the source package!")

    # Exit a parse tree produced by JavaParserLabeled#classBodyDeclaration2.
    def exitClassBodyDeclaration2(self, ctx: JavaParserLabeled.ClassBodyDeclaration2Context):
        self.enter_class = False
        try:
            if ctx.memberDeclaration().classDeclaration().IDENTIFIER().getText() != self.class_identifier:
                return
        except Exception:
            return

        self.class_found = True

        start_index = ctx.start.tokenIndex
        stop_index = ctx.stop.tokenIndex

        # get the class body from the token_stream_rewriter
        class_body = self.token_stream_rewriter.getText(
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            start=start_index,
            stop=stop_index
        )

        self.code += f"import {self.source_package}.*;"
        self.code += self.NEW_LINE * 2
        self.code += f"// Class \"{self.class_identifier}\" moved here " \
                     f"from package {self.source_package} by CodART" + self.NEW_LINE + \
                     f"{class_body}"

        # delete class declaration from source class
        self.token_stream_rewriter.delete(
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            from_idx=start_index,
            to_idx=stop_index
        )

        old_file = open(self.filename, 'w')
        old_file.write(self.token_stream_rewriter.getDefaultText().replace("\r", ""))

        print("----------------------------")
        print("Class attributes: ", str(self.class_fields))
        print("Class methods: ", str(self.class_methods))
        print("----------------------------")

    # Exit a parse tree produced by JavaParserLabeled#typeDeclaration.
    def exitTypeDeclaration(self, ctx: JavaParserLabeled.TypeDeclarationContext):
        if ctx.classDeclaration() is not None:
            self.enter_class = False
            if ctx.classDeclaration().IDENTIFIER().getText() != self.class_identifier:
                return

            self.enter_class = True
            self.class_found = True

            start_index = ctx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex

            # get the class body from the token_stream_rewriter
            class_body = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index
            )

            self.code += f"import {self.source_package}.*;"
            self.code += self.NEW_LINE * 2
            self.code += f"// Class \"{self.class_identifier}\" moved here " \
                         f"from package {self.source_package} by CodART" + self.NEW_LINE + \
                         f"{class_body}"

            # delete class declaration from source class
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=start_index,
                to_idx=stop_index
            )

            print("----------------------------")
            print("Class attributes: ", str(self.class_fields))
            print("Class methods: ", str(self.class_methods))
            print("----------------------------")

    # Enter a parse tree produced by JavaParserLabeled#fieldDeclaration.
    def enterFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.enter_class:
            return

        list_of_fields = ctx.variableDeclarators().getText().split(",")

        for field in list_of_fields:
            self.class_fields.append(field)

    # Enter a parse tree produced by JavaParserLabeled#methodDeclaration.
    def enterMethodDeclaration(self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.enter_class:
            return
        method_name = ctx.IDENTIFIER().getText()
        self.class_methods.append(method_name)

    # Exit a parse tree produced by JavaParserLabeled#compilationUnit.
    def exitCompilationUnit(self, ctx: JavaParserLabeled.CompilationUnitContext):
        if not self.class_found:
            raise ValueError(f"Class \"{self.class_identifier}\" NOT FOUND!")

        file_address = self.dirname + '/' + self.target_package.replace('.',
                                                                        '/') + '/' + self.class_identifier + '.java'

        new_file = open(file_address, 'w')
        new_file.write(self.code.replace("\r", ""))
        print(f"The class \"{self.class_identifier}\" moved to the target package successfully!")
Пример #12
0
class ExtractSubClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None,
                 output_path: str = ""):

        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if moved_fields is None:
            self.moved_fields = []
        else:
            self.moved_fields = moved_fields

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        if new_class is None:
            raise ValueError("new_class is None")
        else:
            self.new_class = new_class

        self.output_path = output_path

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.is_in_constructor = False

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        """
        It checks if it is source class, we generate the declaration of the new class, by appending some text to self.code.
        """
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
            self.code += self.NEW_LINE * 2
            self.code += f"// New class({self.new_class}) generated by CodART" + self.NEW_LINE
            self.code += f"class {self.new_class} extends {self.source_class}{self.NEW_LINE}" + "{" + self.NEW_LINE
            self.code += f"public {self.new_class}()" + "{ }" + self.NEW_LINE
        else:
            self.is_source_class = False

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        """
        It close the opened curly brackets If it is the source class.
        """
        if self.is_source_class:
            self.code += "}"
            self.is_source_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        """
        it writes self.code in the output path.​
        """
        child_file_name = self.new_class + ".java"
        with open(os.path.join(self.output_path, child_file_name), "w+") as f:
            f.write(self.code.replace('\r\n', '\n'))

    def enterVariableDeclaratorId(
            self, ctx: JavaParserLabeled.VariableDeclaratorIdContext):
        """
        It sets the detected field to the field if it is one of the moved fields. ​
        """
        if not self.is_source_class:
            return None
        field_identifier = ctx.IDENTIFIER().getText()
        if field_identifier in self.moved_fields:
            self.detected_field = field_identifier

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        """
        It gets the field name, if the field is one of the moved fields, we move it and delete it from the source program. ​
        """
        if not self.is_source_class:
            return None
        field_identifier = ctx.variableDeclarators().variableDeclarator(
            0).variableDeclaratorId().IDENTIFIER().getText()
        field_names = list()
        field_names.append(field_identifier)
        # print("field_names=", field_names)
        grand_parent_ctx = ctx.parentCtx.parentCtx
        if self.detected_field in field_names:
            if (not grand_parent_ctx.modifier()):
                modifier = ""
            else:
                modifier = grand_parent_ctx.modifier(0).getText()
            field_type = ctx.typeType().getText()
            self.code += f"{self.TAB}{modifier} {field_type} {self.detected_field};{self.NEW_LINE}"

            # delete field from source class ==>new
            start_index = ctx.parentCtx.parentCtx.start.tokenIndex
            stop_index = ctx.parentCtx.parentCtx.stop.tokenIndex
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=start_index,
                to_idx=stop_index)

            self.detected_field = None

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        """
        It sets the detected field to the method if it is one of the moved methods. ​
        """
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if method_identifier in self.moved_methods:
            self.detected_method = method_identifier

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        """
        It gets the method name, if the method is one of the moved methods, we move it to the subclass and delete it from the source program.
        """
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if self.detected_method == method_identifier:
            start_index = ctx.parentCtx.parentCtx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex
            method_text = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index)
            self.code += (self.NEW_LINE + self.TAB + method_text +
                          self.NEW_LINE)
            # delete method from source class
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=start_index,
                to_idx=stop_index)
            self.detected_method = None

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_source_class:
            self.is_in_constructor = True
            self.fields_in_constructor = []
            self.methods_in_constructor = []
            self.constructor_body = ctx.block()
            children = self.constructor_body.children

    def exitConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_source_class and self.is_in_constructor:
            move_constructor_flag = False
            for field in self.fields_in_constructor:
                if field in self.moved_fields:
                    move_constructor_flag = True

            for method in self.methods_in_constructor:
                if method in self.moved_methods:
                    move_constructor_flag = True

            if move_constructor_flag:
                if ctx.formalParameters().formalParameterList():
                    constructor_parameters = [
                        ctx.formalParameters().formalParameterList().
                        children[i] for i in range(
                            len(ctx.formalParameters().formalParameterList().
                                children)) if i % 2 == 0
                    ]
                else:
                    constructor_parameters = []

                constructor_text = ''
                for modifier in ctx.parentCtx.parentCtx.modifier():
                    constructor_text += modifier.getText() + ' '
                constructor_text += self.new_class
                constructor_text += ' ( '
                for parameter in constructor_parameters:
                    constructor_text += parameter.typeType().getText() + ' '
                    constructor_text += parameter.variableDeclaratorId(
                    ).getText() + ', '
                if constructor_parameters:
                    constructor_text = constructor_text[:len(constructor_text
                                                             ) - 2]
                constructor_text += ')\n\t{'
                constructor_text += self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=ctx.block().start.tokenIndex + 1,
                    stop=ctx.block().stop.tokenIndex - 1)
                constructor_text += '}\n'
                self.code += constructor_text
                start_index = ctx.parentCtx.parentCtx.start.tokenIndex
                stop_index = ctx.parentCtx.parentCtx.stop.tokenIndex
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=start_index,
                    to_idx=stop_index)

        self.is_in_constructor = False

    def enterExpression21(self, ctx: JavaParserLabeled.Expression21Context):
        if self.is_source_class and self.is_in_constructor:
            if len(ctx.children[0].children) == 1:
                self.fields_in_constructor.append(ctx.children[0].getText())
            else:
                self.fields_in_constructor.append(
                    ctx.children[0].children[-1].getText())

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        if self.is_source_class and self.is_in_constructor:
            self.methods_in_constructor.append(ctx.IDENTIFIER())
Пример #13
0
class PullUpMethodRefactoringListener(JavaParserLabeledListener):
    """

    To implement pull-up method refactoring based on its actors.

    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 destination_class: str = None,
                 children_class: list = None,
                 moved_methods=None,
                 method_text: str = None):
        """


        """

        if method_text is None:
            self.mothod_text = []
        else:
            self.method_text = method_text

        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if children_class is None:
            self.children_class = []
        else:
            self.children_class = children_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if destination_class is None:
            raise ValueError("source_class is None")
        else:
            self.destination_class = destination_class

        self.is_children_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.tempdeclarationcode = ""

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):

        if self.is_children_class:

            method_identifier = ctx.IDENTIFIER().getText()
            if self.moved_methods == method_identifier:
                methodDefctx = ctx.parentCtx.parentCtx
                start_index = methodDefctx.start.tokenIndex
                stop_index = methodDefctx.stop.tokenIndex
                self.method_text = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=start_index,
                    stop=stop_index)

                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=methodDefctx.start.tokenIndex,
                    to_idx=methodDefctx.stop.tokenIndex)
        else:
            return None

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier in self.children_class:
            self.is_children_class = True

        else:
            # Enter another class
            self.is_children_class = False

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        classDecctx = ctx.parentCtx
        if hasattr(classDecctx, "IDENTIFIER"):
            class_identifier = classDecctx.IDENTIFIER().getText()

            if class_identifier in self.destination_class:
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.start.tokenIndex + 1,
                    to_idx=ctx.start.tokenIndex + 1,
                    text="\n" + self.method_text + "\n")

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_children_class:
            self.is_children_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):

        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.code)
Пример #14
0
class InlineClassRefactoringListener(JavaParserLabeledListener):
    """

    To implement inline class refactoring based on its actors.

    Creates a new class and move fields and methods from two old class to the new one, then delete the two class

    """

    def __init__(
            self, common_token_stream: CommonTokenStream = None,
            source_class: str = None, source_class_data: dict = None,
            target_class: str = None, target_class_data: dict = None, is_complete: bool = False):
        """


        """

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        if target_class is None:
            raise ValueError("new_class is None")
        else:
            self.target_class = target_class
        if target_class:
            self.target_class = target_class
        if source_class_data:
            self.source_class_data = source_class_data
        else:
            self.source_class_data = {'fields': [], 'methods': [], 'constructors': []}
        if target_class_data:
            self.target_class_data = target_class_data
        else:
            self.target_class_data = {'fields': [], 'methods': [], 'constructors': []}

        self.field_that_has_source = []
        self.has_source_new = False

        self.is_complete = is_complete
        self.is_target_class = False
        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
            self.is_target_class = False
        elif class_identifier == self.target_class:
            self.is_target_class = True
            self.is_source_class = False
        else:
            self.is_target_class = False
            self.is_source_class = False

    def exitClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_target_class and (self.source_class_data['fields'] or
                                     self.source_class_data['constructors'] or
                                     self.source_class_data['methods']):
            if not self.is_complete:
                final_fields = merge_fields(self.source_class_data['fields'], self.target_class_data['fields'],
                                            self.target_class)
                final_constructors = merge_constructors(self.source_class_data['constructors'],
                                                        self.target_class_data['constructors'])
                final_methods = merge_methods(self.source_class_data['methods'], self.target_class_data['methods'])
                text = '\t'
                for field in final_fields:
                    text += field.text + '\n'
                for constructor in final_constructors:
                    text += constructor.text + '\n'
                for method in final_methods:
                    text += method.text + '\n'
                self.token_stream_rewriter.insertBeforeIndex(
                    index=ctx.stop.tokenIndex,
                    text=text
                )
                self.is_complete = True
            else:
                self.is_target_class = False
        elif self.is_source_class:
            if ctx.parentCtx.classOrInterfaceModifier(0) is None:
                return
            self.is_source_class = False
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=ctx.parentCtx.classOrInterfaceModifier(0).start.tokenIndex,
                to_idx=ctx.stop.tokenIndex
            )

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if self.is_source_class:
            self.code += self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.start.tokenIndex + 1,
                stop=ctx.stop.tokenIndex - 1
            )
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=ctx.parentCtx.start.tokenIndex,
                to_idx=ctx.parentCtx.stop.tokenIndex
            )
        else:
            return None

    def enterFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if self.is_source_class or self.is_target_class:
            field_text = ''
            for child in ctx.children:
                if child.getText() == ';':
                    field_text = field_text[:len(field_text) - 1] + ';'
                    break
                field_text += child.getText() + ' '

            name = ctx.variableDeclarators().variableDeclarator(0).variableDeclaratorId().IDENTIFIER().getText()

            if ctx.typeType().classOrInterfaceType() is not None and \
                    ctx.typeType().classOrInterfaceType().getText() == self.source_class:
                self.field_that_has_source.append(name)
                return

            modifier_text = ''
            for modifier in ctx.parentCtx.parentCtx.modifier():
                modifier_text += modifier.getText() + ' '
            field_text = modifier_text + field_text
            if self.is_source_class:
                self.source_class_data['fields'].append(Field(name=name, text=field_text))
            else:
                self.target_class_data['fields'].append(Field(name=name, text=field_text))

    def exitFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if self.is_target_class:
            if ctx.typeType().classOrInterfaceType().getText() == self.source_class:
                grand_parent_ctx = ctx.parentCtx.parentCtx
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    from_idx=grand_parent_ctx.start.tokenIndex,
                    to_idx=grand_parent_ctx.stop.tokenIndex)

    def enterConstructorDeclaration(self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_source_class or self.is_target_class:
            if ctx.formalParameters().formalParameterList():
                constructor_parameters = [ctx.formalParameters().formalParameterList().children[i] for i in
                                          range(len(ctx.formalParameters().formalParameterList().children)) if
                                          i % 2 == 0]
            else:
                constructor_parameters = []
            constructor_text = ''
            for modifier in ctx.parentCtx.parentCtx.modifier():
                constructor_text += modifier.getText() + ' '

            if self.is_source_class:
                constructor_text += self.target_class
            else:
                constructor_text += ctx.IDENTIFIER().getText()
            constructor_text += ' ( '
            for parameter in constructor_parameters:
                constructor_text += parameter.typeType().getText() + ' '
                constructor_text += parameter.variableDeclaratorId().getText() + ', '
            if constructor_parameters:
                constructor_text = constructor_text[:len(constructor_text) - 2]
            constructor_text += ')\n\t{'
            constructor_text += self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.block().start.tokenIndex + 1,
                stop=ctx.block().stop.tokenIndex - 1
            )
            constructor_text += '}\n'
            if self.is_source_class:
                self.source_class_data['constructors'].append(ConstructorOrMethod(
                    name=self.target_class, parameters=[Parameter(parameter_type=p.typeType().getText(),
                                                                  name=p.variableDeclaratorId().IDENTIFIER().getText())
                                                        for p in constructor_parameters],
                    text=constructor_text, constructor_body=self.token_stream_rewriter.getText(
                        program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                        start=ctx.block().start.tokenIndex + 1,
                        stop=ctx.block().stop.tokenIndex - 1
                    )))
            else:
                self.target_class_data['constructors'].append(ConstructorOrMethod(
                    name=self.target_class, parameters=[Parameter(parameter_type=p.typeType().getText(),
                                                                  name=p.variableDeclaratorId().IDENTIFIER().getText())
                                                        for p in constructor_parameters],
                    text=constructor_text, constructor_body=self.token_stream_rewriter.getText(
                        program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                        start=ctx.block().start.tokenIndex + 1,
                        stop=ctx.block().stop.tokenIndex - 1
                    )))
                proper_constructor = get_proper_constructor(self.target_class_data['constructors'][-1],
                                                            self.source_class_data['constructors'])

                if proper_constructor is None:
                    return

                self.token_stream_rewriter.insertBeforeIndex(
                    index=ctx.stop.tokenIndex,
                    text=proper_constructor.constructorBody
                )

    def enterMethodDeclaration(self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.is_source_class or self.is_target_class:
            if ctx.formalParameters().formalParameterList():
                method_parameters = [ctx.formalParameters().formalParameterList().children[i] for i in
                                     range(len(ctx.formalParameters().formalParameterList().children)) if i % 2 == 0]
            else:
                method_parameters = []
            method_text = ''
            for modifier in ctx.parentCtx.parentCtx.modifier():
                method_text += modifier.getText() + ' '

            type_text = ctx.typeTypeOrVoid().getText()

            if type_text == self.source_class:
                type_text = self.target_class

                if self.is_target_class:
                    self.token_stream_rewriter.replace(
                        program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                        from_idx=ctx.typeTypeOrVoid().start.tokenIndex,
                        to_idx=ctx.typeTypeOrVoid().stop.tokenIndex,
                        text=type_text
                    )
            method_text += type_text + ' ' + ctx.IDENTIFIER().getText()
            method_text += ' ( '
            for parameter in method_parameters:
                method_text += parameter.typeType().getText() + ' '
                method_text += parameter.variableDeclaratorId().getText() + ', '
            if method_parameters:
                method_text = method_text[:len(method_text) - 2]
            method_text += ')\n\t{'
            method_text += self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.methodBody().start.tokenIndex + 1,
                stop=ctx.methodBody().stop.tokenIndex - 1
            )
            method_text += '}\n'
            if self.is_source_class:
                self.source_class_data['methods'].append(ConstructorOrMethod(
                    name=ctx.IDENTIFIER().getText(),
                    parameters=[Parameter(
                        parameter_type=p.typeType().getText(),
                        name=p.variableDeclaratorId().IDENTIFIER().getText())
                        for p in
                        method_parameters],
                    text=method_text))
            else:
                self.target_class_data['methods'].append(ConstructorOrMethod(
                    name=ctx.IDENTIFIER().getText(),
                    parameters=[Parameter(
                        parameter_type=p.typeType().getText(),
                        name=p.variableDeclaratorId().IDENTIFIER().getText())
                        for p in
                        method_parameters],
                    text=method_text))

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if ctx.IDENTIFIER() is None and ctx.IDENTIFIER().getText() in self.field_that_has_source:
            field_text = ctx.expression().getText()
            self.token_stream_rewriter.replace(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.stop.tokenIndex,
                text=field_text
            )

    def exitExpression21(self, ctx: JavaParserLabeled.Expression21Context):
        if self.has_source_new:
            self.has_source_new = False
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.stop.tokenIndex + 1
            )

    def enterExpression4(self, ctx: JavaParserLabeled.Expression4Context):
        if ctx.children[-1].children[0].getText() == self.source_class:
            self.has_source_new = True

    def enterCreatedName0(self, ctx: JavaParserLabeled.CreatedName0Context):
        if ctx.IDENTIFIER(0).getText() == self.source_class and self.target_class:
            self.token_stream_rewriter.replaceIndex(
                index=ctx.start.tokenIndex,
                text=self.target_class
            )

    def enterCreatedName1(self, ctx: JavaParserLabeled.CreatedName1Context):
        if ctx.getText() == self.source_class and self.target_class:
            self.token_stream_rewriter.replaceIndex(
                index=ctx.start.tokenIndex,
                text=self.target_class
            )

    def enterFormalParameter(self, ctx: JavaParserLabeled.FormalParameterContext):
        class_type = ctx.typeType().classOrInterfaceType()
        if class_type:
            if class_type.IDENTIFIER(0).getText() == self.source_class and self.target_class:
                self.token_stream_rewriter.replaceIndex(
                    index=class_type.start.tokenIndex,
                    text=self.target_class
                )

    def enterQualifiedName(self, ctx: JavaParserLabeled.QualifiedNameContext):
        if ctx.IDENTIFIER(0).getText() == self.source_class and self.target_class:
            self.token_stream_rewriter.replaceIndex(
                index=ctx.start.tokenIndex,
                text=self.target_class
            )

    def exitExpression0(self, ctx: JavaParserLabeled.Expression0Context):
        if ctx.primary().getText() == self.source_class and self.target_class:
            self.token_stream_rewriter.replaceIndex(
                index=ctx.start.tokenIndex,
                text=self.target_class
            )

    def enterLocalVariableDeclaration(self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if ctx.typeType().classOrInterfaceType():
            if ctx.typeType().classOrInterfaceType().getText() == self.source_class and self.target_class:
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    from_idx=ctx.typeType().start.tokenIndex,
                    to_idx=ctx.typeType().stop.tokenIndex,
                    text=self.target_class
                )
Пример #15
0
class RemoveControlFlagRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None):
        self.isRelevant = False
        self.relevantVariable = None
        self.ifStmnt = None
        self.whileStmnt = None
        self.relevantVariableValue = None
        self.lastOccurance = dict()
        self.hasBlock = False
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

    # Enter a parse tree produced by JavaParserLabeled#statement3.
    def enterStatement3(self, ctx: JavaParserLabeled.Statement3Context):
        if isinstance(ctx.statement(), JavaParserLabeled.Statement0Context):
            self.ifStmnt = ctx.statement().block().blockStatement(
                0).statement()
            self.hasBlock = True
            if isinstance(self.ifStmnt,
                          JavaParserLabeled.Statement2Context) and len(
                              self.ifStmnt.children) <= 3:
                exp = self.ifStmnt.parExpression().expression()
                if isinstance(exp, JavaParserLabeled.Expression0Context):
                    prm = exp.primary()
                    if isinstance(prm, JavaParserLabeled.Primary4Context):
                        self.isRelevant += 1
                        self.relevantVariable = prm.IDENTIFIER().getText()

                elif isinstance(exp, JavaParserLabeled.Expression8Context):
                    exp2 = exp.expression()
                    if isinstance(exp2, JavaParserLabeled.Expression0Context):
                        prm = exp2.primary()
                        if isinstance(prm, JavaParserLabeled.Primary4Context):
                            self.isRelevant += 1
                            self.relevantVariable = prm.IDENTIFIER().getText()

        elif isinstance(ctx.statement(),
                        JavaParserLabeled.Statement2Context) and len(
                            ctx.statement().children) <= 3:
            self.hasBlock = False
            self.ifStmnt = ctx.statement()
            exp = self.ifStmnt.parExpression().expression()
            if isinstance(exp, JavaParserLabeled.Expression0Context):
                prm = exp.primary()
                if isinstance(prm, JavaParserLabeled.Primary4Context):
                    self.isRelevant += 1
                    self.relevantVariable = prm.IDENTIFIER().getText()

            elif isinstance(exp, JavaParserLabeled.Expression8Context):
                exp2 = exp.expression()
                if isinstance(exp2, JavaParserLabeled.Expression0Context):
                    prm = exp2.primary()
                    if isinstance(prm, JavaParserLabeled.Primary4Context):
                        self.isRelevant += 1
                        self.relevantVariable = prm.IDENTIFIER().getText()

    # Exit a parse tree produced by JavaParserLabeled#statement3.
    def exitStatement3(self, ctx: JavaParserLabeled.Statement3Context):
        if self.isRelevant:
            if (not self.hasBlock):
                interval = self.ifStmnt.getSourceInterval()
                stmnt = self.ifStmnt.statement(0)
                interval2 = stmnt.getSourceInterval()
                self.token_stream_rewriter.replaceRange(
                    interval[0], interval[1],
                    self.token_stream_rewriter.getText('default', interval2[0],
                                                       interval2[1]))
                declarationInterval = self.lastOccurance[
                    self.relevantVariable].getSourceInterval()
                self.token_stream_rewriter.replaceRange(
                    declarationInterval[0], declarationInterval[1], "")
            else:
                interval = self.ifStmnt.parentCtx.parentCtx.getSourceInterval()
                stmnt = self.ifStmnt.statement(0)
                interval2 = stmnt.getSourceInterval()
                self.token_stream_rewriter.replaceRange(
                    interval[0], interval[1],
                    self.token_stream_rewriter.getText('default', interval2[0],
                                                       interval2[1]))
                declarationInterval = self.lastOccurance[
                    self.relevantVariable].getSourceInterval()
                self.token_stream_rewriter.replaceRange(
                    declarationInterval[0], declarationInterval[1], "")
            self.isRelevant -= 1

    # Enter a parse tree produced by JavaParserLabeled#statement4.
    def enterStatement4(self, ctx: JavaParserLabeled.Statement4Context):
        if isinstance(ctx.statement(), JavaParserLabeled.Statement0Context):
            self.whileStmnt = ctx
            exp = self.whileStmnt.parExpression().expression()
            if isinstance(exp, JavaParserLabeled.Expression0Context):
                prm = exp.primary()
                if isinstance(prm, JavaParserLabeled.Primary4Context):
                    self.isRelevant += 1
                    self.relevantVariable = prm.IDENTIFIER().getText()

            elif isinstance(exp, JavaParserLabeled.Expression8Context):
                exp2 = exp.expression()
                if isinstance(exp2, JavaParserLabeled.Expression0Context):
                    prm = exp2.primary()
                    if isinstance(prm, JavaParserLabeled.Primary4Context):
                        self.isRelevant += 1
                        self.relevantVariable = prm.IDENTIFIER().getText()

    # Exit a parse tree produced by JavaParserLabeled#statement4.
    def exitStatement4(self, ctx: JavaParserLabeled.Statement4Context):
        if self.isRelevant:
            interval = self.whileStmnt.parExpression().expression(
            ).getSourceInterval()
            self.token_stream_rewriter.replaceRange(interval[0], interval[1],
                                                    "true")
            declarationInterval = self.lastOccurance[
                self.relevantVariable].getSourceInterval()
            self.token_stream_rewriter.replaceRange(declarationInterval[0],
                                                    declarationInterval[1], "")
            self.isRelevant -= 1

    # Enter a parse tree produced by JavaParserLabeled#localVariableDeclaration.
    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if self.isRelevant:
            pass

        else:
            for child in ctx.variableDeclarators().variableDeclarator():
                self.lastOccurance[
                    child.variableDeclaratorId().getText()] = ctx.parentCtx
                self.relevantVariableValue = child.variableInitializer(
                ).getText()

    # Enter a parse tree produced by JavaParserLabeled#expression1.
    def enterExpression21(self, ctx: JavaParserLabeled.Expression21Context):
        if self.isRelevant:
            if ctx.expression(0).getText() == self.relevantVariable:
                interval = ctx.getSourceInterval()
                self.token_stream_rewriter.replaceRange(
                    interval[0], interval[1], "break")
Пример #16
0
class StrategyPatternRefactoringListener(JavaParserLabeledListener):
    """
    To implement the strategy pattern refactoring
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 method_identifier: str = None):
        """
        :param common_token_stream:
        """
        self.i = 0
        self.enter_method = False
        self.token_stream = common_token_stream
        self.method_identifier = method_identifier
        self.class_identifier = ""
        self.currentClass = 1
        self.enter_class = False
        self.method_selected = False
        self.ifelse = False
        self.inputPara = False
        self.newClasses = ""
        self.interface = ""
        self.para = ""
        self.newPara = []
        self.oldPara = []
        self.typePara = []
        self.old_method_Declaration = ""
        self.new_method_Declaration = ""
        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        self.enter_class = True
        self.class_identifier = ctx.IDENTIFIER().getText()

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        grand_parent_ctx = ctx.parentCtx.parentCtx
        self.method_selected = False
        if ctx.IDENTIFIER().getText() == self.method_identifier:
            self.enter_method = True
            self.method_selected = True
            self.old_method_Declaration = self.token_stream_rewriter.getText(
                "",
                grand_parent_ctx.modifier(0).start.tokenIndex,
                ctx.formalParameters().stop.tokenIndex)
            self.old_method_Declaration = self.old_method_Declaration.replace(
                self.method_identifier, "doOperation")

    def enterStatement2(self, ctx: JavaParserLabeled.Statement2Context):
        if self.method_selected:
            self.ifelse = True
            self.para = ctx.parExpression().expression().getText().split('==')
            # Define new concrete strategy as subclass of strategy
            new_sub_class = ("\nclass SubNewClass" + str(self.currentClass) +
                             " implements MyStrategy{\n\t" + "@Override\n\t" +
                             self.old_method_Declaration + "\n\t")
            body = self.token_stream_rewriter.getText(
                "",
                ctx.statement(0).block().start.tokenIndex,
                ctx.statement(0).block().stop.tokenIndex)

            # Make body for new subclass
            if body[0] != "{":
                body = "{" + body + "}"
            self.newClasses += new_sub_class + body + "\n}"
            self.currentClass += 1

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.enter_method:
            if self.ifelse and self.inputPara:
                # Create new class(Create an interface of strategy class named MyStrategy)
                self.interface = "\ninterface MyStrategy {\n\t" + self.new_method_Declaration + ";\n}"
                self.newClasses = self.newClasses.replace(
                    self.old_method_Declaration, self.new_method_Declaration)
                self.token_stream_rewriter.insertAfter(
                    ctx.start.tokenIndex - 1,
                    text="\n" + self.interface + self.newClasses + "\n")
                self.enter_method = False
        self.enter_class = False

    def enterFormalParameter(self,
                             ctx: JavaParserLabeled.FormalParameterContext):
        if self.method_selected:
            self.inputPara = True
            self.oldPara.append(ctx.typeType().getText() + " " +
                                ctx.variableDeclaratorId().getText())
            self.typePara.append(ctx.typeType().getText())

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.method_selected:
            # Make new method declaration
            if self.ifelse and self.inputPara:
                self.newPara = []
                for item in self.oldPara:
                    if not item.endswith(str(self.para[0])):
                        self.newPara.append(item)
                self.newPara = ', '.join(self.newPara)
                LPRANindex = self.old_method_Declaration.index('(')
                self.new_method_Declaration = self.old_method_Declaration[:
                                                                          LPRANindex] + "(" + self.newPara + ")"
                new_name = self.old_method_Declaration.replace(
                    "doOperation", self.method_identifier + "Strategy")
                temp1 = ', '.join(self.oldPara)
                temp1 = "(" + temp1 + ")"
                temp2 = "(" + self.newPara + ")"
                new_name = new_name.replace(temp1, temp2)
                for item in self.typePara:
                    self.newPara = self.newPara.replace(item, "")
                # Modify original class
                newbody = (" private MyStrategy strategy;\n" + "\tpublic " +
                           self.class_identifier + "(MyStrategy strategy){\n" +
                           "\t\tthis.strategy = strategy;\n" + "\t}\n" + "\t" +
                           new_name + "{\n" +
                           "\t\treturn strategy.doOperation(" + self.newPara +
                           ");\n" + "\t}")

                self.token_stream_rewriter.replaceRange(
                    ctx.parentCtx.parentCtx.start.tokenIndex,
                    ctx.stop.tokenIndex,
                    newbody,
                )
Пример #17
0
class PullUpFieldRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 destination_class: str = None,
                 children_class=None,
                 moved_fields=None,
                 fieldtext=None):

        if moved_fields is None:
            self.moved_fields = []
        else:
            self.moved_fields = moved_fields
        if children_class is None:
            self.moved_fields = []
        else:
            self.children_class = children_class

        #
        if fieldtext is None:
            raise ValueError("fieldtext is None")
        else:
            self.fieldtext = fieldtext

        #
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if destination_class is None:
            raise ValueError("source_class is None")
        else:
            self.destination_class = destination_class
        # if destination_class is None:
        #     raise ValueError("new_class is None")
        # else:
        #     self.destibation_class = destination_class

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.tempdeclarationcode = ""
        self.field_text = ""
        # self.iscopyfieldtext=False

    def enterFieldDeclaration(self,
                              ctx: JavaParserLabeled.FieldDeclarationContext):

        # if self.is_source_class:
        ctx1 = ctx.parentCtx.parentCtx.parentCtx.parentCtx
        class_identifier = ctx1.IDENTIFIER().getText()
        if class_identifier in self.children_class:

            # class_identifier = ctx.variableDeclarators().variableDeclarator().variableDeclaratorId().IDENTIFIER.getText()
            # field_identifier = ctx.variableDeclarators().getText().split(",")
            field_identifier = ctx.variableDeclarators().variableDeclarator(
                0).variableDeclaratorId().IDENTIFIER().getText()
            # print(class_identifier)
            # for item in self.moved_fields:

            if self.moved_fields[0] in field_identifier:
                ctx1 = ctx.parentCtx.parentCtx
                start_index = ctx1.start.tokenIndex
                stop_index = ctx1.stop.tokenIndex
                self.field_text = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=start_index,
                    stop=stop_index)

                # delete field from source class

                # self.token_stream_rewriter.replaceRange(
                #     from_idx=ctx1.start.tokenIndex,
                #     to_idx=ctx1.stop.tokenIndex,
                #     text=f"{modifier} {field_type} {','.join(field_names)};"
                # )
                # else:
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=ctx1.start.tokenIndex,
                    to_idx=ctx1.stop.tokenIndex)

            # print(self.field_text)

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.destination_class:
            self.is_source_class = True

            # self.code += self.NEW_LINE * 2
            # self.code += f"// New class({self.destibation_class}) generated by CodART" + self.NEW_LINE
            # self.code += f"class {self.destibation_class}{self.NEW_LINE}" + "{" + self.NEW_LINE
        elif class_identifier == "B":
            print("enter B class")
            # self.token_stream_rewriter.replaceRange(
            #                     from_idx=ctx.start.tokenIndex,
            #                     to_idx=ctx.start.tokenIndex,
            #                     text=self.field_text
            #                 )
            self.is_source_class = False

        # self.code += (self.field_text

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        print()
        ctx1 = ctx.parentCtx
        class_identifier = ctx1.IDENTIFIER().getText()
        print(class_identifier)
        if class_identifier == self.destination_class:
            # if not self.is_source_class:
            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.start.tokenIndex + 1,
                to_idx=ctx.start.tokenIndex + 1,
                text="\n" + self.fieldtext + "\n")

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_source_class:
            # self.code += "}"
            self.is_source_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        # self.count+=1
        # if(self.count==1):
        #     my_listener = movefieldupRefactoringListener(common_token_stream=self.token_stream_rewriter, destination_class='A',
        #                                                  children_class=["B", "S"], moved_fields=['a'],)

        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.code)

    def enterVariableDeclaratorId(
            self, ctx: JavaParserLabeled.VariableDeclaratorIdContext):
        if not self.is_source_class:
            return None
        field_identifier = ctx.IDENTIFIER().getText()
        if field_identifier in self.moved_fields:
            self.detected_field = field_identifier
Пример #18
0
class EncapsulateFiledRefactoringListener(JavaParserLabeledListener):
    """

    To implement encapsulate field refactoring.

    Makes a public field private and provide accessors and mutator methods.

    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 package_name: str = None,
                 source_class_name: str = None,
                 field_identifier: str = None):
        """

        Args:

            common_token_stream (CommonTokenStream): contains the program tokens

            package_name (str): The enclosing package of the field

            source_class_name (str): The enclosing class of the field

            field_identifier (str): The field name to be encapsulated

        Returns:

            object (DecreaseMethodVisibilityListener): An instance of EncapsulateFiledRefactoringListener

        """

        self.token_stream = common_token_stream
        if package_name is None:
            self.package_name = ''
        else:
            self.package_name = package_name
        self.source_class_name = source_class_name
        self.field_identifier = field_identifier
        self.getter_exist = False
        self.setter_exist = False
        self.in_source_class = False
        self.in_selected_package = True if self.package_name == '' else False

        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = \
                TokenStreamRewriter(common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

    def enterPackageDeclaration(
            self, ctx: JavaParserLabeled.PackageDeclarationContext):
        if self.package_name == ctx.qualifiedName().getText():
            self.in_selected_package = True
        else:
            self.in_selected_package = False

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        if ctx.IDENTIFIER().getText() == self.source_class_name:
            self.in_source_class = True

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        self.in_source_class = False

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        if self.in_source_class and self.in_selected_package:
            if ctx.variableDeclarators().variableDeclarator(
                    0).variableDeclaratorId().getText(
                    ) == self.field_identifier:
                if not ctx.parentCtx.parentCtx.modifier(0):
                    self.token_stream_rewriter.insertBeforeIndex(
                        index=ctx.typeType().stop.tokenIndex, text='private ')

                elif ctx.parentCtx.parentCtx.modifier(0).getText() == 'public':
                    self.token_stream_rewriter.replaceRange(
                        from_idx=ctx.parentCtx.parentCtx.modifier(
                            0).start.tokenIndex,
                        to_idx=ctx.parentCtx.parentCtx.modifier(
                            0).stop.tokenIndex,
                        text='private')
                else:
                    return

                for c in ctx.parentCtx.parentCtx.parentCtx.classBodyDeclaration(
                ):
                    try:
                        print('method name: ' + c.memberDeclaration().
                              methodDeclaration().IDENTIFIER().getText())

                        if c.memberDeclaration().methodDeclaration().IDENTIFIER() \
                                .getText() == 'get' + str.capitalize(
                            self.field_identifier):
                            self.getter_exist = True

                        if c.memberDeclaration().methodDeclaration().IDENTIFIER() \
                                .getText() == 'set' + str.capitalize(
                            self.field_identifier):
                            self.setter_exist = True

                    except:
                        logger.error("not method !!!")

                logger.debug("setter find: " + str(self.setter_exist))
                logger.debug("getter find: " + str(self.getter_exist))

                # generate accessor and mutator methods
                # Accessor body
                new_code = ''
                if not self.getter_exist:
                    new_code = '\n\t// new getter method\n\t'
                    new_code += 'public ' + ctx.typeType().getText() + \
                                ' get' + str.capitalize(self.field_identifier)
                    new_code += '() { \n\t\treturn this.' + self.field_identifier \
                                + ';' + '\n\t}\n'

                # Mutator body
                if not self.setter_exist:
                    new_code += '\n\t// new setter method\n\t'
                    new_code += 'public void set' + str.capitalize(
                        self.field_identifier)
                    new_code += '(' + ctx.typeType().getText() + ' ' \
                                + self.field_identifier + ') { \n\t\t'
                    new_code += 'this.' + self.field_identifier + ' = ' \
                                + self.field_identifier + ';' + '\n\t}\n'
                self.token_stream_rewriter.insertAfter(ctx.stop.tokenIndex,
                                                       new_code)

                hidden = self.token_stream.getHiddenTokensToRight(
                    ctx.stop.tokenIndex)
                # self.token_stream_rewriter.replaceRange(from_idx=hidden[0].tokenIndex,
                #                                         to_idx=hidden[-1].tokenIndex,
                #                                         text='\n\t/*End of accessor and mutator methods!*/\n\n')

    def exitExpression21(self, ctx: JavaParserLabeled.Expression21Context):
        if self.in_source_class and self.in_selected_package:
            if ctx.expression(0).getText() == self.field_identifier or \
                    ctx.expression(0).getText() == 'this.' + self.field_identifier:
                expr_code = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=ctx.expression(1).start.tokenIndex,
                    stop=ctx.expression(1).stop.tokenIndex)
                new_code = 'this.set' + str.capitalize(
                    self.field_identifier) + '(' + expr_code + ')'
                self.token_stream_rewriter.replaceRange(
                    ctx.start.tokenIndex, ctx.stop.tokenIndex, new_code)

    def exitExpression0(self, ctx: JavaParserLabeled.Expression0Context):
        if self.in_source_class and self.in_selected_package:
            try:
                if ctx.parentCtx.getChild(1).getText() in ('=', '+=', '-=',
                                                           '*=', '/=', '&=',
                                                           '|=', '^=', '>>=',
                                                           '>>>=', '<<=', '%=') and \
                        ctx.parentCtx.getChild(0) == ctx:
                    return
            except:
                pass
            if ctx.getText() == self.field_identifier:
                new_code = 'this.get' + str.capitalize(
                    self.field_identifier) + '()'
                self.token_stream_rewriter.replaceRange(
                    ctx.start.tokenIndex, ctx.stop.tokenIndex, new_code)

    def exitExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if self.in_source_class and self.in_selected_package:
            try:
                if ctx.parentCtx.getChild(1).getText() in ('=', '+=', '-=',
                                                           '*=', '/=', '&=',
                                                           '|=', '^=', '>>=',
                                                           '>>>=', '<<=', '%=') and \
                        ctx.parentCtx.getChild(0) == ctx:
                    return
            except:
                pass
            if ctx.getText() == 'this.' + self.field_identifier:
                new_code = 'this.get' + str.capitalize(
                    self.field_identifier) + '()'
                self.token_stream_rewriter.replaceRange(
                    ctx.start.tokenIndex, ctx.stop.tokenIndex, new_code)

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        try:
            hidden = self.token_stream.getHiddenTokensToLeft(
                ctx.start.tokenIndex)
            self.token_stream_rewriter.replaceRange(
                from_idx=hidden[0].tokenIndex,
                to_idx=hidden[-1].tokenIndex,
                text='/*After refactoring (Refactored version)*/\n')
        except:
            pass
Пример #19
0
    def do_refactor(self):
        program = get_program(self.source_filenames)
        static = 0

        if self.class_name not in program.packages[self.package_name].classes or self.target_class_name not in \
                program.packages[
                    self.target_package_name].classes or self.method_key not in \
                program.packages[self.package_name].classes[
                    self.class_name].methods:
            return False

        _sourceclass = program.packages[self.package_name].classes[
            self.class_name]
        _targetclass = program.packages[self.target_package_name].classes[
            self.target_class_name]
        _method = program.packages[self.package_name].classes[
            self.class_name].methods[self.method_key]

        if _method.is_constructor:
            return False

        Rewriter_ = Rewriter(program, lambda x: x)
        tokens_info = TokensInfo(
            _method.parser_context)  # tokens of ctx method
        param_tokens_info = TokensInfo(_method.formalparam_context)
        method_declaration_info = TokensInfo(
            _method.method_declaration_context)
        exp = [
        ]  # برای نگه داری متغیرهایی که داخل کلاس تعریف شدند و در بدنه متد استفاده شدند
        exps = tokens_info.get_token_index(tokens_info.token_stream.tokens,
                                           tokens_info.start, tokens_info.stop)

        # check that method is static or not
        for modifier in _method.modifiers:
            if modifier == "static":
                static = 1

        for token in exps:
            if token.text in _sourceclass.fields:
                exp.append(token.tokenIndex)
            # check that where this method is call
        for package_names in program.packages:
            package = program.packages[package_names]
            for class_ in package.classes:
                _class = package.classes[class_]
                for method_ in _class.methods:
                    __method = _class.methods[method_]
                    for inv in __method.body_method_invocations:
                        invc = __method.body_method_invocations[inv]
                        method_name = self.method_key[:self.method_key.find('('
                                                                            )]
                        if invc[0] == method_name:
                            inv_tokens_info = TokensInfo(inv)
                            if static == 0:
                                class_token_info = TokensInfo(
                                    _class.body_context)
                                Rewriter_.insert_after_start(
                                    class_token_info,
                                    self.target_class_name + " " +
                                    str.lower(self.target_class_name) + "=" +
                                    "new " + self.target_class_name + "();")
                                Rewriter_.apply()
                            Rewriter_.insert_before_start(
                                class_token_info,
                                "import " + self.target_package_name + "." +
                                self.target_class_name + ";")
                            Rewriter_.replace(inv_tokens_info,
                                              self.target_class_name)
                        Rewriter_.apply()

        class_tokens_info = TokensInfo(_targetclass.parser_context)
        package_tokens_info = TokensInfo(
            program.packages[self.target_package_name].package_ctx)
        singlefileelement = SingleFileElement(_method.parser_context,
                                              _method.filename)
        token_stream_rewriter = TokenStreamRewriter(
            singlefileelement.get_token_stream())

        # insert name of source.java class befor param that define in body of classe (that use in method)
        for index in exp:
            token_stream_rewriter.insertBeforeIndex(
                index=index, text=str.lower(self.class_name) + ".")

        for inv in _method.body_method_invocations:
            if inv.getText() == self.target_class_name:
                inv_tokens_info_target = TokensInfo(inv)
                token_stream_rewriter.replaceRange(
                    from_idx=inv_tokens_info_target.start,
                    to_idx=inv_tokens_info_target.stop + 1,
                    text=" ")

            # insert source.java class befor methods of sourcr class that used in method
        for i in _method.body_method_invocations_without_typename:
            if i.getText() == self.class_name:
                ii = _method.body_method_invocations_without_typename[i]
                i_tokens = TokensInfo(ii[0])
                token_stream_rewriter.insertBeforeIndex(
                    index=i_tokens.start,
                    text=str.lower(self.class_name) + ".")

        # pass object of source.java class to method
        if param_tokens_info.start is not None:
            token_stream_rewriter.insertBeforeIndex(
                param_tokens_info.start,
                text=self.class_name + " " + str.lower(self.class_name) + ",")
        else:
            token_stream_rewriter.insertBeforeIndex(
                method_declaration_info.stop,
                text=self.class_name + " " + str.lower(self.class_name))

        strofmethod = token_stream_rewriter.getText(
            program_name=token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            start=tokens_info.start,
            stop=tokens_info.stop)

        Rewriter_.insert_before(tokens_info=class_tokens_info,
                                text=strofmethod)
        Rewriter_.insert_after(
            package_tokens_info, "import " + self.target_package_name + "." +
            self.target_class_name + ";")
        Rewriter_.replace(tokens_info, "")
        Rewriter_.apply()
        return True
Пример #20
0
class MoveMethodDownRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 children_class=None,
                 moved_methods: str = None,
                 method_text: str = None):

        if method_text is None:
            self.method_text = []
        else:
            self.method_text = method_text
        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if children_class is None:
            self.moved_methods = []
        else:
            self.children_class = children_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        # if destination_class is None:
        #     raise ValueError("new_class is None")
        # else:
        #     self.destibation_class = destination_class

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.tempdeclarationcode = ""

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):

        if self.is_source_class:

            # method_identifier = ctx.variableDeclarators().variableDeclarator().variableDeclaratorId().IDENTIFIER.getText()
            method_identifier = ctx.IDENTIFIER().getText()
            print(method_identifier)
            print(self.moved_methods)
            if self.moved_methods == method_identifier:
                methodDefctx = ctx.parentCtx.parentCtx
                start_index = methodDefctx.start.tokenIndex
                stop_index = methodDefctx.stop.tokenIndex
                self.method_text = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=start_index,
                    stop=stop_index)

                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=methodDefctx.start.tokenIndex,
                    to_idx=methodDefctx.stop.tokenIndex)

            print("method text: ", self.method_text)
        else:
            return None

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True

        elif class_identifier == "B":
            print("enter B class")
            self.is_source_class = False

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        classDecctx = ctx.parentCtx
        class_identifier = classDecctx.IDENTIFIER().getText()
        if class_identifier in self.children_class:
            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.start.tokenIndex + 1,
                to_idx=ctx.start.tokenIndex + 1,
                text="\n" + self.method_text + "\n")

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_source_class:
            self.is_source_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):

        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.code)
Пример #21
0
class RemoveFlagArgumentListener(JavaParserLabeledListener):
    """
        To remove boolean flag argument which specifies method logic in if and else block .
    For more information visit Martin Frauler book .
    if(flag)
    {

    }
    else
    {

    }
    This listener is used to capture needed pattern and edit source method and extract two distinct logic
    in if and else blog there are several key assumption made at this momenent that the argument should be
    boolean and there must only been used in if else block and the structure of if and else should be in
    block format and single line if and else are not supported
        
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class="",
                 source_method="",
                 argument_name: str = ""):
        """create removeflaglistener to extract and edit needed pattern

        Args:
            common_token_stream (CommonTokenStream, optional): default token stream passed by higher level api. Defaults to None.
            source_class (str, optional): name of the class which method rests in. Defaults to "".
            source_method (str, optional): name of the method to be edited. Defaults to "".
            argument_name (str, optional): name of the boolean argument which branchs the logic. Defaults to "".

        Raises:
            ValueError: if no common token stream is find will be raised since its is essential to the process
        """
        self.argument_name = argument_name
        self.source_method = source_method
        self.source_class = source_class
        self.token_stream_rewriter_changed = False

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
            self.common_token_stream = common_token_stream

        self.is_source_class = False
        self.is_source_method = False
        self.is_if_block = False
        self.is_else_block = False

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        """check if the class is the source class
        Args:
            ctx (JavaParserLabeled.ClassDeclarationContext)
        """
        print("Refactoring started, please wait...")
        self.is_source_class = (
            ctx.IDENTIFIER().getText() == self.source_class)

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        """check if this is the intended method if so capture signature and remove boolean argument
            
        Args:
            ctx (JavaParserLabeled.MethodDeclarationContext): 
        """
        self.is_source_method = (
            ctx.IDENTIFIER().getText() == self.source_method)
        if self.is_source_method:

            nextParam = None

            for idx, formalParameter in enumerate(ctx.formalParameters(
            ).formalParameterList().formalParameter()):
                if formalParameter.variableDeclaratorId().IDENTIFIER().getText(
                ) == self.argument_name:
                    self.argument_token = formalParameter
                    nextParam = ctx.formalParameters().formalParameterList().formalParameter()[idx + 1] \
                        if idx != len(ctx.formalParameters().formalParameterList().formalParameter()) - 1 else None
                    break

            if nextParam:
                self.token_stream_rewriter.replaceRange(
                    self.argument_token.start.tokenIndex,
                    nextParam.start.tokenIndex - 1, '')
            else:
                self.token_stream_rewriter.replaceRange(
                    self.argument_token.start.tokenIndex,
                    self.argument_token.stop.tokenIndex, '')

            self.signature = self.token_stream_rewriter.getText(
                self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                ctx.start.tokenIndex,
                ctx.methodBody().start.tokenIndex)

            if self.token_stream_rewriter_changed == False:
                self.token_stream_rewriter = TokenStreamRewriter(
                    self.common_token_stream)
                self.token_stream_rewriter_changed = True

    def exitMethodBody(self, ctx: JavaParserLabeled.MethodBodyContext):
        """after exiting the soure method create two new method for new method logics and call these in if and
        else block in the source method
        Args:
            ctx (JavaParserLabeled.MethodBodyContext)
        """
        if self.is_source_method:
            signature1 = self.signature.split('(')[0].rstrip(
            ) + 'IsTrue' + ' (' + ''.join(self.signature.split('(')[1:])
            signature2 = self.signature.split('(')[0].rstrip(
            ) + 'IsFalse' + ' (' + ''.join(self.signature.split('(')[1:])

            res = '\n\t' + signature1 + self.body_1 + '\n\t' + signature2 + self.body_2
            self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                                   text=res)
            # self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex, text=self.body_2)
            # self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex, text=self.signature)
            # print(self.signature)

            arguments = [
                s.rstrip().split(' ')[-1]
                for s in signature1.split('(')[1].split(')')[0].split(',')
            ]
            print("exit method")
            signature1_name = signature1.split('(')[0].rstrip().split()[-1]
            signature2_name = signature2.split('(')[0].rstrip().split()[-1]

            self.token_stream_rewriter.replaceRange(
                self.body_1_token.start.tokenIndex,
                self.body_1_token.stop.tokenIndex,
                '\t' + signature1_name + '( ' + ','.join(arguments) + ')')
            self.token_stream_rewriter.replaceRange(
                self.body_2_token.start.tokenIndex,
                self.body_2_token.stop.tokenIndex,
                '\t' + signature2_name + '( ' + ','.join(arguments) + ')')

    def enterStatement0(self, ctx: JavaParserLabeled.Statement0Context):
        if self.is_source_method:
            pass

    def enterStatement2(self, ctx: JavaParserLabeled.Statement2Context):
        """when entering if else block we get both of the logic in the block if this was source method
            and capture the token which is needed later to do the refactoring
        Args:
            ctx (JavaParserLabeled.Statement2Context)
        """
        if self.is_source_method:

            try:
                primary = ctx.parExpression().expression().primary()
                if hasattr(primary, "IDENTIFIER"):
                    if ctx.parExpression().expression().primary().IDENTIFIER(
                    ).getText() == self.argument_name:
                        iterator = iter(ctx.statement())

                        # TODO : handle on statements blocks .e.g. {}

                        self.body_1, self.body_2 = [
                            self.common_token_stream.getText(
                                s.block().start,
                                s.block().stop)[1:] for s in ctx.statement()
                        ]

                        self.body_1_token, self.body_2_token = [
                            s.block() for s in ctx.statement()
                        ]

                        # print(ctx.getPayload())
                        # print(self.common_token_stream.getText(ctx.start, ctx.stop))
                        # print(dir(ctx.statement()[0].block()))

                        # for s in ctx.statement():
                        #     print(s.block().getText())

            except:
                pass
Пример #22
0
    def do_refactor(self):
        program = get_program(
            self.source_filenames)  # getting the program packages
        _sourceclass = program.packages[self.package_name].classes[
            self.class_name]
        target_class_name = _sourceclass.superclass_name
        static = 0
        removemethod = get_removemethods(
            program, self.package_name, target_class_name, self.method_key,
            self.class_name)  # Similar methods in other classes
        _targetclass = program.packages[
            self.package_name].classes[target_class_name]
        _method_name = program.packages[self.package_name].classes[
            self.class_name].methods[self.method_key]
        tokens_info = TokensInfo(_method_name.parser_context)
        exps = tokens_info.get_token_index(
            tokens_info.token_stream.tokens, tokens_info.start, tokens_info.
            stop)  # list of class variables that are used in the method
        if _method_name.is_constructor:
            return False
        # if method use param of class body return false
        for token in exps:
            if token.text in _sourceclass.fields:
                return False

        if bool(_method_name.body_method_invocations_without_typename):
            return False

        Rewriter_ = Rewriter(program, self.filename_mapping)
        for remove in removemethod:
            _methodd = removemethod[remove]
            if _methodd is not None:
                _methodds = _methodd[0]
                _method = program.packages[
                    self.package_name].classes[remove].methods[str(_methodds)]
                _method_token_info = TokensInfo(_method.parser_context)
                Rewriter_.replace(_method_token_info, " ")

        class_tokens_info = TokensInfo(_targetclass.parser_context)
        singlefileelement = SingleFileElement(_method_name.parser_context,
                                              _method_name.filename)
        token_stream_rewriter = TokenStreamRewriter(
            singlefileelement.get_token_stream())
        strofmethod = token_stream_rewriter.getText(
            program_name=token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            start=tokens_info.start,
            stop=tokens_info.stop)
        Rewriter_.insert_before(tokens_info=class_tokens_info,
                                text=strofmethod)
        Rewriter_.apply()
        # The Method has to be updated anywhere else that it's used
        for package_names in program.packages:
            package = program.packages[package_names]
            for class_ in package.classes:
                _class = package.classes[class_]
                for method_ in _class.methods:
                    __method = _class.methods[method_]
                    for inv in __method.body_method_invocations:
                        invc = __method.body_method_invocations[inv]
                        method_name = self.method_key[:self.method_key.find('('
                                                                            )]
                        if invc[0] == method_name & package_names == self.package_name:
                            inv_tokens_info = TokensInfo(inv)
                            if static == 0:
                                class_token_info = TokensInfo(
                                    _class.body_context)
                                Rewriter_.insert_after_start(
                                    class_token_info, target_class_name + " " +
                                    str.lower(target_class_name) + "=" +
                                    "new " + target_class_name + "();")
                                Rewriter_.apply()
                            Rewriter_.replace(inv_tokens_info,
                                              target_class_name)
                            Rewriter_.apply()
        return True
Пример #23
0
class ExtractClassRefactoringListener(Java9_v2Listener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None):
        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if moved_fields is None:
            self.moved_fields = []
        else:
            self.moved_fields = moved_fields

        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        if new_class is None:
            raise ValueError("new_class is None")
        else:
            self.new_class = new_class

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""

    def enterNormalClassDeclaration(
            self, ctx: Java9_v2Parser.NormalClassDeclarationContext):
        print("Refactoring started, please wait...")
        class_identifier = ctx.identifier().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
            self.code += self.NEW_LINE * 2
            self.code += f"// New class({self.new_class}) generated by CodART" + self.NEW_LINE
            self.code += f"class {self.new_class}{self.NEW_LINE}" + "{" + self.NEW_LINE
        else:
            self.is_source_class = False

    def exitNormalClassDeclaration(
            self, ctx: Java9_v2Parser.NormalClassDeclarationContext):
        if self.is_source_class:
            self.code += "}"
            self.is_source_class = False

    def exitOrdinaryCompilation(
            self, ctx: Java9_v2Parser.OrdinaryCompilationContext):
        print("Finished Processing...")
        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.code)

    def enterVariableDeclaratorId(
            self, ctx: Java9_v2Parser.VariableDeclaratorIdContext):
        if not self.is_source_class:
            return None
        field_identifier = ctx.identifier().getText()
        if field_identifier in self.moved_fields:
            self.detected_field = field_identifier

    def exitFieldDeclaration(self,
                             ctx: Java9_v2Parser.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        field_names = ctx.variableDeclaratorList().getText().split(",")
        if self.detected_field in field_names:
            modifier = ctx.fieldModifier(0).getText()
            field_type = ctx.unannType().getText()
            self.code += f"{self.TAB}{modifier} {field_type} {self.detected_field};{self.NEW_LINE}"
            # delete field from source class
            field_names.remove(self.detected_field)
            if field_names:
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.start.tokenIndex,
                    to_idx=ctx.stop.tokenIndex,
                    text=f"{modifier} {field_type} {','.join(field_names)};")
            else:
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=ctx.start.tokenIndex,
                    to_idx=ctx.stop.tokenIndex)
            self.detected_field = None

    def enterMethodDeclarator(self,
                              ctx: Java9_v2Parser.MethodDeclaratorContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.identifier().getText()
        if method_identifier in self.moved_methods:
            self.detected_method = method_identifier

    def exitMethodDeclaration(self,
                              ctx: Java9_v2Parser.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.methodHeader().methodDeclarator().identifier(
        ).getText()
        if self.detected_method == method_identifier:
            start_index = ctx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex
            method_text = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index)
            self.code += (self.NEW_LINE + self.TAB + method_text +
                          self.NEW_LINE)
            # delete method from source class
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=start_index,
                to_idx=stop_index)
            self.detected_method = None
Пример #24
0
class CollapseHierarchyRefactoringGetMethodTextListener(
        JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 child_class=None):

        if child_class is None:
            self.moved_methods = []
        else:
            self.child_class = child_class
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        self.is_children_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.methodcode = ""

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.child_class:
            self.is_source_class = True
            self.methodcode += self.NEW_LINE * 2
            self.methodcode += f"// child class({self.child_class}) methods: " + self.NEW_LINE
        else:
            self.is_source_class = False

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.is_source_class:
            self.is_source_class = False

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        self.token_stream_rewriter.insertAfter(index=ctx.stop.tokenIndex,
                                               text=self.methodcode)

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        self.detected_method = ctx.IDENTIFIER().getText()

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        print("Here it is a method")

        grand_parent_ctx = ctx.parentCtx.parentCtx
        modifier = ""
        for i in range(0, len(grand_parent_ctx.modifier())):
            modifier += grand_parent_ctx.modifier(i).getText()
            modifier += " "

        if self.detected_method == method_identifier:
            start_index = ctx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex
            method_text = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index)
            self.methodcode += (self.NEW_LINE + self.TAB + modifier +
                                method_text + self.NEW_LINE)
Пример #25
0
def pullup_method_refactoring(
        source_filenames: list,
        package_name: str,
        class_name: str,
        method_key: str,
        filename_mapping=lambda x: x + ".rewritten.java"):
    program = get_program(source_filenames)  #گرفتن پکیج های برنامه
    _sourceclass = program.packages[package_name].classes[class_name]
    target_class_name = _sourceclass.superclass_name
    static = 0
    removemethod = get_removemethods(
        program, package_name, target_class_name, method_key,
        class_name)  #متد های مشابه در کلاس های دیگر
    _targetclass = program.packages[package_name].classes[target_class_name]
    _method_name = program.packages[package_name].classes[class_name].methods[
        method_key]
    tokens_info = TokensInfo(_method_name.parser_context)
    exps = tokens_info.get_token_index(
        tokens_info.token_stream.tokens, tokens_info.start, tokens_info.stop
    )  #لیست متغیر های داخل بدنه کلاس که داخل متد استفاده شده اند
    if _method_name.is_constructor:
        return False
    #if method use param of class body return false
    for token in exps:
        if token.text in _sourceclass.fields:
            return False

    if bool(_method_name.body_method_invocations_without_typename) == True:
        return False

    Rewriter_ = Rewriter(program, filename_mapping)
    for remove in removemethod:
        _methodd = removemethod[remove]
        if _methodd != None:
            _methodds = _methodd[0]
            _method = program.packages[package_name].classes[remove].methods[
                str(_methodds)]
            _method_token_info = TokensInfo(_method.parser_context)
            Rewriter_.replace(_method_token_info, " ")

    class_tokens_info = TokensInfo(_targetclass.parser_context)
    singlefileelement = SingleFileElement(_method_name.parser_context,
                                          _method_name.filename)
    token_stream_rewriter = TokenStreamRewriter(
        singlefileelement.get_token_stream())
    strofmethod = token_stream_rewriter.getText(
        program_name=token_stream_rewriter.DEFAULT_PROGRAM_NAME,
        start=tokens_info.start,
        stop=tokens_info.stop)
    Rewriter_.insert_before(tokens_info=class_tokens_info, text=strofmethod)
    Rewriter_.apply()
    #در کلاس های دیگر هر جا که از این متد استفاده شده باید اپدیت شود
    for package_names in program.packages:
        package = program.packages[package_names]
        for class_ in package.classes:
            _class = package.classes[class_]
            for method_ in _class.methods:
                __method = _class.methods[method_]
                for inv in __method.body_method_invocations:
                    invc = __method.body_method_invocations[inv]
                    method_name = method_key[:method_key.find('(')]
                    if (invc[0] == method_name & package_names ==
                            package_name):
                        inv_tokens_info = TokensInfo(inv)
                        if (static == 0):
                            class_token_info = TokensInfo(_class.body_context)
                            Rewriter_.insert_after_start(
                                class_token_info, target_class_name + " " +
                                str.lower(target_class_name) + "=" + "new " +
                                target_class_name + "();")
                            Rewriter_.apply()
                        Rewriter_.replace(inv_tokens_info, target_class_name)
                        Rewriter_.apply()
    return True
Пример #26
0
class FactoryMethodRefactoringListener(JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 creator_identifier: str = None,
                 products_identifier: list = None):
        self.enter_class = False
        self.token_stream = common_token_stream
        self.creator_identifier = creator_identifier
        self.products_identifier = products_identifier
        self.interfaceName = "ProductsAbstract"
        self.inCreator = False
        self.inProducts = False
        self.productsMethod = {}
        self.productsClassIndex = []
        self.productVarTypeIndex = []
        self.productVarValueIndex = []
        self.productConstructorMethod = []
        self.productConstructorParam = {}
        self.currentClass = None
        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        if ctx.IDENTIFIER().getText() == self.creator_identifier:
            self.inCreator = True
            self.CretorStartIndex = ctx.classBody().start.tokenIndex
            self.currentClass = ctx.IDENTIFIER().symbol.text

        elif ctx.IDENTIFIER().getText() in self.products_identifier:
            self.inProducts = True
            self.productsClassIndex.append(ctx.IDENTIFIER().symbol.tokenIndex)
            self.currentClass = ctx.IDENTIFIER().symbol.text

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        self.inCreator = False
        self.inProducts = False

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.inProducts == True:
            methodModifire = ctx.parentCtx.parentCtx.start.text
            if methodModifire == 'public':
                MethodText = self.token_stream_rewriter.getText(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    start=ctx.parentCtx.parentCtx.start.tokenIndex,
                    stop=ctx.formalParameters().RPAREN(
                    ).symbol.tokenIndex) + ";"
                if MethodText not in self.productsMethod:
                    self.productsMethod[MethodText] = [self.currentClass]
                else:
                    self.productsMethod[MethodText].append(self.currentClass)

    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if self.inCreator == True:
            variableType = ctx.typeType().classOrInterfaceType().IDENTIFIER(0)
            if variableType.symbol.text in self.products_identifier:
                self.productVarTypeIndex.append(variableType.symbol.tokenIndex)
                self.productVarValueIndex.append([
                    variableType.symbol.text,
                    ctx.variableDeclarators().variableDeclarator(
                        0).ASSIGN().symbol.tokenIndex, ctx.stop.tokenIndex
                ])

    def enterFieldDeclaration(self,
                              ctx: JavaParserLabeled.FieldDeclarationContext):
        if self.inCreator == True:
            variableType = ctx.typeType().classOrInterfaceType().IDENTIFIER(0)
            if variableType.symbol.text in self.products_identifier:
                self.productVarTypeIndex.append(variableType.symbol.tokenIndex)
                self.productVarValueIndex.append([
                    variableType.symbol.text,
                    ctx.variableDeclarators().variableDeclarator(
                        0).ASSIGN().symbol.tokenIndex, ctx.stop.tokenIndex
                ])

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.inProducts == True:
            Parameter = ""
            if ctx.formalParameters().children.__len__() > 0:
                ParamChild = ctx.formalParameters().children[1]
                for i in range(0, ParamChild.children.__len__(), 2):
                    Parameter += ParamChild.children[i].stop.text + ","
                Parameter = Parameter[:-1]

            self.productConstructorParam[self.currentClass] = Parameter

            ParamList = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.formalParameters().LPAREN().symbol.tokenIndex,
                stop=ctx.formalParameters().RPAREN().symbol.tokenIndex)

            Method = "\t" + self.interfaceName + " create" + \
                     self.currentClass + ParamList + \
                     "{\n\t\t" + "return new " + self.currentClass + "(" + Parameter + ");\n\t}\n"

            self.productConstructorMethod.append(Method)

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        # InterfaceChecked
        interfaceMethodList = []
        for key, value in self.productsMethod.items():
            if sorted(value) == sorted(self.products_identifier):
                interfaceMethodList.append(key)
        if interfaceMethodList.__len__() > 0:
            intefaceText = "public interface " + self.interfaceName + "{"
            for item in interfaceMethodList:
                intefaceText += "\n\t" + item
            intefaceText += "\n}\n\n"
            self.token_stream_rewriter.insertBefore(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                index=1,
                text=intefaceText)

            for item in self.productsClassIndex:
                self.token_stream_rewriter.insertAfter(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    index=item,
                    text=" implements " + self.interfaceName)

            for item in self.productVarTypeIndex:
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=item,
                    to_idx=item,
                    text=self.interfaceName)
            for item in self.productVarValueIndex:
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=item[1] + 1,
                    to_idx=item[2],
                    text="create" + item[0] + " (" +
                    self.productConstructorParam[item[0]] + ")")

            newProductMethod = "\n"
            for item in self.productConstructorMethod:
                newProductMethod += item
            self.token_stream_rewriter.insertAfter(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                index=self.CretorStartIndex,
                text=newProductMethod)
Пример #27
0
class EncapsulateFiledRefactoringListener(Java9_v2Listener):
    """
    To implement the encapsulate filed refactored
    Encapsulate field: Make a public field private and provide accessors
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 field_identifier: str = None):
        """
        :param common_token_stream:
        """
        self.token_stream = common_token_stream
        self.field_identifier = field_identifier
        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

    def exitFieldDeclaration(self,
                             ctx: Java9_v2Parser.FieldDeclarationContext):
        if ctx.variableDeclaratorList().getText() == self.field_identifier:
            if ctx.fieldModifier(0).getText() == 'public':
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.fieldModifier(0).start.tokenIndex,
                    to_idx=ctx.fieldModifier(0).stop.tokenIndex,
                    text='private')

            # generate accessor and mutator methods
            # Accessor body
            new_code = '\n\t'
            new_code += 'public ' + ctx.unannType().getText(
            ) + ' get' + str.capitalize(self.field_identifier)
            new_code += '() { \n\t\t return this.' + self.field_identifier + ';' + '\n\t}'

            # Mutator body
            new_code += '\n\t'
            new_code += 'public void set' + str.capitalize(
                self.field_identifier)
            new_code += '(' + ctx.unannType().getText(
            ) + ' ' + self.field_identifier + ') { \n\t\t'
            new_code += 'this.' + self.field_identifier + ' = ' + self.field_identifier + ';' + '\n\t}\n'

            self.token_stream_rewriter.insertAfter(ctx.stop.tokenIndex,
                                                   new_code)

            hidden = self.token_stream.getHiddenTokensToRight(
                ctx.stop.tokenIndex)
            self.token_stream_rewriter.replaceRange(
                from_idx=hidden[0].tokenIndex,
                to_idx=hidden[-1].tokenIndex,
                text='\t/*End of accessor and mutator methods!*/\n\n')

    def exitAssignment(self, ctx: Java9_v2Parser.AssignmentContext):
        if ctx.leftHandSide().getText() == self.field_identifier or \
                ctx.leftHandSide().getText() == 'this.' + self.field_identifier:
            expr_code = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.expression().start.tokenIndex,
                stop=ctx.expression().stop.tokenIndex)
            # new_code = 'this.set' + str.capitalize(self.field_identifier) + '(' + ctx.expression().getText() + ')'
            new_code = 'this.set' + str.capitalize(
                self.field_identifier) + '(' + expr_code + ')'
            self.token_stream_rewriter.replaceRange(ctx.start.tokenIndex,
                                                    ctx.stop.tokenIndex,
                                                    new_code)

    def exitPrimary(self, ctx: Java9_v2Parser.PrimaryContext):
        if ctx.getChildCount() == 2:
            if ctx.getText() == 'this.' + self.field_identifier or ctx.getText(
            ) == self.field_identifier:
                new_code = 'this.get' + str.capitalize(
                    self.field_identifier) + '()'
                self.token_stream_rewriter.replaceRange(
                    ctx.start.tokenIndex, ctx.stop.tokenIndex, new_code)

    def enterCompilationUnit1(self,
                              ctx: Java9_v2Parser.CompilationUnit1Context):
        hidden = self.token_stream.getHiddenTokensToLeft(ctx.start.tokenIndex)
        self.token_stream_rewriter.replaceRange(
            from_idx=hidden[0].tokenIndex,
            to_idx=hidden[-1].tokenIndex,
            text='/*After refactoring (Refactored version)*/\n')
Пример #28
0
class ExtractClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None,
                 method_map: dict = None):
        if method_map is None:
            self.method_map = {}
        else:
            self.method_map = method_map

        if moved_methods is None:
            self.moved_methods = []
        else:
            self.moved_methods = moved_methods
        if moved_fields is None:
            self.moved_fields = []
        else:
            self.moved_fields = moved_fields

        if common_token_stream is None:
            raise ValueError("common_token_stream is None")
        else:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

        if source_class is None:
            raise ValueError("source_class is None")
        else:
            self.source_class = source_class
        if new_class is None:
            raise ValueError("new_class is None")
        else:
            self.new_class = new_class

        self.is_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.package_name = ""
        self.parameters = []
        self.object_name = self.new_class.replace(
            self.new_class, self.new_class[0].lower() + self.new_class[1:])
        self.modifiers = ""

        self.do_increase_visibility = False

        temp = []
        for method in moved_methods:
            temp.append(self.method_map.get(method))
        self.fields_to_increase_visibility = set().union(*temp)

    def enterPackageDeclaration(
            self, ctx: JavaParserLabeled.PackageDeclarationContext):
        if ctx.qualifiedName() and not self.package_name:
            self.package_name = ctx.qualifiedName().getText()
            self.code += f"package {self.package_name};{self.NEW_LINE}"

    def enterImportDeclaration(
            self, ctx: JavaParserLabeled.ImportDeclarationContext):
        i = self.token_stream_rewriter.getText(
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            start=ctx.start.tokenIndex,
            stop=ctx.stop.tokenIndex)
        self.code += f"\n{i}\n"

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = str(ctx.children[1])
        if class_identifier == self.source_class:
            self.is_source_class = True
            self.code += self.NEW_LINE * 2
            self.code += f"// New class({self.new_class}) generated by CodART" + self.NEW_LINE
            self.code += f"class {self.new_class}{self.NEW_LINE}" + "{" + self.NEW_LINE
        else:
            self.is_source_class = False

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if self.is_source_class:
            self.token_stream_rewriter.insertAfterToken(
                token=ctx.start,
                text="\n\t" +
                f"public {self.new_class} {self.object_name} = new {self.new_class}();",
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME)

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = str(ctx.children[1])
        if class_identifier == self.source_class:
            self.code += "}"
            self.is_source_class = False
        else:
            self.is_source_class = True

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        pass

    def enterVariableDeclaratorId(
            self, ctx: JavaParserLabeled.VariableDeclaratorIdContext):
        if not self.is_source_class:
            return None
        field_identifier = ctx.IDENTIFIER().getText()
        if field_identifier in self.moved_fields:
            self.detected_field = field_identifier

    def enterFieldDeclaration(self,
                              ctx: JavaParserLabeled.FieldDeclarationContext):
        field_names = ctx.variableDeclarators().getText().split(",")
        for field in field_names:
            if field in self.fields_to_increase_visibility:
                for modifier in ctx.parentCtx.parentCtx.modifier():
                    if modifier.getText() == "private":
                        self.token_stream_rewriter.replaceSingleToken(
                            token=modifier.start, text="public")

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        if not self.detected_field:
            return None

        field_names = ctx.variableDeclarators().getText()
        field_names = field_names.split(',')
        grand_parent_ctx = ctx.parentCtx.parentCtx
        if any([self.detected_field in i for i in field_names]):
            field_type = ctx.typeType().getText()

            if len(field_names) == 1:
                self.code += f"public {field_type} {field_names[0]};{self.NEW_LINE}"
            else:
                self.code += f"public {field_type} {self.detected_field};{self.NEW_LINE}"
            # delete field from source class
            for i in field_names:
                if self.detected_field in i:
                    field_names.remove(i)

            if field_names:
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.start.tokenIndex,
                    to_idx=grand_parent_ctx.stop.tokenIndex,
                    text=f"public {field_type} {','.join(field_names)};\n")
            else:
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=grand_parent_ctx.start.tokenIndex,
                    to_idx=grand_parent_ctx.stop.tokenIndex)
            self.detected_field = None

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if method_identifier in self.moved_methods:
            self.detected_method = method_identifier

    def enterFormalParameter(self,
                             ctx: JavaParserLabeled.FormalParameterContext):
        if self.detected_method:
            self.parameters.append(
                ctx.variableDeclaratorId().IDENTIFIER().getText())

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class:
            return None
        method_identifier = ctx.IDENTIFIER().getText()
        if self.detected_method == method_identifier:
            start_index = ctx.start.tokenIndex
            stop_index = ctx.stop.tokenIndex
            method_text = self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=start_index,
                stop=stop_index)
            self.code += self.NEW_LINE + ("public " + method_text +
                                          self.NEW_LINE)
            # delegate method body in source class
            if self.method_map.get(method_identifier):
                self.parameters.append("this")

            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.methodBody().start.tokenIndex,
                to_idx=stop_index,
                text="{" +
                f"\nreturn this.{self.object_name}.{self.detected_method}(" +
                ",".join(self.parameters) + ");\n" + "}")
            self.parameters = []
            self.detected_method = None

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        identifier = ctx.IDENTIFIER()
        if identifier is not None:
            if identifier.getText(
            ) in self.moved_fields and self.detected_method not in self.moved_methods:
                # Found field usage!
                self.token_stream_rewriter.insertBeforeToken(
                    token=ctx.stop,
                    text=self.object_name + ".",
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME)