Пример #1
0
class PushDownMethodRefactoringListener(JavaParserLabeledListener):
    """


    """
    def __init__(self, common_token_stream: CommonTokenStream,
                 source_class: str, source_method_text: str):
        """

        """

        self.source_method_text = source_method_text
        self.source_class = source_class
        self.token_stream_rewriter = TokenStreamRewriter(common_token_stream)
        self.is_safe = False

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

    def exitClassDeclaration(self,
                             ctx: JavaParserLabeled.ClassDeclarationContext):
        self.is_safe = not self.is_safe

    def enterClassBody(self, ctx: JavaParserLabeled.ClassBodyContext):
        if self.is_safe:
            self.token_stream_rewriter.insertBefore(
                index=ctx.stop.tokenIndex,
                text=self.source_method_text + "\n",
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME)
Пример #2
0
class PropagationMakeConcreteClassRefactoringListener(JavaParserLabeledListener
                                                      ):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 Source_class=None,
                 using_variable_name=None,
                 used_method_name=None,
                 propagated_class_name=None):

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

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

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

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

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

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

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

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

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

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

    def enterExpression(self, ctx: JavaParserLabeled.ExpressionContext):
        if not self.is_class:
            return None
        if ctx != None:
            if ctx.methodCall() != None:
                if ctx.methodCall().IDENTIFIER().getText(
                ) in self.using_method_name:
                    count = ctx.methodCall().getChildCount()
                    if count == 3:
                        self.token_stream_rewriter.insertBefore(
                            index=ctx.start.tokenIndex,
                            text=self.object + '.',
                            program_name=self.token_stream_rewriter.
                            DEFAULT_PROGRAM_NAME)
Пример #3
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())
Пример #4
0
class FactoryMethodRefactoringListener(JavaParserLabeledListener):
    def __init__(self,
                 common_token_stream: CommonTokenStream = None,
                 creator_identifier: str = None,
                 products_identifier: list = None):
        self.enter_class = False
        self.token_stream = common_token_stream
        self.creator_identifier = creator_identifier
        self.products_identifier = products_identifier
        self.interfaceName = "ProductsAbstract"
        self.inCreator = False
        self.inProducts = False
        self.productsMethod = {}
        self.productsClassIndex = []
        self.productVarTypeIndex = []
        self.productVarValueIndex = []
        self.productConstructorMethod = []
        self.productConstructorParam = {}
        self.currentClass = None
        # Move all the tokens in the source code in a buffer, token_stream_rewriter.
        if common_token_stream is not None:
            self.token_stream_rewriter = TokenStreamRewriter(
                common_token_stream)
        else:
            raise TypeError('common_token_stream is None')

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

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

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

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

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

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

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

            self.productConstructorParam[self.currentClass] = Parameter

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

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

            self.productConstructorMethod.append(Method)

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

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

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

            newProductMethod = "\n"
            for item in self.productConstructorMethod:
                newProductMethod += item
            self.token_stream_rewriter.insertAfter(
                program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
                index=self.CretorStartIndex,
                text=newProductMethod)
Пример #5
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
                )
Пример #6
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 = ""

    # Exit a parse tree produced by JavaParserLabeled#importDeclaration.
    def exitImportDeclaration(self,
                              ctx: JavaParserLabeled.ImportDeclarationContext):
        if ctx.qualifiedName().getText(
        ) != self.source_package + '.' + self.class_identifier:
            return

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

        text_to_replace = "import " + self.target_package + '.' + self.class_identifier + ';'
        if ctx.STATIC() is not None:
            text_to_replace = text_to_replace.replace("import",
                                                      "import static")

        # replace the import source package with target package
        self.token_stream_rewriter.replace(
            program_name=self.token_stream_rewriter.DEFAULT_PROGRAM_NAME,
            from_idx=start_index,
            to_idx=stop_index,
            text=text_to_replace)

    # 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

                # 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)