package de.refactoringbot.refactoring.supportedrefactorings; import java.io.File; import java.io.FileInputStream; import java.io.PrintWriter; import java.util.EnumSet; import org.springframework.stereotype.Component; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.Modifier.Keyword; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter; import de.refactoringbot.model.botissue.BotIssue; import de.refactoringbot.model.configuration.GitConfiguration; import de.refactoringbot.model.exceptions.BotRefactoringException; import de.refactoringbot.refactoring.RefactoringHelper; import de.refactoringbot.refactoring.RefactoringImpl; /** * This class is used to bring method and field modifiers into the correct * order, following the Java Language Specification (JLS) */ @Component public class ReorderModifier implements RefactoringImpl { /** * Reorder modifiers of a given field or method to comply with the JLS */ @Override public String performRefactoring(BotIssue issue, GitConfiguration gitConfig) throws Exception { String filepath = gitConfig.getRepoFolder() + File.separator + issue.getFilePath(); FileInputStream in = new FileInputStream(filepath); CompilationUnit compilationUnit = LexicalPreservingPrinter.setup(StaticJavaParser.parse(in)); FieldDeclaration field = RefactoringHelper.getFieldDeclarationByLineNumber(issue.getLine(), compilationUnit); MethodDeclaration method = RefactoringHelper.getMethodDeclarationByLineNumber(issue.getLine(), compilationUnit); boolean isModifierListUnchanged = false; NodeList<Modifier> modifiersInCorrectOrder; if (field != null) { modifiersInCorrectOrder = getModifiersInCorrectOrder(field.getModifiers()); isModifierListUnchanged = field.getModifiers().equals(modifiersInCorrectOrder); field.setModifiers(new NodeList<Modifier>()); field.setModifiers(modifiersInCorrectOrder); } else if (method != null) { modifiersInCorrectOrder = getModifiersInCorrectOrder(method.getModifiers()); isModifierListUnchanged = method.getModifiers().equals(modifiersInCorrectOrder); method.setModifiers(new NodeList<Modifier>()); method.setModifiers(modifiersInCorrectOrder); } else { throw new BotRefactoringException("Could not find method or field declaration at the given line!"); } if (isModifierListUnchanged) { throw new BotRefactoringException("All modifiers are in correct order! Nothing to refactor."); } // Save changes to file PrintWriter out = new PrintWriter(filepath); out.println(LexicalPreservingPrinter.print(compilationUnit)); out.close(); // Return commit message return "Reordered modifiers to comply with the Java Language Specification"; } private NodeList<Modifier> getModifiersInCorrectOrder(NodeList<Modifier> modifiers) { NodeList<Modifier> reorderedModifiers = new NodeList<>(); if (modifiers.size() <= 1) { return modifiers; } // Fill enum set with java modifier keywords, assuming that they are in the // correct order EnumSet<Keyword> keywords = EnumSet.noneOf(Keyword.class); for (Modifier modifier : modifiers) { keywords.add(modifier.getKeyword()); } // Reorder modifiers for (Keyword keyword : keywords) { for (Modifier modifier : modifiers) { if (keyword.equals(modifier.getKeyword())) { reorderedModifiers.add(modifier); } } } return reorderedModifiers; } }