From 79c036344d46bbb81f1fba6983a600fc2e7a66c7 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Mon, 23 Oct 2017 08:11:24 +0200 Subject: [PATCH] Generalize `-XepPatchChecks` command line parsing - Support arguments combining built-in and Refaster rules. - Support arguments listing multiple Refaster rules. Fixes #595 --- .../BaseErrorProneJavaCompiler.java | 44 ++++++++------- .../google/errorprone/ErrorProneOptions.java | 54 ++++++++++++------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/check_api/src/main/java/com/google/errorprone/BaseErrorProneJavaCompiler.java b/check_api/src/main/java/com/google/errorprone/BaseErrorProneJavaCompiler.java index 70faabf96a5..477da793343 100644 --- a/check_api/src/main/java/com/google/errorprone/BaseErrorProneJavaCompiler.java +++ b/check_api/src/main/java/com/google/errorprone/BaseErrorProneJavaCompiler.java @@ -18,6 +18,8 @@ import static com.google.common.base.StandardSystemProperty.JAVA_SPECIFICATION_VERSION; +import com.google.common.base.Optional; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.errorprone.RefactoringCollection.RefactoringResult; @@ -220,26 +222,32 @@ static ErrorProneAnalyzer createAnalyzer( } refactoringCollection[0] = RefactoringCollection.refactor(epOptions.patchingOptions(), context); - // Refaster refactorer or using builtin checks - CodeTransformer codeTransformer = - epOptions - .patchingOptions() - .customRefactorer() - .or( - () -> { - ScannerSupplier toUse = - ErrorPronePlugins.loadPlugins(scannerSupplier, context) - .applyOverrides(epOptions); - ImmutableSet namedCheckers = epOptions.patchingOptions().namedCheckers(); - if (!namedCheckers.isEmpty()) { - toUse = toUse.filter(bci -> namedCheckers.contains(bci.canonicalName())); - } - return ErrorProneScannerTransformer.create(toUse.get()); - }) - .get(); + // Use Refaster refactorer if configured + Optional> customRefactorer = + epOptions.patchingOptions().customRefactorer(); + CodeTransformer builtinTransformer = + createBuiltinRefactorer(scannerSupplier, epOptions, context, customRefactorer.isPresent()); + CodeTransformer compoundTransformer = + customRefactorer + .transform(s -> CompositeCodeTransformer.compose(s.get(), builtinTransformer)) + .or(builtinTransformer); return ErrorProneAnalyzer.createWithCustomDescriptionListener( - codeTransformer, epOptions, context, refactoringCollection[0]); + compoundTransformer, epOptions, context, refactoringCollection[0]); + } + + private static CodeTransformer createBuiltinRefactorer( + ScannerSupplier scannerSupplier, + ErrorProneOptions epOptions, + Context context, + boolean forceFilter) { + ScannerSupplier toUse = + ErrorPronePlugins.loadPlugins(scannerSupplier, context).applyOverrides(epOptions); + Set namedCheckers = epOptions.patchingOptions().namedCheckers(); + if (forceFilter || !namedCheckers.isEmpty()) { + toUse = toUse.filter(bci -> namedCheckers.contains(bci.canonicalName())); + } + return ErrorProneScannerTransformer.create(toUse.get()); } static class RefactoringTask implements TaskListener { diff --git a/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java b/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java index ca9d9a5541e..3f1e0c4d0b1 100644 --- a/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java +++ b/check_api/src/main/java/com/google/errorprone/ErrorProneOptions.java @@ -24,12 +24,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.errorprone.apply.ImportOrganizer; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -434,25 +436,7 @@ public static ErrorProneOptions processArgs(Iterable args) { } } else if (arg.startsWith(PATCH_CHECKS_PREFIX)) { String remaining = arg.substring(PATCH_CHECKS_PREFIX.length()); - if (remaining.startsWith("refaster:")) { - // Refaster rule, load from InputStream at file - builder - .patchingOptionsBuilder() - .customRefactorer( - () -> { - String path = remaining.substring("refaster:".length()); - try (InputStream in = - Files.newInputStream(FileSystems.getDefault().getPath(path)); - ObjectInputStream ois = new ObjectInputStream(in)) { - return (CodeTransformer) ois.readObject(); - } catch (IOException | ClassNotFoundException e) { - throw new RuntimeException("Can't load Refaster rule from " + path, e); - } - }); - } else { - Iterable checks = Splitter.on(',').trimResults().split(remaining); - builder.patchingOptionsBuilder().namedCheckers(ImmutableSet.copyOf(checks)); - } + configurePatchChecks(builder, remaining); } else if (arg.startsWith(PATCH_IMPORT_ORDER_PREFIX)) { String remaining = arg.substring(PATCH_IMPORT_ORDER_PREFIX.length()); ImportOrganizer importOrganizer = ImportOrderParser.getImportOrganizer(remaining); @@ -473,6 +457,38 @@ public static ErrorProneOptions processArgs(Iterable args) { return builder.build(remainingArgs.build()); } + private static void configurePatchChecks(Builder builder, String arg) { + List> customCodeTransformers = new ArrayList<>(); + ImmutableSet.Builder namedCheckers = ImmutableSet.builder(); + for (String check : Splitter.on(',').trimResults().split(arg)) { + if (check.startsWith("refaster:")) { + customCodeTransformers.add( + createRefasterCodeTransformerLoader(check.substring("refaster:".length()))); + } else { + namedCheckers.add(check); + } + } + builder.patchingOptionsBuilder().namedCheckers(namedCheckers.build()); + if (!customCodeTransformers.isEmpty()) + builder + .patchingOptionsBuilder() + .customRefactorer( + () -> + CompositeCodeTransformer.compose( + Iterables.transform(customCodeTransformers, Supplier::get))); + } + + private static Supplier createRefasterCodeTransformerLoader(String path) { + return () -> { + try (InputStream in = Files.newInputStream(FileSystems.getDefault().getPath(path)); + ObjectInputStream ois = new ObjectInputStream(in)) { + return (CodeTransformer) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException("Can't load Refaster rule from " + path, e); + } + }; + } + /** * Given a list of command-line arguments, produce the corresponding {@link ErrorProneOptions} * instance.