示例#1
0
    def testInsertAfterLastIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)
        rewriter.insertAfter(10, 'x')

        self.assertEqual(rewriter.getDefaultText(), 'abcx')
示例#2
0
class CollapseHierarchyRefactoringGetFieldTextListener(JavaParserLabeledListener):

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

        if child_class is None:
            self.moved_fields = []
        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.fieldcode = ""

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

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.child_class:
            self.is_source_class = True
            self.fieldcode += self.NEW_LINE * 2
            self.fieldcode += f"// child class({self.child_class}) fields: " + 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.fieldcode
        )

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

    def exitFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        self.detected_field = ctx.variableDeclarators().getText().split(',')
        print("Here it is a field")
        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 += " "
        field_type = ctx.typeType().getText()
        self.fieldcode += f"{self.TAB}{modifier} {field_type} {self.detected_field[0]};{self.NEW_LINE}"
    def testInsertAfterLastIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)
        rewriter.insertAfter(10, 'x')

        self.assertEquals(rewriter.getDefaultText(), 'abcx')
    def test2InsertBeforeAfterMiddleIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.insertBeforeIndex(1, 'x')
        rewriter.insertAfter(1, 'x')

        self.assertEquals(rewriter.getDefaultText(), 'axbxc')
示例#5
0
    def testReplaceRangeThenInsertAfterRightEdge(self):
        input = InputStream('abcccba')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceRange(2, 4, 'x')
        rewriter.insertAfter(4, 'y')

        self.assertEqual('abxyba', rewriter.getDefaultText())
    def testReplaceThenInsertAfterLastIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceIndex(2, 'x')
        rewriter.insertAfter(2, 'y')

        self.assertEquals('abxy', rewriter.getDefaultText())
    def testReplaceRangeThenInsertAfterRightEdge(self):
        input = InputStream('abcccba')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceRange(2, 4, 'x')
        rewriter.insertAfter(4, 'y')

        self.assertEquals('abxyba', rewriter.getDefaultText())
示例#8
0
    def test2InsertBeforeAfterMiddleIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.insertBeforeIndex(1, 'x')
        rewriter.insertAfter(1, 'x')

        self.assertEqual(rewriter.getDefaultText(), 'axbxc')
示例#9
0
    def testReplaceThenInsertAfterLastIndex(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.replaceIndex(2, 'x')
        rewriter.insertAfter(2, 'y')

        self.assertEqual('abxy', rewriter.getDefaultText())
示例#10
0
class AddingImplementStatementToClass(JavaParserLabeledListener):
    def __init__(self, common_token_stream, class_name, interface_package,
                 interface_name):
        self.common_token_stream = common_token_stream
        self.class_name = class_name
        self.interface_package = interface_package
        self.interface_name = interface_name
        self.last_import_token_index = None
        self.implement_token_index = None
        self.implement_state = []

        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)

    def enterPackageDeclaration(
            self, ctx: JavaParserLabeled.PackageDeclarationContext):
        self.last_import_token_index = ctx.stop.tokenIndex

    def enterImportDeclaration(
            self, ctx: JavaParserLabeled.ImportDeclarationContext):
        self.last_import_token_index = ctx.stop.tokenIndex

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        if ctx.IDENTIFIER().getText() == self.class_name:
            self.implement_token_index = ctx.IDENTIFIER().symbol.tokenIndex
            if ctx.EXTENDS() is not None:
                self.implement_state.append(ctx.EXTENDS().getText())
                self.implement_token_index = ctx.typeType().stop.tokenIndex
            if ctx.IMPLEMENTS() is not None:
                self.implement_state.append(ctx.IMPLEMENTS().getText())
                self.implement_token_index = ctx.typeList().typeType(
                )[-1].stop.tokenIndex

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        import_text = f"\nimport {self.interface_package}.{self.interface_name};"
        self.token_stream_rewriter.insertAfter(
            self.last_import_token_index,
            import_text,
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME)

        if 'implements' in self.implement_state:
            implement_text = f",{self.interface_name}"
        else:
            implement_text = f" implements {self.interface_name}"

        self.token_stream_rewriter.insertAfter(
            self.implement_token_index,
            implement_text,
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME)
    def testPreservesOrderOfContiguousInserts(self):
        """
        Test for fix for: https://github.com/antlr/antlr4/issues/550
        """
        input = InputStream('aa')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.insertBeforeIndex(0, '<b>')
        rewriter.insertAfter(0, '</b>')
        rewriter.insertBeforeIndex(1, '<b>')
        rewriter.insertAfter(1, '</b>')

        self.assertEquals('<b>a</b><b>a</b>', rewriter.getDefaultText())
示例#12
0
    def testPreservesOrderOfContiguousInserts(self):
        """
        Test for fix for: https://github.com/antlr/antlr4/issues/550
        """
        input = InputStream('aa')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.insertBeforeIndex(0, '<b>')
        rewriter.insertAfter(0, '</b>')
        rewriter.insertBeforeIndex(1, '<b>')
        rewriter.insertAfter(1, '</b>')

        self.assertEqual('<b>a</b><b>a</b>', rewriter.getDefaultText())
示例#13
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))
示例#14
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)))
示例#15
0
class ReplaceParameterWithQueryListener(JavaParserLabeledListener):
    #constructor
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 target_class: str = None,
                 target_method: str = None,
                 target_parameters: 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("target class is None")
        else:
            self.target_class = target_class

        if target_method is None:
            raise ValueError("target method is None")
        else:
            self.target_method = target_method

        if target_parameters is None:
            self.target_parameters = []
        else:
            self.target_parameters = target_parameters

        self.current_class = None
        self.current_method = None
        self.current_method_call = None
        self.target_method_obj = None
        self.removed_expressions = []
        self.local_variables = []
        self.add_to_target_method = []
        self.index_of_parameter = 0

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        self.current_class = ctx.IDENTIFIER().getText()

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        self.current_class = None

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        self.current_method = ctx.IDENTIFIER().getText()
        if self.current_method == self.target_method and self.current_class == self.target_class:
            self.target_method_obj = ctx

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        self.FindObjrctIndex()

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        self.current_method = ctx.IDENTIFIER().getText()
        if self.current_method == self.target_method and self.current_class == self.target_class:
            self.target_method_obj = ctx

    def exitConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        self.FindObjrctIndex()

    def FindObjrctIndex(self):
        i = 0
        for expression in self.removed_expressions:
            #print("expression",expression.getText())
            if type(expression) is JavaParserLabeled.Expression0Context and \
                    type(expression.primary()) is JavaParserLabeled.Primary4Context:
                self.removeExpression(expression)
            else:
                self.add_to_target_method.append(expression.getText())
                #find index of target object
                self.index_of_parameter = i

            i += 1
        self.removed_expressions = []
        self.local_variables = []
        self.current_method = None

    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        self.local_variables.append(ctx.getText())
        #print(self.local_variables)

    #delete in method call
    def removeExpression(self, expression):
        for local_variable in self.local_variables:
            flag = False
            variable_declarator = local_variable.variableDeclarators()
            print("$", variable_declarator.children)
            remaining_variables = []
            for i in range(len(variable_declarator.children)):
                if i % 2 == 0:
                    vd = variable_declarator.children[i]
                    if expression.getText() != vd.variableDeclaratorId(
                    ).getText():
                        remaining_variables.append(vd.getText())
                    else:
                        self.add_to_target_method.append(
                            vd.variableInitializer().getText())
                        flag = True

            if len(remaining_variables) == 0:
                parent_ctx = local_variable.parentCtx
                #print("parent",parent_ctx)
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=parent_ctx.start.tokenIndex,
                    to_idx=parent_ctx.stop.tokenIndex)
            elif len(remaining_variables) < (
                    len(variable_declarator.children) + 1) // 2:
                self.token_stream_rewriter.replaceRange(
                    from_idx=variable_declarator.start.tokenIndex,
                    to_idx=variable_declarator.stop.tokenIndex,
                    text=f"{', '.join(remaining_variables)}")

            if flag:
                break

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        self.current_method_call = ctx.IDENTIFIER().getText()

    def exitMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        self.current_method_call = None


#in method call

    def enterExpressionList(self,
                            ctx: JavaParserLabeled.ExpressionListContext):
        if self.current_method_call == self.target_method:
            #print("ex",ctx.getText())
            expressions = []
            for i in range(len(ctx.children)):
                if i % 2 == 0:
                    if (i // 2) in self.target_parameters:
                        self.removed_expressions.append(ctx.children[i])
                    else:
                        expressions.append(ctx.children[i].getText())
                        #print(expressions)
                #else => ctx.children = ,
            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.stop.tokenIndex,
                text=f"{', '.join(expressions)}")

    #method body
    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        temp = ""
        if self.target_method_obj is not None:
            #print("self",self.index_of_parameter)
            #declaration
            ctx = self.target_method_obj
            text = ''
            formal_parameter_list = ctx.formalParameters().formalParameterList(
            )
            #print("b",ctx.formalParameters().formalParameterList().getText()[1])
            survived_parameters = []
            for j in range(len(formal_parameter_list.children)):
                #find object name to gain the name, insetr obj name in local variables
                if j % 2 == 0:
                    if (j // 2) not in self.target_parameters:
                        if j // 2 == self.index_of_parameter:
                            parameter = formal_parameter_list.children[j]
                            parameter_vdi = parameter.variableDeclaratorId(
                            ).getText()
                            temp = parameter_vdi

            for i in range(len(formal_parameter_list.children)):
                if i % 2 == 0:
                    if (i // 2) in self.target_parameters:
                        parameter = formal_parameter_list.children[i]
                        parameter_type = parameter.typeType().getText()
                        parameter_vdi = parameter.variableDeclaratorId(
                        ).getText()
                        #print("i",i)
                        #print("target",parameter_vdi)
                        parameter_initializer = self.add_to_target_method[0]

                        print("temp", temp)

                        text += parameter_type + ' ' + parameter_vdi + ' = ' + temp + '.' + parameter_initializer.split(".")[1] \
                                + ';' + "\n" + "\t" + "\t"
                        self.add_to_target_method.remove(parameter_initializer)

                    else:
                        parameter = formal_parameter_list.children[i]
                        parameter_type = parameter.typeType().getText()
                        parameter_vdi = parameter.variableDeclaratorId(
                        ).getText()
                        survived_parameters.append(parameter_type + ' ' +
                                                   parameter_vdi)
            #delete in declarition
            self.token_stream_rewriter.replaceRange(
                from_idx=formal_parameter_list.start.tokenIndex,
                to_idx=formal_parameter_list.stop.tokenIndex,
                text=f"{', '.join(survived_parameters)}")

            block_statement = ctx.methodBody().block().blockStatement()[0]
            self.token_stream_rewriter.insertAfter(
                index=block_statement.start.tokenIndex - 1, text=text)
示例#16
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)
示例#17
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
示例#18
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
示例#19
0
class PropagationMakeConcreteClassRefactoringListener(JavaParserLabeledListener
                                                      ):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 Source_class=None,
                 using_variable_name=None,
                 used_method_name=None,
                 propagated_class_name=None):

        if Source_class is None:
            self.source_class = []
        else:
            self.source_class = Source_class

        if used_method_name is None:
            self.using_method_name = []
        else:
            self.using_method_name = used_method_name

        if using_variable_name is None:
            self.using_variable_name = []
        else:
            self.using_variable_name = using_variable_name

        if propagated_class_name is None:
            self.propagated_class_name = []
        else:
            self.propagated_class_name = propagated_class_name

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

        self.is_class = False
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.object = ""

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        print("Propagation started, please wait...")
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier in self.propagated_class_name:
            self.is_class = True
        else:
            self.is_class = False

        if class_identifier in self.propagated_class_name:
            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.typeType().stop.tokenIndex,
                text=ctx.CLASS().getText() + ' ' + ctx.IDENTIFIER().getText())

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if not self.is_class:
            return None
        self.object = 'obj' + str.capitalize(self.source_class)
        self.token_stream_rewriter.insertAfter(
            index=ctx.start.tokenIndex,
            text=self.NEW_LINE + self.TAB + self.TAB + self.source_class +
            ' ' + self.object + ' = ' + 'new ' + self.source_class + '(' +
            ')' + ';' + self.NEW_LINE,
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME)

    def enterVariableDeclarator(
            self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        if not self.is_class:
            return None
        if ctx.variableDeclaratorId().IDENTIFIER().getText(
        ) in self.using_variable_name:
            count = ctx.getChildCount()
            if count == 3:
                self.token_stream_rewriter.insertBefore(
                    index=ctx.variableInitializer().start.tokenIndex,
                    text=self.object + '.',
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME)

    def enterExpression(self, ctx: JavaParserLabeled.ExpressionContext):
        if not self.is_class:
            return None
        if ctx != None:
            if ctx.methodCall() != None:
                if ctx.methodCall().IDENTIFIER().getText(
                ) in self.using_method_name:
                    count = ctx.methodCall().getChildCount()
                    if count == 3:
                        self.token_stream_rewriter.insertBefore(
                            index=ctx.start.tokenIndex,
                            text=self.object + '.',
                            program_name=self.token_stream_rewriter.
                            DEFAULT_PROGRAM_NAME)
示例#20
0
class FieldUsageListener(UtilsListener):
    """
    FieldUsageListener finds all the usage of
    an specified field f, from a class c in
    package pkg.
    """
    def __init__(self, filename: str, source_class: str, source_package: str,
                 target_class: str, target_package: str, field_name: str,
                 field_candidates: set, field_tobe_moved: Field):
        super(FieldUsageListener, self).__init__(filename)
        self.source_class = source_class
        self.source_package = source_package
        self.target_class = target_class
        self.target_package = target_package
        self.field_name = field_name
        self.has_imported_source = False
        self.has_imported_target = False
        self.usages = []
        # current class name is the public class in each file.
        self.current_class_name = ""
        self.field_candidates = field_candidates
        self.rewriter = None
        # this represents the text to be added in target i.e. public int a;
        self.field_tobe_moved = field_tobe_moved
        self.methods_tobe_updated = []

    def enterCompilationUnit(self, ctx: JavaParser.CompilationUnitContext):
        super().enterCompilationUnit(ctx)
        self.rewriter = TokenStreamRewriter(ctx.parser.getTokenStream())

    def enterClassDeclaration(self, ctx: JavaParser.ClassDeclarationContext):
        super().enterClassDeclaration(ctx)

        if ctx.parentCtx.classOrInterfaceModifier()[0].getText() == "public":
            self.current_class_name = ctx.IDENTIFIER().getText()
        else:
            return

        self.has_imported_source = self.file_info.has_imported_package(self.package.name) or \
                                   self.file_info.has_imported_class(self.package.name, self.source_class)

        # import target if we're not in Target and have not imported before
        if self.current_class_name != self.target_class:
            self.rewriter.insertBeforeIndex(
                ctx.parentCtx.start.tokenIndex,
                f"import {self.target_package}.{self.target_class};\n")

    def enterClassBody(self, ctx: JavaParser.ClassBodyContext):
        super().exitClassBody(ctx)
        if self.current_class_name == self.target_class:
            replacement_text = ""
            if self.field_tobe_moved.name == self.field_name:
                for mod in self.field_tobe_moved.modifiers:
                    replacement_text += f"{mod} "
                replacement_text += f"{self.field_tobe_moved.datatype} {self.field_tobe_moved.name};"
            self.rewriter.insertAfter(ctx.start.tokenIndex,
                                      f"\n\t{replacement_text}\n")

            # add getter and setter
            name = self.field_tobe_moved.name
            method_name = self.field_tobe_moved.name.upper(
            ) + self.field_tobe_moved.name[1:-1]
            type = self.field_tobe_moved.datatype

            getter = f"\tpublic {type} get{method_name}() {{ return this.{name}; }}\n"
            setter = f"\tpublic void set{method_name}({type} {name}) {{ this.{name} = {name}; }}\n"
            self.rewriter.insertBeforeIndex(ctx.stop.tokenIndex, getter)
            self.rewriter.insertBeforeIndex(ctx.stop.tokenIndex, setter)

    def exitFieldDeclaration(self, ctx: JavaParser.FieldDeclarationContext):
        super().exitFieldDeclaration(ctx)
        if self.current_class_name != self.source_class:
            return

        if self.field_tobe_moved is None:
            field = self.package.classes[self.current_class_name].fields[
                ctx.variableDeclarators().children[0].children[0].IDENTIFIER(
                ).getText()]
            if field.name == self.field_name:
                self.field_tobe_moved = field

    def exitClassBody(self, ctx: JavaParser.ClassBodyContext):
        super().exitClassBody(ctx)
        save(self.rewriter, self.filename)

    def exitMethodDeclaration(self, ctx: JavaParser.MethodDeclarationContext):
        super().exitMethodDeclaration(ctx)
        # we will remove getter and setter from source
        # and add it to target so there is no need to
        # find usages there

        if self.current_class_name == self.source_class and \
                self.is_method_getter_or_setter(ctx.IDENTIFIER().getText()):
            self.rewriter.replaceRange(
                ctx.parentCtx.parentCtx.start.tokenIndex,
                ctx.parentCtx.parentCtx.stop.tokenIndex, "")

    def exitConstructorDeclaration(
            self, ctx: JavaParser.ConstructorDeclarationContext):
        self.current_method.name = ctx.IDENTIFIER().getText()
        self.current_method.returntype = self.current_method.class_name
        self.handleMethodUsage(ctx, True)
        super().exitConstructorDeclaration(ctx)

    def exitMethodBody(self, ctx: JavaParser.MethodBodyContext):
        super().exitMethodBody(ctx)
        self.handleMethodUsage(ctx, False)

    def handleMethodUsage(self, ctx, is_constructor: bool):
        method_identifier = ctx.IDENTIFIER().getText(
        ) if is_constructor else ctx.parentCtx.IDENTIFIER().getText()
        formal_params = ctx.formalParameters(
        ) if is_constructor else ctx.parentCtx.formalParameters()
        target_added = False
        target_param_name = "$$target"
        target_param = f"Target {target_param_name}" if \
            len(self.current_method.parameters) == 0 \
            else f", Target {target_param_name}"

        # if we have not imported source package or
        # Source class just ignore this
        if not self.has_imported_source:
            return

        local_candidates = set()
        if self.current_class_name == self.source_class:
            # we will remove getter and setter from source
            # and add it to target so there is no need to
            # find usages there
            if self.is_method_getter_or_setter(method_identifier):
                self.rewriter.replaceRange(ctx.start.tokenIndex,
                                           ctx.stop.tokenIndex, "")
                return
            local_candidates.add("this")

        # find parameters with type Source
        for t, identifier in self.current_method.parameters:
            if t == self.source_class:
                local_candidates.add(identifier)

        # find all local variables with type Source
        for var_or_exprs in self.current_method.body_local_vars_and_expr_names:
            if type(var_or_exprs) is LocalVariable:
                if var_or_exprs.datatype == self.source_class:
                    local_candidates.add(var_or_exprs.identifier)

        should_ignore = False

        for var_or_exprs in self.current_method.body_local_vars_and_expr_names:
            if type(var_or_exprs) is ExpressionName:
                # we're going to find source.field
                try:
                    local_ctx = var_or_exprs.parser_context.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx
                    creator = local_ctx.expression()[0].getText()
                    if creator.__contains__(
                            f"new{self.source_class}"
                    ) and local_ctx.IDENTIFIER().getText() == self.field_name:
                        self.propagate_field(local_ctx, target_param_name)

                except:
                    pass

                if len(var_or_exprs.dot_separated_identifiers) < 2:
                    continue
                if (var_or_exprs.dot_separated_identifiers[0] in local_candidates or
                    var_or_exprs.dot_separated_identifiers[0] in self.field_candidates) and \
                        var_or_exprs.dot_separated_identifiers[1] == self.field_name:
                    if not target_added:
                        # add target to param
                        self.rewriter.insertBeforeIndex(
                            formal_params.stop.tokenIndex, target_param)
                        self.methods_tobe_updated.append(self.current_method)
                        target_added = True

                    self.usages.append(var_or_exprs.parser_context)
                    self.propagate_field(var_or_exprs.parser_context,
                                         target_param_name)

            elif type(var_or_exprs) is MethodInvocation:
                # we are going to find getter or setters
                # if len(var_or_exprs.dot_separated_identifiers) < 2:
                #     continue
                if var_or_exprs.dot_separated_identifiers[
                        0] == f"new{self.source_class}":
                    if var_or_exprs.parser_context.methodCall() is not None and \
                            self.is_method_getter_or_setter(
                                var_or_exprs.parser_context.methodCall().IDENTIFIER().getText()):
                        self.propagate_getter_setter(
                            var_or_exprs.parser_context, target_param_name)
                elif self.is_method_getter_or_setter(
                        var_or_exprs.dot_separated_identifiers[0]):
                    if not target_added:
                        # add target to param
                        self.rewriter.insertBeforeIndex(
                            formal_params.stop.tokenIndex, target_param)
                        self.methods_tobe_updated.append(self.current_method)
                        target_added = True
                    if not should_ignore and var_or_exprs.parser_context is not None and type(
                            var_or_exprs.parser_context
                    ) is not JavaParser.ExpressionContext:
                        continue
                    self.usages.append(var_or_exprs.parser_context)
                    self.propagate_getter_setter_form2(
                        var_or_exprs.parser_context, target_param_name)
                elif len(var_or_exprs.dot_separated_identifiers
                         ) > 1 and self.is_getter_or_setter(
                             var_or_exprs.dot_separated_identifiers[0],
                             var_or_exprs.dot_separated_identifiers[1],
                             local_candidates):
                    if not target_added:
                        # add target to param
                        self.rewriter.insertBeforeIndex(
                            formal_params.stop.tokenIndex, target_param)
                        self.methods_tobe_updated.append(self.current_method)
                        target_added = True

                    self.usages.append(var_or_exprs.parser_context)
                    self.propagate_getter_setter(var_or_exprs.parser_context,
                                                 target_param_name)

    def is_getter_or_setter(self, first_id: str, second_id: str,
                            local_candidates: set):
        return (
            first_id in local_candidates or first_id in self.field_candidates
        ) and (second_id
               == f"set{self.field_name[0].upper() + self.field_name[1:-1]}"
               or second_id
               == f"get{self.field_name[0].upper() + self.field_name[1:-1]}"
               or second_id
               == f"has{self.field_name[0].upper() + self.field_name[1:-1]}"
               or second_id
               == f"is{self.field_name[0].upper() + self.field_name[1:-1]}")

    def is_method_getter_or_setter(self, method: str):
        return (method
                == f"set{self.field_name[0].upper() + self.field_name[1:-1]}"
                or method
                == f"get{self.field_name[0].upper() + self.field_name[1:-1]}"
                or method
                == f"has{self.field_name[0].upper() + self.field_name[1:-1]}"
                or method
                == f"is{self.field_name[0].upper() + self.field_name[1:-1]}")

    def propagate_getter_setter(self, ctx: JavaParser.ExpressionContext,
                                target_name: str):
        index = ctx.DOT().symbol.tokenIndex
        self.rewriter.replaceRange(ctx.start.tokenIndex, index - 1,
                                   target_name)

    def propagate_getter_setter_form2(self, ctx: JavaParser.ExpressionContext,
                                      target_name: str):
        """
        form 2 is getA() setA()...
        """
        self.rewriter.insertBeforeIndex(ctx.start.tokenIndex,
                                        f"{target_name}.")

    def propagate_field(self, ctx: JavaParser.ExpressionContext,
                        target_name: str):
        index = ctx.DOT().symbol.tokenIndex
        self.rewriter.replaceRange(ctx.start.tokenIndex, index - 1,
                                   target_name)
示例#21
0
class ExtractMethodRefactoring(JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 class_name: str = "Main",
                 new_method_name: str = "newMethod"):
        """
        :param common_token_stream:
        :param class_name: the name of the class that duplications should be considered
        :param new_method_name: the name of the new method that contains that statements
        """
        self.common_token_stream = common_token_stream
        self.tokens = common_token_stream.tokens
        self.refactor_class_name = class_name
        self.new_method_name = new_method_name

        # make a copy of the tokens
        if common_token_stream is None:
            raise ValueError('common_token_stream is None')
        else:
            self.token_stream_re_writer = TokenStreamRewriter(
                common_token_stream)

        self.method_statements = {
        }  # dictionary that maps the methods to its statements

        # tree helper variables
        self.is_in_target_class = False
        self.is_in_a_method = False
        self.current_method_name = ""

        # refactoring
        self.duplicates = None  # if it is None, then we don't have any duplications

    ######################################
    # Collect statements from parse tree
    ######################################

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        print("enterClassDeclaration")
        if is_equal(ctx.IDENTIFIER(), self.refactor_class_name):
            self.is_in_target_class = True

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if is_equal(ctx.IDENTIFIER(), self.refactor_class_name):
            self.is_in_target_class = False
            self.find_duplicates()
            # print(self.duplicates.duplications[0].statements[0].statement.getText())
            if self.duplicates is not None and len(
                    self.duplicates.duplications) > 0:
                self.refactor(ctx)

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.is_in_target_class:
            self.is_in_a_method = True
            self.current_method_name = ctx.IDENTIFIER()
            self.method_statements[self.current_method_name] = []

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        self.is_in_a_method = False

    def enterStatement15(self, ctx: JavaParserLabeled.Statement0Context):
        if self.is_in_target_class:
            if self.is_in_a_method:
                self.method_statements[self.current_method_name].append(
                    Statement(ctx, []))

    def log_statements_of_methods(self):
        """
        It will print out statements of each method for the class.
        :return:
        """
        for method_name in self.method_statements.keys():
            print(method_name)
            statements = self.method_statements[method_name]
            for statement in statements:
                print(str(statement))
            print("---------------")

    ##########################
    # Searching Duplications
    ##########################

    def check_semi_duplicate(self, sa, sb, k):
        """
        It checks if the statements are similar or not. Two statements are similar if
        we can omit duplicated code with adding new method that has some arguments
        :param sa: first statements
        :param sb: second statement
        :param k: the k represent the index of the statements.
        :return:
        """
        fta, ftb = sa.statement.start.tokenIndex, sb.statement.start.tokenIndex
        tta, ttb = sa.statement.stop.tokenIndex, sb.statement.stop.tokenIndex

        if tta - fta != ttb - ftb:
            return False, sa, sb

        count = 0

        m = min(tta - fta, ttb - ftb)
        for i in range(m):
            txt_token_a = self.tokens[fta + i].text
            txt_token_b = self.tokens[ftb + i].text
            if txt_token_a != txt_token_b:
                if self.tokens[fta + i].type != self.tokens[ftb + i].type:
                    return False, sa, sb
                else:
                    history_a = list(map(lambda x: x[2], sa.variables))
                    history_b = list(map(lambda x: x[2], sb.variables))
                    count += 1
                    if txt_token_a not in history_a:
                        sa.variables.append((self.tokens[fta + i].type,
                                             "variable{}Number{}{}".format(
                                                 self.tokens[fta + i].type, k,
                                                 count), txt_token_a))
                    if txt_token_b not in history_b:
                        sb.variables.append((self.tokens[ftb + i].type,
                                             "variable{}Number{}{}".format(
                                                 self.tokens[ftb + i].type, k,
                                                 count), txt_token_b))

        return True, sa, sb

    def get_duplicate_continues_statements(self, a_statements, b_statements):
        """
        Find duplicate statements between two arrays of statements.
        :param a_statements: the first list of statements
        :param b_statements:  the second list of statements
        :return: (k, i, j) that k represent number of duplicated statements,
        and i, j are the list of the statements. The length of each of them is k.
        return could be None if there was not any duplications.
        There might be lots of duplications, but it would return the one that
        has the most duplicated statements.
        """
        len_a_statement = len(a_statements)
        len_b_statement = len(b_statements)

        # for any methods like such as getters or setters that have few number of
        # statements, we should return None.
        if len_b_statement <= 1 or len_a_statement <= 1:
            return None

        # diagnose exact duplications
        method_a_b_duplications = []
        i = 0
        while i < len_a_statement:
            j = 0
            while j < len_b_statement:
                sa = a_statements[i]
                sb = b_statements[j]
                count_duplicate_statement = 0
                a_duplicates = []
                b_duplicates = []
                k = 0
                while is_equal(sa.statement.getText(), sb.statement.getText()) \
                        and i + k < len_a_statement and j + k < len_b_statement:
                    sa = a_statements[i + k]
                    sb = b_statements[j + k]
                    count_duplicate_statement += 1
                    a_duplicates.append(sa)
                    b_duplicates.append(sb)
                    k += 1
                if count_duplicate_statement != 0:
                    method_a_b_duplications.append(
                        (count_duplicate_statement, a_duplicates.copy(),
                         b_duplicates.copy()))
                j += 1
            i += 1

        # calculate the maximum based on the number of duplications
        max_exact_duplicate = None
        if len(method_a_b_duplications) > 1:
            max_exact_duplicate = max(method_a_b_duplications,
                                      key=lambda x: x[0])

        # diagnose semi duplications
        # here we search for duplications that can be avoided by passing variable
        method_a_b_semi_duplications = []
        i = 0
        while i < len_a_statement:
            j = 0
            while j < len_b_statement:
                count_duplicate_statement = 0
                a_duplicates = []
                b_duplicates = []
                k = 0
                while i + k < len_a_statement and j + k < len_b_statement:
                    sa = a_statements.copy()[i + k]
                    sb = b_statements.copy()[j + k]
                    if is_equal(sa.statement.getText(),
                                sb.statement.getText()):
                        count_duplicate_statement += 1
                    else:
                        is_semi, sa, sb = self.check_semi_duplicate(
                            sa.copy(), sb.copy(), k)
                        if not is_semi:
                            break
                        count_duplicate_statement += 1
                    a_duplicates.append(sa.copy())
                    b_duplicates.append(sb.copy())
                    k += 1
                if count_duplicate_statement != 0:
                    method_a_b_semi_duplications.append(
                        (count_duplicate_statement, a_duplicates.copy(),
                         b_duplicates.copy()))
                j += 1
            i += 1

        # calculate the maximum based on the number of duplications
        max_semi_duplicate = None
        if len(method_a_b_semi_duplications) > 1:
            max_semi_duplicate = max(method_a_b_semi_duplications,
                                     key=lambda x: x[0])

        return max(max_exact_duplicate, max_semi_duplicate, key=lambda x: x[0])

    @staticmethod
    def log_duplication(duplicate, i, j, methods):
        """
        It will show you a report about the a duplications.
        :param duplicate: is a tuple that (k, i, j): k is the number of duplications,
        and i, j are the statements.
        :param i: index of the first method
        :param j: index of the second method
        :param methods: a list of methods that are existed in the class.
        :return:
        """
        print()
        print(
            "lines {}-{} in {} and lines {}-{} {} are duplicated. count: {}\n".
            format(duplicate[1][0].statement.start.line,
                   duplicate[1][-1].statement.start.line, methods[i].getText(),
                   duplicate[2][0].statement.start.line,
                   duplicate[2][-1].statement.start.line, methods[j].getText(),
                   duplicate[0]),
            list(map(lambda x: x.statement.getText(), duplicate[1])))

    def find_duplicates(self):
        """
        This method is responsible for choosing duplication and
        set it to self.duplicates. It will find the maximum lines of
        duplication, and search through all of the methods.
        This method compare each one of those methods using
        self.get_duplicate_continues_statements method.
        :return:
        """

        # it is for representing the statements of each method
        # self.log_statements_of_methods()

        # Compare each one of methods with the other methods
        methods = list(self.method_statements.keys())
        len_method = len(methods)
        i = 0
        duplicates = {
            "statements": [],
            "lines": [],
            "text": "",
            "variables": []
        }
        while i < len_method - 1:
            j = i + 1
            while j < len_method:
                duplicate = self.get_duplicate_continues_statements(
                    self.method_statements[methods[i]],
                    self.method_statements[methods[j]])

                # return value is None when not any duplications have been found.
                if duplicate is not None:
                    self.log_duplication(duplicate, i, j, methods)
                    if len(duplicates["statements"]) == 0:
                        duplicates["statements"].append(duplicate[1])
                        duplicates["variables"] = duplicate[1]
                        duplicates["lines"].append(
                            duplicate[1][0].statement.start.line)
                        for d in duplicate[1]:
                            duplicates["text"] += d.statement.getText()

                    # here we check how many duplications have been occurred.
                    # trying to find out similar duplications to change them all together.
                    for i in range(1, 3):
                        print(duplicate[i][0].statement.start.line)
                        if duplicate[i][
                                0].statement.start.line not in duplicates[
                                    "lines"]:
                            temp = ""
                            for d in duplicate[i]:
                                temp += d.statement.getText()
                            if temp == duplicates["text"]:
                                duplicates["statements"].append(duplicate[i])
                            else:
                                is_ok = True
                                if len(duplicate[i]) != len(
                                        duplicates["statements"][0]):
                                    break
                                else:
                                    for s1 in duplicates["statements"][0]:
                                        for s2 in duplicate[i]:
                                            if len(s1.variables) != len(
                                                    s2.variables):
                                                is_ok = False
                                                break
                                            else:
                                                for v1 in s1.variables:
                                                    for v2 in s2.variables:
                                                        if v1[0] != v2[0]:
                                                            is_ok = False
                                                            break
                                                    if is_ok:
                                                        duplicates[
                                                            "statements"].append(
                                                                duplicate[i])
                j += 1
            i += 1
        self.duplicates = DuplicationRefactoring(duplicates["statements"])

    ###############
    # Refactoring
    # Refactoring is in 2 steps.
    # First: Creating a new method at the end of the class.
    # Second: Deleting the duplications and replacing with new method.
    ###############

    def create_new_method(self, start_index):
        """
        It creates a new method based on the given name to avoid duplication.
        :param start_index: the index of token.
        :return:
        """
        # here we are creating the arguments
        d = self.duplicates.duplications[0]
        func_args = []
        for s in d.statements:
            for v in s.variables:
                arg_type = v[0]
                arg_name = v[1]
                try:
                    func_args.append(VariableTypes.MAP_TYPE[arg_type] + " " +
                                     arg_name)
                except:
                    pass
        func_args = ", ".join(func_args)

        # adding the new method
        new_method = "\n"
        new_method += "\tpublic void " + self.new_method_name + "(" + func_args + ") {\n"
        k = 0
        for statement_obj in self.duplicates.duplications[0].statements:
            if len(statement_obj.variables) == 0:
                new_method += "\t\t{}\n".format(
                    statement_obj.statement.getText())
            else:
                statement = "\t\t{}\n".format(
                    statement_obj.statement.getText())
                for v in statement_obj.variables:
                    statement = statement.replace(v[2], v[1])
                new_method += statement
            k += 1
        new_method += "\t}\n"
        new_method += "\n"

        self.token_stream_re_writer.insertAfter(start_index, new_method)

    def replace_duplicate_code(self):
        """
        Replaces all of the duplications with new method.
        :return:
        """
        self.duplicates.duplications.sort(key=lambda x: x.to_line,
                                          reverse=True)
        for duplicate in self.duplicates.duplications:
            # arguments
            variables = []
            for state in duplicate.statements:
                for v in state.variables:
                    variables.append(v)
            variables = list(map(lambda x: x[2], variables))
            # replacing
            start_index = duplicate.statements[0].statement.start.tokenIndex
            end_index = duplicate.statements[-1].statement.stop.tokenIndex
            self.token_stream_re_writer.replaceRange(
                start_index, end_index,
                "{}({});".format(self.new_method_name, ", ".join(variables)))
        # print(self.token_stream_re_writer.getDefaultText())

    def refactor(self, ctx):
        """
        Main method for refactoring.
        :param ctx:
        :return:
        """
        self.create_new_method(ctx.stop.tokenIndex - 1)
        self.replace_duplicate_code()
示例#22
0
class ReplaceConstructorWithFactoryFunctionRefactoringListener(JavaParserLabeledListener):

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

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

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

        self.is_target_class = False
        self.have_constructor = False
        self.new_factory_function = False
        self.new_parameters = []
        self.new_parameters_names = []

    def enterClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        # self.target_class = ctx.IDENTIFIER().getText()
        # have_constructor = False
        # if ctx.IDENTIFIER().getText() ==
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.target_class:
            self.is_target_class = True
            # print("class name " + ctx.IDENTIFIER().getText())
        else:
            self.is_target_class = False

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

    def enterConstructorDeclaration(self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_target_class:
            # print("constructor name " + ctx.IDENTIFIER().getText())
            # parameters = ctx.formalParameters().getText()
            # print(len(ctx.formalParameters().formalParameterList().formalParameter()))
            grandParentCtx = ctx.parentCtx.parentCtx
            if ctx.IDENTIFIER().getText() == self.target_class:
                self.have_constructor = True
                # do refactor
                """
                Declare the constructor private.
                """
                if grandParentCtx.modifier():
                    if 'public' == grandParentCtx.modifier(0).getText():
                        self.codeRewrite.replaceRange(
                            from_idx=grandParentCtx.modifier(0).start.tokenIndex,
                            to_idx=grandParentCtx.modifier(0).stop.tokenIndex,
                            text='private')
                else:
                    self.codeRewrite.insertBeforeIndex(
                        index=ctx.start.tokenIndex,
                        text="private "
                    )

    def exitConstructorDeclaration(self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        """
        Create a factory method. Make its body a call to the current constructor.
        """
        if self.is_target_class:
            grandParentCtx = ctx.parentCtx.parentCtx
            self.codeRewrite.insertAfter(
                index=grandParentCtx.stop.tokenIndex,
                text="\n    public static " + ctx.IDENTIFIER().getText() + " Create( " + ", ".join(
                    self.new_parameters) +
                     "){\n       return new " + ctx.IDENTIFIER().getText() + "(" + ", ".join(
                    self.new_parameters_names) + ");\n}"
            )
        self.new_parameters = []
        self.new_parameters_names = []

    def enterFormalParameterList0(self, ctx: JavaParserLabeled.FormalParameterList0Context):
        # print(len(ctx.formalParameter()))
        pass

    def exitFormalParameterList0(self, ctx: JavaParserLabeled.FormalParameterList0Context):
        pass

    def enterFormalParameter(self, ctx: JavaParserLabeled.FormalParameterContext):
        # print(ctx.typeType().getText())
        # print(ctx.variableDeclaratorId().getText())
        constructorName = ctx.parentCtx.parentCtx.parentCtx.IDENTIFIER().getText()
        if self.target_class == constructorName:
            text = ctx.typeType().getText() + " " + ctx.variableDeclaratorId().getText()
            self.new_parameters.append(text)
            self.new_parameters_names.append(ctx.variableDeclaratorId().getText())

    def exitFormalParameter(self, ctx: JavaParserLabeled.FormalParameterContext):
        pass

    def enterExpression4(self, ctx: JavaParserLabeled.Expression4Context):
        """
            Replace all constructor calls with calls to the factory method.
        """
        # currentMethodOrClassCtx=ctx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx
        # print(ctx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.parentCtx.getText())
        if ctx.creator().createdName().getText() == self.target_class:
            self.codeRewrite.replaceRange(
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.stop.tokenIndex,
                text=self.target_class + "." + "Create" + ctx.creator().classCreatorRest().getText())
示例#23
0
class SingletonRefactoringListener(JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 class_identifier: str = None):
        """
        :param common_token_stream:
        """
        self.enter_class = False
        self.token_stream = common_token_stream
        self.class_identifier = class_identifier
        self.ObjectIndex = []
        # 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.class_identifier:
            self.enter_class = True
            new_code = "\n\tprivate static " + self.class_identifier + " Instance = null;\n\t"
            self.token_stream_rewriter.insertAfter(
                ctx.classBody().start.tokenIndex + 1, new_code)
            self.addInstance = True

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.enter_class:
            self.enter_class = False
            new_code = ("\n\tpublic static " + self.class_identifier +
                        " getInstance()\n\t{\n\t\tif (Instance == null)" +
                        "\n\t\t\tInstance = new " + self.class_identifier +
                        "();" + "\n\t\treturn Instance;\n\t}\n")
            self.token_stream_rewriter.insertAfter(ctx.stop.tokenIndex - 1,
                                                   new_code)

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.enter_class:
            constructor_modifier = ctx.parentCtx.parentCtx
            if constructor_modifier.start.text == 'public':
                self.token_stream_rewriter.replaceRange(
                    from_idx=constructor_modifier.start.tokenIndex,
                    to_idx=constructor_modifier.start.tokenIndex,
                    text='private')

    def enterFieldDeclaration(self,
                              ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.enter_class:
            if ctx.start.text == self.class_identifier:
                start = ctx.variableDeclarators().variableDeclarator(
                    0).ASSIGN().symbol.tokenIndex + 1
                end = ctx.stop.tokenIndex
                self.ObjectIndex.append([start, end])

    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if not self.enter_class:
            if ctx.start.text == self.class_identifier:
                start = ctx.variableDeclarators().variableDeclarator(
                    0).ASSIGN().symbol.tokenIndex + 1
                end = ctx.stop.tokenIndex
                self.ObjectIndex.append([start, end])

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        for item in self.ObjectIndex:
            self.token_stream_rewriter.replaceRange(
                from_idx=item[0],
                to_idx=item[1],
                text=" " + self.class_identifier + ".getInstance()")
示例#24
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
class ReplaceParameterWithQueryRefactoringListener(JavaParserLabeledListener):
    """
    To implement replace parameter with query refactoring based on its actors.
    Find usages of target method and remove target parameters from these and add the removed parameters to
    top of target method.
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 target_class: str = None,
                 target_method: str = None,
                 target_parameters: 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("target class is None")
        else:
            self.target_class = target_class

        if target_method is None:
            raise ValueError("target method is None")
        else:
            self.target_method = target_method

        if target_parameters is None:
            self.target_parameters = []
        else:
            self.target_parameters = target_parameters

        self.current_class = None
        self.current_method = None
        self.current_method_call = None
        self.target_method_ctx = None
        self.removed_expressions = []
        self.all_local_variable_declarators = []
        self.add_to_top_of_target_method = []

        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        self.current_class = ctx.IDENTIFIER().getText()

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        self.current_class = None

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        self.current_method = ctx.IDENTIFIER().getText()
        if self.current_method == self.target_method and self.current_class == self.target_class:
            self.target_method_ctx = ctx

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        self.exit_method_or_constructor()

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        self.current_method = ctx.IDENTIFIER().getText()
        if self.current_method == self.target_method and self.current_class == self.target_class:
            self.target_method_ctx = ctx

    def exitConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        self.exit_method_or_constructor()

    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        self.all_local_variable_declarators.append(ctx)

    def remove_expression_declaration(self, expression):
        for lvd in self.all_local_variable_declarators:
            flag = False
            vds = lvd.variableDeclarators()
            survived_vds = []
            for i in range(len(vds.children)):
                if i % 2 == 0:
                    vd = vds.children[i]
                    if expression.getText() != vd.variableDeclaratorId(
                    ).getText():
                        survived_vds.append(vd.getText())
                    else:
                        self.add_to_top_of_target_method.append(
                            vd.variableInitializer().getText())
                        flag = True

            if len(survived_vds) == 0:
                parent_ctx = lvd.parentCtx
                print(type(parent_ctx))
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=parent_ctx.start.tokenIndex,
                    to_idx=parent_ctx.stop.tokenIndex)
            elif len(survived_vds) < (len(vds.children) + 1) // 2:
                self.token_stream_rewriter.replaceRange(
                    from_idx=vds.start.tokenIndex,
                    to_idx=vds.stop.tokenIndex,
                    text=f"{', '.join(survived_vds)}")

            if flag:
                break

    def exit_method_or_constructor(self):
        for expression in self.removed_expressions:
            if type(expression) is JavaParserLabeled.Expression0Context and \
                    type(expression.primary()) is JavaParserLabeled.Primary4Context:
                self.remove_expression_declaration(expression)

            else:
                self.add_to_top_of_target_method.append(expression.getText())

        self.removed_expressions = []
        self.all_local_variable_declarators = []
        self.current_method = None

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        self.current_method_call = ctx.IDENTIFIER().getText()

    def exitMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        self.current_method_call = None

    def enterExpressionList(self,
                            ctx: JavaParserLabeled.ExpressionListContext):
        if self.current_method_call == self.target_method:

            parameters = []
            for i in range(len(ctx.children)):
                if i % 2 == 0:
                    if ((i // 2) + 1) in self.target_parameters:
                        self.removed_expressions.append(ctx.children[i])
                    else:
                        parameters.append(ctx.children[i].getText())

            self.token_stream_rewriter.replaceRange(
                from_idx=ctx.start.tokenIndex,
                to_idx=ctx.stop.tokenIndex,
                text=f"{', '.join(parameters)}")

    def exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        if self.target_method_ctx is not None:
            ctx = self.target_method_ctx
            text = ''
            formal_parameter_list = ctx.formalParameters().formalParameterList(
            )
            survived_parameters = []
            for i in range(len(formal_parameter_list.children)):
                if i % 2 == 0:
                    if ((i // 2) + 1) in self.target_parameters:
                        parameter = formal_parameter_list.children[i]
                        parameter_type = parameter.typeType().getText()
                        parameter_vdi = parameter.variableDeclaratorId(
                        ).getText()
                        parameter_initializer = self.add_to_top_of_target_method[
                            0]
                        text += \
                            parameter_type + ' ' + parameter_vdi + ' = ' + parameter_initializer + \
                            ';' + self.NEW_LINE + self.TAB + self.TAB
                        self.add_to_top_of_target_method.remove(
                            parameter_initializer)

                    else:
                        parameter = formal_parameter_list.children[i]
                        parameter_type = parameter.typeType().getText()
                        parameter_vdi = parameter.variableDeclaratorId(
                        ).getText()
                        survived_parameters.append(parameter_type + ' ' +
                                                   parameter_vdi)

            self.token_stream_rewriter.replaceRange(
                from_idx=formal_parameter_list.start.tokenIndex,
                to_idx=formal_parameter_list.stop.tokenIndex,
                text=f"{', '.join(survived_parameters)}")

            block_statement = ctx.methodBody().block().blockStatement()[0]
            self.token_stream_rewriter.insertAfter(
                index=block_statement.start.tokenIndex - 1, text=text)
示例#26
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
示例#27
0
class MakeMethodStaticRefactoringListener(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,
                 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.is_target_class = False
        self.detected_instance_of_target_class = []
        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
        else:
            self.is_target_class = False

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

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        if self.is_target_class:
            if ctx.IDENTIFIER().getText() in self.target_methods:
                if 'this.' in ctx.getText():
                    raise ValueError("this method can not refactor")
                grand_parent_ctx = ctx.parentCtx.parentCtx
                if grand_parent_ctx.modifier():
                    if len(grand_parent_ctx.modifier()) == 2:
                        return None
                    else:
                        self.token_stream_rewriter.insertAfter(
                            index=grand_parent_ctx.modifier(0).stop.tokenIndex,
                            program_name=self.token_stream_rewriter.
                            DEFAULT_PROGRAM_NAME,
                            text=" static")
                else:
                    self.token_stream_rewriter.insertBeforeIndex(
                        index=ctx.start.tokenIndex, text="static ")

    def enterLocalVariableDeclaration(
            self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if ctx.typeType().getText() == self.target_class:
            self.detected_instance_of_target_class.append(
                ctx.variableDeclarators().variableDeclarator(
                    0).variableDeclaratorId().IDENTIFIER().getText())
            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 enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        if ctx.IDENTIFIER().getText() in self.target_methods:
            if ctx.parentCtx.expression().getText(
            ) in self.detected_instance_of_target_class:
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME,
                    from_idx=ctx.parentCtx.expression().start.tokenIndex,
                    to_idx=ctx.parentCtx.expression().stop.tokenIndex,
                    text=self.target_class)
示例#28
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)
示例#29
0
class VisitorPatternRefactoringListener(JavaParserLabeledListener):
    """
    implement the visitor pattern refactoring
    """

    def __init__(self, common_token_stream: CommonTokenStream = None,
                 SuperClass_identifier: str = None,
                 SubClass_identifier: list = None):
        """
        :param common_token_stream:
        """
        self.enter_class = False
        self.token_stream = common_token_stream
        self.SuperClass_identifier = SuperClass_identifier
        self.SubClass_identifier = SubClass_identifier
        self.InSuperClass = False
        self.InSubClass = False
        self.InMainClass = False
        self.CurrentCC = None
        self.Visitors = {}
        # 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.SuperClass_identifier:
            self.InSuperClass = True
        elif ctx.IDENTIFIER().getText() in self.SubClass_identifier:
            self.InSubClass = True
        elif ctx.IDENTIFIER().getText() == "Main":
            self.InMainClass = True

        if ctx.EXTENDS().__str__() == "extends":
            # SubClass Headers Rename
            self.token_stream_rewriter.insertAfter(ctx.start.tokenIndex + 4, "implements")
            self.token_stream_rewriter.deleteIndex(ctx.start.tokenIndex + 4)

    def exitClassDeclaration(self, ctx: JavaParserLabeled.ClassDeclarationContext):
        if self.InSuperClass:
            # SuperClass Interface Make
            interface_text = (
                    "interface "
                    + self.SuperClass_identifier
                    + "\n{\n\tpublic void accept (Visitor"
                    + self.SuperClass_identifier
                    + " visitor);\n}"
            )
            self.token_stream_rewriter.insertAfter(ctx.start.tokenIndex - 1, "\n" + interface_text + "\n")

            # SuperClass Visitor interface Make
            interface_text_vistor = "interface Visitor" + self.SuperClass_identifier + "\n{"
            index = 0
            for item in self.Visitors:
                interface_text_vistor += "\n\t" + "public void " + "visit(" + self.SubClass_identifier[
                    index] + " " + item + ");"
                index += 1
            interface_text_vistor += "\n}"
            self.token_stream_rewriter.insertAfter(ctx.start.tokenIndex - 1, "\n" + interface_text_vistor + "\n")
            # SuperClass DoVisitor Make
            newSC = (
                    "\nclass DoVisitor"
                    + self.SuperClass_identifier
                    + " implements Visitor"
                    + self.SuperClass_identifier + "\n{"
            )
            method_body = ""
            index = 0
            # SuperClassDoVisitor Mathods Make
            for item in self.Visitors:
                method_body = str_list(self.Visitors[item])
                method_body = "{\n\t" + method_body[2:-2] + "\n\t}"
                newSC += "\n\t" + "@Override\n\tpublic void visit(" + self.SubClass_identifier[
                    index] + " " + item + ")\n\t" + method_body
                index += 1
            newSC += "\n}"
            self.token_stream_rewriter.replaceRange(ctx.start.tokenIndex, ctx.stop.tokenIndex, newSC)
        self.InSuperClass = False
        self.InSubClass = False
        self.InMainClass = False

    def enterMethodDeclaration(self, ctx: JavaParserLabeled.MethodDeclarationContext):
        # Extract Methods Name & Methods body of SuperClass
        if self.InSuperClass:
            new_class_name = ctx.IDENTIFIER().getText()
            new_method_body = ctx.methodBody().getText()
            self.Visitors[new_class_name] = [new_method_body]

    def exitClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if self.InSubClass:
            # Implement Mathod of SuperClass InterFace
            override_text = (
                    "@Override\n\tpublic void accept(Visitor"
                    + self.SuperClass_identifier
                    + " visitor)\n\t{\n\t\tvisitor.visit(this);\n\t}"
            )
            self.token_stream_rewriter.insertAfter(ctx.start.tokenIndex, "\n\t" + override_text)

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        if self.InMainClass:
            # Modify Main Method
            if ctx.IDENTIFIER().getText() in self.Visitors:
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.start.tokenIndex,
                    to_idx=ctx.stop.tokenIndex,
                    text="accept(new DoVisitor" + self.SuperClass_identifier + "())")
示例#30
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)
示例#31
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,
                )
示例#32
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
示例#33
0
class MakeFieldStaticRefactoringListener(JavaParserLabeledListener):
    """
    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,
                 class_identifier: str = None,
                 package_identifier: str = None):
        """
        :param common_token_stream:
        """
        self.token_stream = common_token_stream
        self.field_identifier = field_identifier
        self.class_identifier = class_identifier
        self.package_identifier = package_identifier
        self.declared_objects_names = []

        self.is_package_imported = False
        self.in_selected_package = False
        self.in_selected_class = False
        self.in_some_package = 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):
        self.in_some_package = True
        if self.package_identifier is not None:
            if self.package_identifier == ctx.qualifiedName().getText():
                self.in_selected_package = True
                print("Package Found")

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

        if self.package_identifier is None and not self.in_some_package or\
                self.package_identifier is not None and self.in_selected_package:
            if ctx.IDENTIFIER().getText() == self.class_identifier:
                print("Class Found")
                self.in_selected_class = True

    def enterImportDeclaration(
            self, ctx: JavaParserLabeled.ImportDeclarationContext):
        if self.package_identifier is not None:
            if ctx.getText() == "import" + self.package_identifier + "." + self.class_identifier + ";" \
                    or ctx.getText() == "import" + self.package_identifier + ".*" + ";" \
                    or ctx.getText() == "import" + self.package_identifier + ";":
                self.is_package_imported = True

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        if self.package_identifier is None and not self.in_some_package\
                or self.package_identifier is not None and self.in_selected_package:
            if self.in_selected_class:
                if ctx.variableDeclarators().variableDeclarator(0)\
                        .variableDeclaratorId().getText() == self.field_identifier:

                    grand_parent_ctx = ctx.parentCtx.parentCtx
                    if len(grand_parent_ctx.modifier()) == 0:
                        self.token_stream_rewriter.insertBeforeIndex(
                            index=ctx.parentCtx.start.tokenIndex,
                            text=' static ')
                    else:
                        is_static = False
                        for modifier in grand_parent_ctx.modifier():
                            if modifier.getText() == "static":
                                is_static = True
                                break
                        if not is_static:
                            self.token_stream_rewriter.insertAfter(
                                index=grand_parent_ctx.start.tokenIndex +
                                len(grand_parent_ctx.modifier()),
                                text=' static ')

        if self.package_identifier is None or self.package_identifier is not None and self.is_package_imported:
            if ctx.typeType().classOrInterfaceType() is not None:
                if ctx.typeType().classOrInterfaceType().getText(
                ) == self.class_identifier:
                    self.declared_objects_names.append(
                        ctx.variableDeclarators().variableDeclarator(
                            0).variableDeclaratorId().getText())
                    print("Object " + ctx.variableDeclarators().variableDeclarator(0).variableDeclaratorId().getText()\
                          + " of type " + self.class_identifier + " found.")

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if self.is_package_imported or self.package_identifier is None or self.in_selected_package:
            for object_name in self.declared_objects_names:
                if ctx.getText() == object_name + "." + self.field_identifier:
                    self.token_stream_rewriter.replaceIndex(
                        index=ctx.start.tokenIndex, text=self.class_identifier)
示例#34
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)
示例#35
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')
class IncreaseFieldVisibilityRefactoringListener(JavaParserLabeledListener):
    """
    ## Introduction

    Increase the visibility of a field from private to package, package to protected or protected to public.

    ## Pre and Post Conditions

    ### Pre Conditions:

    1. User must enter the field's name, and the source class's name for the refactoring
       in order to increase the target field's visibility.

    ### Post Conditions:

    No specific Post Condition
    """

    def __init__(self, common_token_stream: CommonTokenStream = None, source_class=None, field_name: str = None):
        """To implement Increase Field Visibility refactoring based on its actors.
           Detects the required field and increases/changes its visibility status.

           Args:
                common_token_stream (CommonTokenStream): A stream of tokens generated by parsing the main file using the ANTLR parser generator

                source_class (str): Name of the class in which the refactoring has to be done

                field_name (str): Name of the field whose visibility status has to be changed

           Returns:
                No returns
        """
        if field_name is None:
            self.field_name = ""
        else:
            self.field_name = field_name

        if source_class is None:
            self.source_class = ""
        else:
            self.source_class = source_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_source_class = False
        self.detected_field = None
        self.detected_method = None
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.tempdeclarationcode = ""

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

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
        else:
            self.is_source_class = False

    def exitFieldDeclaration(self, ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_source_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        # field_identifier = ctx.variableDeclarators().getText().split(",")
        field_identifier = ctx.variableDeclarators().variableDeclarator(0).variableDeclaratorId().IDENTIFIER().getText()
        if self.field_name in field_identifier:
            if grand_parent_ctx.modifier() == []:
                self.token_stream_rewriter.replaceRange(
                    from_idx=ctx.typeType().start.tokenIndex,
                    to_idx=ctx.typeType().stop.tokenIndex,
                    text='private ' + ctx.typeType().getText()
                )
            elif grand_parent_ctx.modifier(0).getText() == 'public':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private')
            elif grand_parent_ctx.modifier(0).getText() != 'private':
                self.token_stream_rewriter.replaceRange(
                    from_idx=grand_parent_ctx.modifier(0).start.tokenIndex,
                    to_idx=grand_parent_ctx.modifier(0).stop.tokenIndex,
                    text='private ' + grand_parent_ctx.modifier(0).getText())
            # generate accessor and mutator methods
            # Accessor body
            new_code = '\n\t'
            new_code += 'public ' + ctx.typeType().getText() + ' get' + str.capitalize(self.field_name)
            new_code += '() { \n\t\t return this.' + self.field_name + ';' + '\n\t}'

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

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