google-java-format-gradle-plugin icon indicating copy to clipboard operation
google-java-format-gradle-plugin copied to clipboard

Provide a mechanism to specify a custom google-java-format JAR

Open alexkleiman opened this issue 6 years ago • 2 comments

It would be nice if it was possible to specify a customer google-java-format JAR to use. This would allow this plugin to used to run forked versions of google-java-format.

The gradle errorprone plugin accomplishes this by using the errorprone JAR in the errorprone configuration, if such a JAR exists, as explained in the documentation:

The plugin adds an errorprone configuration that automatically uses the latest release of error-prone. You can override it to use a specific version with:

dependencies {
  errorprone 'com.google.errorprone:error_prone_core:2.0.21'
}

They then retrieve this JAR from the configuration, create a new classloader, and use reflection to instantiate the class which runs errorprone:

  private final Configuration errorprone;

  public ErrorProneCompiler(Configuration errorprone) {
    this.errorprone = errorprone;
  }

  @Override
  public WorkResult execute(JavaCompileSpec spec) {
    LOGGER.info("Compiling with error-prone compiler");

    List<String> args = new JavaCompilerArgumentsBuilder(spec).includeSourceFiles(true).build();

    URL[] urls =
        errorprone
            .getFiles()
            .stream()
            .map(
                file -> {
                  try {
                    return file.toURI().toURL();
                  } catch (MalformedURLException e) {
                    throw UncheckedException.throwAsUncheckedException(e);
                  }
                })
            .toArray(URL[]::new);

    ClassLoader tccl = Thread.currentThread().getContextClassLoader();
    int exitCode;
    try (URLClassLoader cl = new SelfFirstClassLoader(urls)) {
      Thread.currentThread().setContextClassLoader(cl);

      Class<?> builderClass = cl.loadClass("com.google.errorprone.ErrorProneCompiler$Builder");
      Object compilerBuilder = builderClass.getConstructor().newInstance();
      Object compiler = builderClass.getMethod("build").invoke(compilerBuilder);
      Object result =
          compiler
              .getClass()
              .getMethod("compile", String[].class)
              .invoke(compiler, (Object) args.toArray(new String[args.size()]));
      exitCode = result.getClass().getField("exitCode").getInt(result);
    }

alexkleiman avatar May 17 '18 20:05 alexkleiman

I understand that some people don't have another choice than forking and adjusting google-java-format to their needs. I can't really 'support' forks of google-java-format though, as I don't have access to them and therefore cannot test against them. I'd prefer to not have to face all the potential problems this feature might bring and instead only support the 'real' google-java-format.

sherter avatar Jun 10 '18 13:06 sherter

@sherter thank you for your response! I understand your concerns here, and think it would be reasonable for you to close this feature request if you do not plan on implementing it.

With regard to testing: I think it would be possible to test this by using a "custom" google-java-format JAR which is really just an old version of google-java-format.

That being said, it is of course not possible to test against all possible forks of google-java-format. If this means that you are not comfortable implementing this feature, I understand.

alexkleiman avatar Jun 10 '18 23:06 alexkleiman