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())
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
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)
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)
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 )
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)
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
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)
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())
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!")
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...')
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())
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)
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
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
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)
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
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))
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