Beispiel #1
0
class RemoveMethodRefactoringListener(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=None,
                 method_name: str = None):

        if method_name is None:
            self.method_name = ""
        else:
            self.method_name = method_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.inner_class_count = 0
        self.is_static = False

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

        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = True
        elif self.is_source_class is True:
            self.inner_class_count += 1

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        class_identifier = ctx.IDENTIFIER().getText()
        if class_identifier == self.source_class:
            self.is_source_class = False
        elif self.is_source_class is True:
            self.inner_class_count -= 1

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_source_class or self.inner_class_count != 0:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        method_identifier = ctx.IDENTIFIER().getText()
        if self.method_name == method_identifier:
            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_method = None
    def testCombineInsertOnLeftWithDelete(self):
        input = InputStream('abc')
        lexer = TestLexer(input)
        stream = CommonTokenStream(lexer=lexer)
        stream.fill()
        rewriter = TokenStreamRewriter(tokens=stream)

        rewriter.delete('default', 0, 2)
        rewriter.insertBeforeIndex(0, 'z')

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

        rewriter.delete('default', 0, 2)
        rewriter.insertBeforeIndex(0, 'z')

        self.assertEquals('z', rewriter.getDefaultText())
Beispiel #4
0
class RemoveFieldRefactoringListener(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=None,
                 field_name: str = None):

        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.is_static = False

    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):
        # print("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&")
        if not self.is_source_class:
            return None
        field_identifier = ctx.variableDeclarators().variableDeclarator(
            0).variableDeclaratorId().IDENTIFIER().getText()
        # print("field_identifier:::::::::",field_identifier)
        if self.field_name in field_identifier:
            grand_parent_ctx = ctx.parentCtx.parentCtx
            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=grand_parent_ctx.start.tokenIndex,
                to_idx=grand_parent_ctx.stop.tokenIndex)
            self.detected_field = None
Beispiel #5
0
class RemoveClassRefactoringListener(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,
                 class_name: str = None):

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

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

        self.is_objective_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):
        print("self.objective_class: ", self.objective_class)
        class_identifier = ctx.IDENTIFIER().getText()
        ctxparent = ctx.parentCtx
        if self.objective_class == class_identifier:
            start_index = ctxparent.start.tokenIndex
            stop_index = ctxparent.stop.tokenIndex

            self.token_stream_rewriter.delete(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                from_idx=start_index,
                to_idx=stop_index)
            self.detected_method = None
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)
Beispiel #7
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)
Beispiel #8
0
class ReplaceDependentObjectsListener(JavaParserLabeledListener):
    """
    To implement the move class refactoring
    a stream of tokens is sent to the listener, to build an object token_stream_rewriter
    and we move all class methods and fields from the source package to the target package
    """

    def __init__(self, common_token_stream: CommonTokenStream = None, class_identifier: str = None,
                 source_package: str = None, target_package: str = None, filename: str = None, has_import: bool = None):
        """
        :param common_token_stream:
        """
        self.token_stream = common_token_stream

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

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

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

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

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

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

        self.need_import = False
        self.TAB = "\t"
        self.NEW_LINE = "\n"
        self.code = ""
        self.mul_imports = []
        self.exact_imports = []

    # Enter a parse tree produced by CompilationUnitContext
    def enterCompilationUnit(self, ctx: JavaParserLabeled.CompilationUnitContext):
        # Iterate over the declarations of context to save all import statements
        # in exact_imports and mul_imports
        for declaration in ctx.children:
            if isinstance(declaration, JavaParserLabeled.ImportDeclarationContext):
                imported_package = ""
                mul = None
                if declaration.qualifiedName() is not None:
                    imported_package += declaration.qualifiedName().getText()
                if declaration.MUL() is not None:
                    mul = declaration.MUL().getText()
                    imported_package += ".*"

                if mul is not None:
                    self.mul_imports.append(imported_package)
                else:
                    self.exact_imports.append(imported_package)

    # Exit a parse tree produced by JavaParserLabeled#importDeclaration.
    def exitImportDeclaration(self, ctx: JavaParserLabeled.ImportDeclarationContext):
        # extract the imported package from context
        imported_package = ""
        mul = None
        if ctx.qualifiedName() is not None:
            imported_package += ctx.qualifiedName().getText()
        if ctx.MUL() is not None:
            mul = ctx.MUL().getText()
            imported_package += '.' + ctx.MUL().getText()

        # return if the current import statement is not relevant to source package
        if self.source_package not in imported_package or (self.class_identifier not in imported_package and '*' not in imported_package):
            return

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

        target_exact_package = f"{self.target_package}.{self.class_identifier}"
        target_exact_import = f"import {target_exact_package};"

        if ctx.STATIC() is not None:
            target_exact_import = target_exact_import.replace("import", "import ")

        # handle import scenarios in files dependent on the moved class
        if target_exact_package in self.exact_imports:
            if mul is None:
                self.token_stream_rewriter.delete(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    from_idx=start_index,
                    to_idx=stop_index + 1
                )
        else:
            if mul is not None:
                self.token_stream_rewriter.insertAfter(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    index=stop_index,
                    text=self.NEW_LINE + target_exact_import
                )
            else:
                print(ctx.getText())
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    from_idx=start_index,
                    to_idx=stop_index,
                    text=target_exact_import
                )
            self.exact_imports.append(target_exact_package)

    # Exit a parse tree produced by JavaParserLabeled#classOrInterfaceType.
    def exitClassOrInterfaceType(self, ctx: JavaParserLabeled.ClassOrInterfaceTypeContext):
        if not self.has_import or not self.need_import:
            if self.class_identifier in ctx.getText().split('.'):
                self.need_import = True

    # Exit a parse tree produced by JavaParserLabeled#createdName0.
    def exitCreatedName0(self, ctx: JavaParserLabeled.CreatedName0Context):
        if not self.has_import or not self.need_import:
            if self.class_identifier in ctx.getText().split('.'):
                self.need_import = True

    # Exit a parse tree produced by JavaParserLabeled#expression1.
    def exitExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        if not self.has_import or not self.need_import:
            if ctx.expression().getText == self.class_identifier:
                self.need_import = True

    # Exit a parse tree produced by JavaParserLabeled#typeDeclaration.
    def exitTypeDeclaration(self, ctx: JavaParserLabeled.TypeDeclarationContext):
        if ctx.classDeclaration() is not None:
            if not self.has_import or self.need_import:
                index = ctx.start.tokenIndex

                # return if the file has already imported the package
                if (self.source_package + '.' + self.class_identifier not in self.exact_imports) \
                        or (self.target_package + '.' + self.class_identifier in self.exact_imports):
                    return

                # delete class declaration from source class
                self.token_stream_rewriter.insertBefore(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    index=index,
                    text="import " + self.target_package + '.' + self.class_identifier + ';' + self.NEW_LINE
                )
Beispiel #9
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)
Beispiel #10
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
Beispiel #11
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)
Beispiel #12
0
class ExtractSubClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None,
                 output_path: str = ""):

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

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

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

        self.output_path = output_path

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

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

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

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

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

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

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

            self.detected_field = None

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

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

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

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

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

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

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

        self.is_in_constructor = False

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

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        if self.is_source_class and self.is_in_constructor:
            self.methods_in_constructor.append(ctx.IDENTIFIER())
Beispiel #13
0
class MoveClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement the move class refactoring
    a stream of tokens is sent to the listener, to build an object token_stream_rewriter
    and we move all class methods and fields from the source package to the target package
    """

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

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

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

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

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

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

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

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

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

        self.code += text_to_replace + self.NEW_LINE

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

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

        self.class_found = True

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

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

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

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

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

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

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

            self.enter_class = True
            self.class_found = True

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

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

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

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

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

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

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

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

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

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

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

        new_file = open(file_address, 'w')
        new_file.write(self.code.replace("\r", ""))
        print(f"The class \"{self.class_identifier}\" moved to the target package successfully!")
Beispiel #14
0
class RemoveFieldRefactoringListener(JavaParserLabeledListener):
    def __init__(self, common_token_stream: CommonTokenStream = None, class_identifier: str = None,
                 fieldname: str = None, filename: str = None):
        """
        :param common_token_stream:
        """
        self.enter_class = False
        self.enter_field = False
        self.is_found_field = False
        self.is_found = False
        self.token_stream = common_token_stream
        self.class_identifier = class_identifier
        self.class_number = 0

        # 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 = TSR(common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

        self.class_fields = []
        self.class_methods = []

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

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

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

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

        self.class_number += 1
        if ctx.IDENTIFIER().getText() != self.class_identifier:
            return
        self.enter_class = True

    # Enter a parse tree produced by Java9_v2Parser#normalClassDeclaration.
    # def enterNormalClassDeclaration(self, ctx: Java9_v2Parser.NormalClassDeclarationContext):
    #
    #     self.class_number += 1
    #     if ctx.identifier().getText() != self.class_identifier:
    #         return
    #     self.enter_class = True

    def exitClassDeclaration(self, ctx:JavaParserLabeled.ClassDeclarationContext):
        self.enter_class = False
        if ctx.IDENTIFIER().getText() != self.class_identifier:
            return

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

    # Exit a parse tree produced by Java9_v2Parser#normalClassDeclaration.
    # def exitNormalClassDeclaration(self, ctx: Java9_v2Parser.NormalClassDeclarationContext):
    #     self.enter_class = False
    #     if ctx.identifier().getText() != self.class_identifier:
    #         return
    #
    #     old_file = open(self.filename, 'w')
    #     old_file.write(self.token_stream_rewriter.getDefaultText().replace("\r", ""))
    #
    #     # print("----------------------------")
    #     # print("Class attributes: ", str(self.class_fields))
    #     # print("Class methods: ", str(self.class_methods))
    #     # print("----------------------------")

    # Enter a parse tree produced by Java9_v2Parser#fieldDeclaration.

    def enterFieldDeclaration(self, ctx:JavaParserLabeled.FieldDeclarationContext):
        if not self.enter_class:
            return
        self.enter_field = True
        self.is_found_field = False

    # def enterFieldDeclaration(self, ctx:Java9_v2Parser.FieldDeclarationContext):
    #     if not self.enter_class:
    #         return
    #     self.enter_field = True
    #     self.is_found_field = False

    # Exit a parse tree produced by Java9_v2Parser#fieldDeclaration.

    def exitClassBodyDeclaration2(self, ctx:JavaParserLabeled.ClassBodyDeclaration2Context):
        if not self.enter_class:
            return

        # print("Enter 'exitFieldDeclaration' Methode")
        start = ctx.start.tokenIndex
        stop = ctx.stop.tokenIndex

        if (self.is_found_field):
            self.token_stream_rewriter.delete(program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                                              from_idx=start,
                                              to_idx=stop)
            print(f'Field: "{self.fieldname}" SUCCESSFULLY REMOVED...')

    # def exitFieldDeclaration(self, ctx:JavaParserLabeled.FieldDeclarationContext):
    #     if not self.enter_class:
    #         return
    #
    #     # print("Enter 'exitFieldDeclaration' Methode")
    #     start = ctx.start.tokenIndex
    #     stop = ctx.stop.tokenIndex
    #
    #     if (self.is_found_field):
    #         self.token_stream_rewriter.delete(program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
    #                                           from_idx=start,
    #                                           to_idx=stop)
    #         print(f'Field: "{self.fieldname}" SUCCESSFULLY REMOVED...')

    # def exitFieldDeclaration(self, ctx: Java9_v2Parser.FieldDeclarationContext):
    #     if not self.enter_class:
    #         return
    #
    #     # print("Enter 'exitFieldDeclaration' Methode")
    #     start = ctx.start.tokenIndex
    #     stop = ctx.stop.tokenIndex
    #
    #     if (self.is_found_field):
    #         self.token_stream_rewriter.delete(program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
    #                                           from_idx=start,
    #                                           to_idx=stop)
    #         print(f'Field: "{self.fieldname}" SUCCESSFULLY REMOVED...')

    # Exit a parse tree produced by Java9_v2Parser#variableDeclaratorList.

    def exitVariableDeclarators(self, ctx:JavaParserLabeled.VariableDeclaratorsContext):
        if not (self.enter_class and self.enter_field):
            return
        # print("Enter 'exitVariableDeclaratorList' Methode")
        fields = ctx.getText().split(',')
        start = ctx.start.tokenIndex
        stop = ctx.stop.tokenIndex
        for index, field in enumerate(fields):
            if (self.fieldname == str(field).split('=')[0]):
                self.is_found = True
                self.is_found_field = True
                print(f'Find "{self.fieldname}", At: {start} - {stop}')
                if (len(fields) == 1):
                    return
                del fields[index]
                print('New: ' ,', '.join(str(field) for field in fields))
                self.token_stream_rewriter.replace(program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                                                   from_idx=start,
                                                   to_idx=stop,
                                                   text=', '.join(str(field) for field in fields))
                self.is_found_field = False
                print(f'Field: "{self.fieldname}" SUCCESSFULLY REMOVED...')
                break

    # def exitVariableDeclaratorList(self, ctx:Java9_v2Parser.VariableDeclaratorListContext):
    #     if not (self.enter_class and self.enter_field):
    #         return
    #     # print("Enter 'exitVariableDeclaratorList' Methode")
    #     fields = ctx.getText().split(',')
    #     start = ctx.start.tokenIndex
    #     stop = ctx.stop.tokenIndex
    #     for index, field in enumerate(fields):
    #         if (self.fieldname == str(field).split('=')[0]):
    #             self.is_found = True
    #             self.is_found_field = True
    #             print(f'Find "{self.fieldname}", At: {start} - {stop}')
    #             if (len(fields) == 1):
    #                 return
    #             del fields[index]
    #             print('New: ' ,', '.join(str(field) for field in fields))
    #             self.token_stream_rewriter.replace(program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
    #                                                from_idx=start,
    #                                                to_idx=stop,
    #                                                text=', '.join(str(field) for field in fields))
    #             self.is_found_field = False
    #             print(f'Field: "{self.fieldname}" SUCCESSFULLY REMOVED...')
    #             break

    def exitCompilationUnit(self, ctx:JavaParserLabeled.CompilationUnitContext):
        if not self.is_found:
            print(f'Field "{self.fieldname}" NOT FOUND...')
Beispiel #15
0
class PropagationMakeAbstractClassRefactoringListener(JavaParserLabeledListener
                                                      ):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 Source_class=None,
                 object_name=None,
                 propagated_class_name=None):

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

        if object_name is None:
            self.object_name = []
        else:
            self.object_name = object_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

    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

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if not self.is_class:
            return None
        self.token_stream_rewriter.insertBefore(
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            index=ctx.start.tokenIndex,
            text=' extends ' + self.source_class)

    def enterVariableDeclarator(
            self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        if not self.is_class:
            return None
        ctx_grandparent = ctx.parentCtx.parentCtx
        if ctx.variableDeclaratorId().IDENTIFIER().getText(
        ) in self.object_name:
            self.objectName = ctx.variableDeclaratorId().IDENTIFIER().getText()
            if ctx_grandparent.typeType().classOrInterfaceType().IDENTIFIER(
                    0).getText() in self.source_class:
                self.token_stream_rewriter.delete(
                    from_idx=ctx_grandparent.start.tokenIndex,
                    to_idx=ctx_grandparent.stop.tokenIndex,
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME)

    def enterExpression(self, ctx: JavaParserLabeled.ExpressionContext):
        if not self.is_class:
            return None
        if ctx.expression(0) != None:
            if ctx.expression(0).primary() != None:
                if ctx.expression(0).primary().IDENTIFIER().getText(
                ) in self.object_name:
                    count = ctx.getChildCount()
                    if count == 3:
                        self.token_stream_rewriter.replaceRange(
                            from_idx=ctx.start.tokenIndex,
                            to_idx=ctx.stop.tokenIndex,
                            text=ctx.children[count - 1].getText())
Beispiel #16
0
class ExtractClassRefactoringListener(JavaParserLabeledListener):
    """
    To implement extract class refactoring based on its actors.
    Creates a new class and move fields and methods from the old class to the new one
    """
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 source_class: str = None,
                 new_class: str = None,
                 moved_fields=None,
                 moved_methods=None,
                 method_map: dict = None):
        if method_map is None:
            self.method_map = {}
        else:
            self.method_map = method_map

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

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

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

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

        self.do_increase_visibility = False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def enterExpression1(self, ctx: JavaParserLabeled.Expression1Context):
        identifier = ctx.IDENTIFIER()
        if identifier is not None:
            if identifier.getText(
            ) in self.moved_fields and self.detected_method not in self.moved_methods:
                # Found field usage!
                self.token_stream_rewriter.insertBeforeToken(
                    token=ctx.stop,
                    text=self.object_name + ".",
                    program_name=self.token_stream_rewriter.
                    DEFAULT_PROGRAM_NAME)
Beispiel #17
0
class myExtractClassRefactoringListener(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}{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
Beispiel #18
0
class CollapseHierarchyRefactoringListener(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,
                 parent_class=None,
                 child_class=None,
                 field_text: str = None,
                 method_text: str = None):

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

        if field_text is None:
            self.field_text = []
        else:
            self.field_text = field_text
        if parent_class is None:
            self.parent_class = []
        else:
            self.parent_class = parent_class

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

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

        self.is_parent_class = False
        self.is_child_class = False
        self.detected_field = None
        self.detected_method = None

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

        elif class_identifier in self.child_class:
            self.is_child_class = True

        else:
            print("enter other class")
            self.is_parent_class = False

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

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

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        if not self.is_child_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        # delete method from source class
        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_method = None

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        if not self.is_child_class:
            return None
        grand_parent_ctx = ctx.parentCtx.parentCtx
        # delete field from source class
        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 exitCompilationUnit(self,
                            ctx: JavaParserLabeled.CompilationUnitContext):
        pass
Beispiel #19
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)
Beispiel #20
0
class RemoveDeadCodeClass(JavaParserLabeledListener):
    def __init__(self,
                 Tokens: CommonTokenStream = None,
                 Identifier: {} = None):
        self.Class = False
        self.Method = False
        self.Field = False
        self.Variable = False
        self.Parameter = False

        self.Classes = Identifier["Classes"]
        self.ClassIndex = 0

        self.Methods = Identifier["Methods"]
        self.MethodIndex = 0
        self.IsSourceClassForMethods = [None] * len(self.Methods)

        self.Fields = Identifier["Fields"]
        self.FieldIndex = 0
        self.IsSourceClassForFields = [None] * len(self.Fields)

        self.Variables = Identifier["Variables"]
        self.VariableIndex = 0
        self.IsSourceClassForVariables = [None] * len(self.Variables)
        self.IsSourceMethodForVariables = [None] * len(self.Variables)

        self.Parameters = Identifier["Parameters"]
        self.ParameterIndex = 0
        self.IsSourceClassForParameters = [None] * len(self.Parameters)
        self.IsSourceMethodForParameters = [None] * len(self.Parameters)

        if len(Identifier["Classes"]) != 0:
            self.Class = True

        if len(Identifier["Methods"]) != 0:
            self.Method = True

        if len(Identifier["Fields"]) != 0:
            self.Field = True
        if len(Identifier["Variables"]) != 0:
            self.Variable = True

        if len(Identifier["Parameters"]) != 0:
            self.Parameter = True

        if Tokens is not None:
            self.CodeRewrite = TokenStreamRewriter(Tokens)
        else:
            raise TypeError('Tokens is None')

    def enterClassDeclaration(self,
                              ctx: JavaParserLabeled.ClassDeclarationContext):
        classIdentifier = ctx.IDENTIFIER().getText()
        ctxParent = ctx.parentCtx
        if self.Method:
            for i in range(len(self.Methods)):
                if self.Methods[i].split('/')[0] == classIdentifier:
                    self.IsSourceClassForMethods[i] = True

        if self.Field:
            for i in range(len(self.Fields)):
                if self.Fields[i].split('/')[0] == classIdentifier:
                    self.IsSourceClassForFields[i] = True

        if self.Variable:
            for i in range(len(self.Variables)):
                if self.Variables[i].split('/')[0] == classIdentifier:
                    self.IsSourceClassForVariables[i] = True

        if self.Parameter:
            for i in range(len(self.Parameters)):
                if self.Parameters[i].split('/')[0] == classIdentifier:
                    self.IsSourceClassForParameters[i] = True

        if self.Class and self.ClassIndex < len(self.Classes) and self.Classes[
                self.ClassIndex] == classIdentifier:
            startIndex = ctxParent.start.tokenIndex
            stopIndex = ctxParent.stop.tokenIndex

            self.CodeRewrite.delete(self.CodeRewrite.DEFAULT_PROGRAM_NAME,
                                    startIndex, stopIndex)
            self.ClassIndex += 1

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        pass

    def enterMethodDeclaration(
            self, ctx: JavaParserLabeled.MethodDeclarationContext):
        methodIdentifier = ctx.IDENTIFIER().getText()
        if self.Variable:
            for i in range(len(self.Variables)):
                if self.IsSourceClassForVariables[i] and self.Variables[
                        i].split('/')[1] == methodIdentifier:
                    self.IsSourceMethodForVariables[i] = True

        if self.Parameter:
            for i in range(len(self.Parameters)):
                if self.IsSourceClassForParameters[i] and self.Parameters[
                        i].split('/')[1] == methodIdentifier:
                    self.IsSourceMethodForParameters[i] = True
        pass

    def exitMethodDeclaration(self,
                              ctx: JavaParserLabeled.MethodDeclarationContext):
        grandParentCtx = ctx.parentCtx.parentCtx
        methodIdentifier = ctx.IDENTIFIER().getText()
        if self.Method and self.MethodIndex < len(
                self.Methods) and self.Methods[self.MethodIndex].split(
                    '/')[1] == methodIdentifier:
            if self.IsSourceClassForMethods[self.MethodIndex]:
                self.CodeRewrite.delete(self.CodeRewrite.DEFAULT_PROGRAM_NAME,
                                        grandParentCtx.start.tokenIndex,
                                        grandParentCtx.stop.tokenIndex)
                self.MethodIndex += 1

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

    def exitFieldDeclaration(self,
                             ctx: JavaParserLabeled.FieldDeclarationContext):
        fieldIdentifier = ctx.variableDeclarators().variableDeclarator(
            0).variableDeclaratorId().IDENTIFIER().getText()
        grandParentCtx = ctx.parentCtx.parentCtx

        if self.Field and self.FieldIndex < len(self.Fields) and self.Fields[
                self.FieldIndex].split('/')[1] == fieldIdentifier:
            if self.IsSourceClassForFields[self.FieldIndex]:
                self.CodeRewrite.delete(self.CodeRewrite.DEFAULT_PROGRAM_NAME,
                                        grandParentCtx.start.tokenIndex,
                                        grandParentCtx.stop.tokenIndex)
                self.FieldIndex += 1

    def enterVariableDeclarator(
            self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        pass

    def exitVariableDeclarator(
            self, ctx: JavaParserLabeled.VariableDeclaratorContext):
        variableIdentifier = ctx.variableDeclaratorId().IDENTIFIER().getText()
        grandParentCtx = ctx.parentCtx.parentCtx.parentCtx
        if self.Variable and self.VariableIndex < len(
                self.Variables) and self.Variables[self.VariableIndex].split(
                    '/')[2] == variableIdentifier:
            if self.IsSourceClassForVariables[
                    self.VariableIndex] and self.IsSourceMethodForVariables[
                        self.VariableIndex]:
                self.CodeRewrite.delete(self.CodeRewrite.DEFAULT_PROGRAM_NAME,
                                        grandParentCtx.start.tokenIndex,
                                        grandParentCtx.stop.tokenIndex)
                self.VariableIndex += 1

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

    def exitFormalParameter(self,
                            ctx: JavaParserLabeled.FormalParameterContext):
        parameterIdentifier = ctx.variableDeclaratorId().IDENTIFIER().getText()
        grandParentCtx = ctx
        Parent = ctx.parentCtx.children
        # for i in range(len(Parent)):
        #     print(Parent[i].variableDeclaratorId().IDENTIFIER().getText())

        start = grandParentCtx.start.tokenIndex
        stop = grandParentCtx.stop.tokenIndex
        if self.Parameter and self.ParameterIndex < len(
                self.Parameters) and self.Parameters[
                    self.ParameterIndex].split('/')[2] == parameterIdentifier:
            if self.IsSourceClassForParameters[
                    self.ParameterIndex] and self.IsSourceMethodForParameters[
                        self.ParameterIndex]:
                self.CodeRewrite.delete(self.CodeRewrite.DEFAULT_PROGRAM_NAME,
                                        start, stop)
                self.ParameterIndex += 1

    def enterMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        parametersList = ctx.expressionList()
        # print(parametersList.parentCtx.IDENTIFIER().getText())
        if self.Parameter and parametersList.parentCtx.IDENTIFIER().getText(
        ) in self.Parameters:
            pass

    def exitMethodCall0(self, ctx: JavaParserLabeled.MethodCall0Context):
        pass
Beispiel #21
0
class InlineClassRefactoringListener(JavaParserLabeledListener):
    """

    To implement inline class refactoring based on its actors.

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

    """

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


        """

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

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

        self.field_that_has_source = []
        self.has_source_new = False

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

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

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

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

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

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

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

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

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

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

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

                if proper_constructor is None:
                    return

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

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

            type_text = ctx.typeTypeOrVoid().getText()

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

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

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

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

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

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

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

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

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

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

    def enterLocalVariableDeclaration(self, ctx: JavaParserLabeled.LocalVariableDeclarationContext):
        if ctx.typeType().classOrInterfaceType():
            if ctx.typeType().classOrInterfaceType().getText() == self.source_class and self.target_class:
                self.token_stream_rewriter.replace(
                    program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                    from_idx=ctx.typeType().start.tokenIndex,
                    to_idx=ctx.typeType().stop.tokenIndex,
                    text=self.target_class
                )
class MakeMethodNonStaticRefactoringListener(JavaParserLabeledListener):
    """

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

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


        """

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

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

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

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

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

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

    def enterConstructorDeclaration(
            self, ctx: JavaParserLabeled.ConstructorDeclarationContext):
        if self.is_target_class:
            if ctx.formalParameters().formalParameterList():
                constructor_parameters = [
                    ctx.formalParameters().formalParameterList().children[i]
                    for i in range(
                        len(ctx.formalParameters().formalParameterList().
                            children)) if i % 2 == 0
                ]
            else:
                constructor_parameters = []
            constructor_text = ''
            for modifier in ctx.parentCtx.parentCtx.modifier():
                constructor_text += modifier.getText() + ' '
                constructor_text += ctx.IDENTIFIER().getText()
            constructor_text += ' ( '
            for parameter in constructor_parameters:
                constructor_text += parameter.typeType().getText() + ' '
                constructor_text += parameter.variableDeclaratorId().getText(
                ) + ', '
            if constructor_parameters:
                constructor_text = constructor_text[:len(constructor_text) - 2]
            constructor_text += ')\n\t{'
            constructor_text += self.token_stream_rewriter.getText(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                start=ctx.block().start.tokenIndex + 1,
                stop=ctx.block().stop.tokenIndex - 1)
            constructor_text += '}\n'
            self.target_class_data['constructors'].append(
                ConstructorOrMethod(
                    name=self.target_class,
                    parameters=[
                        Parameter(parameterType=p.typeType().getText(),
                                  name=p.variableDeclaratorId().IDENTIFIER().
                                  getText()) for p in constructor_parameters
                    ],
                    text=constructor_text))
Beispiel #23
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