Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8181202

Java Compiler StandardLocation addition feature request

    Details

      Description

      A DESCRIPTION OF THE REQUEST :
      In order to implement incremental build support for the Java Compiler with using annotation processing, one would require a location, where arbitrary data can be stored between compilations. To solve this, a new StandardLocation enumeration value can be introduced, which represents a location where annotation processors can store data.

      JUSTIFICATION :
      Some annotation processors generate, and derive data from multiple source files. When compiling the sources in an incremental way, not all of the information may be available to the processor. To solve this, processors can store previously derived data in a standardized location, and use that and the modified sources to derive the up to date information.
      The location should be standardized in order to have multiple compiler support over time.
      The example provides an use-case, where the annotation provides records the top level classes during compilation, and derives them in a comma separated format. As this is a minimal example, there are more use-cases to this enhancement.
      During the file generation, the originating elements could be supplied, however when deriving information in a big project/from lots of sources, compiling them again could increase the build times significantly.
      The value addition does not break any compatibility, as it has no effect on the JavaFileManagers which does not support a new location.
      The annotation processors should continue working without this location, but that can require full build every time.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The introduced value in javax.tools.StandardLocation can be named as 'INCREMENTAL_OUTPUT' and isOutputLocation() should return true.
      ACTUAL -
      No standardized value is specified.

      ---------- BEGIN SOURCE ----------
      package bence.sipka.compiler.java;

      import java.io.IOException;
      import java.io.OutputStream;
      import java.util.Arrays;
      import java.util.Collection;
      import java.util.Collections;
      import java.util.HashSet;
      import java.util.Iterator;
      import java.util.Set;

      import javax.annotation.processing.Completion;
      import javax.annotation.processing.Filer;
      import javax.annotation.processing.ProcessingEnvironment;
      import javax.annotation.processing.Processor;
      import javax.annotation.processing.RoundEnvironment;
      import javax.lang.model.SourceVersion;
      import javax.lang.model.element.AnnotationMirror;
      import javax.lang.model.element.Element;
      import javax.lang.model.element.ExecutableElement;
      import javax.lang.model.element.TypeElement;
      import javax.tools.FileObject;
      import javax.tools.StandardLocation;

      public class TestProcessor implements Processor {

      @Override
      public Set<String> getSupportedOptions() {
      return Collections.emptySet();
      }

      @Override
      public Set<String> getSupportedAnnotationTypes() {
      HashSet<String> result = new HashSet<>();
      result.add("*");
      return result;
      }

      @Override
      public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latest();
      }

      private Filer filer;
      private ProcessingEnvironment processingEnv;
      private Collection<String> classes = new HashSet<>();

      @Override
      public void init(ProcessingEnvironment processingEnv) {
      this.processingEnv = processingEnv;
      this.filer = processingEnv.getFiler();

      try {
      FileObject res = filer.getResource(StandardLocation.INCREMENTAL_OUTPUT, "test.pkg", "file");
      classes.addAll(Arrays.asList(res.getCharContent(true).toString().split(",")));
      for (Iterator<String> it = classes.iterator(); it.hasNext();) {
      String clazz = it.next();
      TypeElement type = processingEnv.getElementUtils().getTypeElement(clazz);
      if (type == null) {
      // class no longer exists, remove
      it.remove();
      }
      }
      } catch (IOException e) {
      e.printStackTrace();
      }
      }

      @Override
      public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      for (Element rootelem : roundEnv.getRootElements()) {
      if (rootelem instanceof TypeElement) {
      classes.add(processingEnv.getElementUtils().getBinaryName((TypeElement) rootelem).toString());
      }
      }
      if (roundEnv.processingOver()) {
      try {
      FileObject res = filer.createResource(StandardLocation.INCREMENTAL_OUTPUT, "test.pkg", "file");
      try (OutputStream os = res.openOutputStream()) {
      os.write(String.join(",", classes).getBytes());
      }
      } catch (IOException e) {
      e.printStackTrace();
      }
      }
      return false;
      }

      @Override
      public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
      return Collections.emptyList();
      }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Using StandardLocation.locationFor(String) method can bypass this issue, however a single value addition can encourage widespread support.

        Attachments

          Activity

            People

            • Assignee:
              darcy Joe Darcy
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated: