/** * Applies the provided set of suggested fixes to the provided code and returns the new code. * The {@code filenameToCodeMap} must contain all the files that the provided fixes apply to. * The fixes can be provided in any order, but they may not have any overlapping modifications * for the same file. * This function will return new code only for the files that have been modified. */ public static Map<String, String> applySuggestedFixesToCode( Iterable<SuggestedFix> fixes, Map<String, String> filenameToCodeMap) { ImmutableSetMultimap.Builder<String, CodeReplacement> builder = ImmutableSetMultimap.builder(); for (SuggestedFix fix : fixes) { builder.putAll(fix.getReplacements()); } SetMultimap<String, CodeReplacement> replacementsMap = builder.build(); ImmutableMap.Builder<String, String> newCodeMap = ImmutableMap.builder(); for (Map.Entry<String, Set<CodeReplacement>> entry : Multimaps.asMap(replacementsMap).entrySet()) { String filename = entry.getKey(); if (!filenameToCodeMap.containsKey(filename)) { throw new IllegalArgumentException("filenameToCodeMap missing code for file: " + filename); } Set<CodeReplacement> replacements = entry.getValue(); String newCode = applyCodeReplacements(replacements, filenameToCodeMap.get(filename)); newCodeMap.put(filename, newCode); } return newCodeMap.build(); }
/** * Applies the provided set of suggested fixes to the files listed in the suggested fixes. * The fixes can be provided in any order, but they may not have any overlapping modifications * for the same file. */ public static void applySuggestedFixesToFiles(Iterable<SuggestedFix> fixes) throws IOException { Set<String> filenames = new HashSet<String>(); for (SuggestedFix fix : fixes) { filenames.addAll(fix.getReplacements().keySet()); } Map<String, String> filenameToCodeMap = new HashMap<String, String>(); for (String filename : filenames) { filenameToCodeMap.put(filename, Files.toString(new File(filename), UTF_8)); } Map<String, String> newCode = applySuggestedFixesToCode(fixes, filenameToCodeMap); for (Map.Entry<String, String> entry : newCode.entrySet()) { Files.write(entry.getValue(), new File(entry.getKey()), UTF_8); } }
/** * Applies the provided set of code replacements to the code and returns the transformed code. * The code replacements may not have any overlap. */ public static String applyCodeReplacements(Iterable<CodeReplacement> replacements, String code) { List<CodeReplacement> sortedReplacements = ORDER_CODE_REPLACEMENTS.sortedCopy(replacements); validateNoOverlaps(sortedReplacements); StringBuilder sb = new StringBuilder(); int lastIndex = 0; for (CodeReplacement replacement : sortedReplacements) { sb.append(code, lastIndex, replacement.getStartPosition()); sb.append(replacement.getNewContent()); lastIndex = replacement.getStartPosition() + replacement.getLength(); } if (lastIndex <= code.length()) { sb.append(code, lastIndex, code.length()); } return sb.toString(); }
/** @return Whether any fixes were applied. */ private static boolean fix(String filename, ImmutableSet<DiagnosticType> unfixableErrors) throws IOException { Compiler compiler = new Compiler(System.out); FixingErrorManager errorManager = new FixingErrorManager(unfixableErrors); compiler.setErrorManager(errorManager); errorManager.setCompiler(compiler); lint(Paths.get(filename), compiler); Collection<SuggestedFix> fixes = errorManager.getSureFixes(); if (!fixes.isEmpty()) { ApplySuggestedFixes.applySuggestedFixesToFiles(fixes); return true; } return false; } }
ApplySuggestedFixes.applySuggestedFixesToFiles(fixes);
ApplySuggestedFixes.applySuggestedFixesToFiles(fixes);