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

Annotation processor option deemed unrecognized when processor not engaged

    Details

    • Subcomponent:
    • CPU:
      x86_64
    • OS:
      linux_ubuntu

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_102"
      Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Linux t520 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      If an annotation processor is correctly provided to javac, and a correctly spelled option that it recognizes is also provided, but the processor is never asked to process a round (e.g., because no annotation it processes is used), a warning is issued deeming the option unrecognized. For example:

        warning: The following options were not recognized by any processor: '[proc]'

      This warning is inaccurate, as the compiler has been told that the option is recognized (through getSupportedOptions), and simply isn't acting on that information until a round is submitted to the processor.

      The example source code defines an annotation @Example, a processor Proc, and two almost identical test classes, Test1 and Test2. Test2 is annotated with @Example; Test1 is not. Neither use any other classes, so they can be regarded as two independently compilable source trees, one in which the annotation is not used at all, and one in which the annotation is applied at least once. The problem manifests in the former, i.e., when no file in the source tree uses the annotation recognized by the processor.

      The steps to reproduce the problem include one step to compile the processor and its annotation. The last two steps respectively compile Test1 and Test2 with identical annotation-processing options.

      The intent of the warning is not certain, but the most obvious possibilities don't make sense:

      (1) To detect when an option is provided, but no processor is correctly provided to make use of it.
      (2) To detect when an option is mispelled with respect to a correctly provided processor.
      (3) To detect when a processor is not 'fully engaged' (i.e., its process() method is never invoked).

      (1) and (2) do not apply in the provided example, as the processor configuration is the same in each command (so it can't be correct in one and incorrect in the other), and only the source trees differ. In both Test1 and Test2, the processor is correctly provided (and stderr shows it is invoked and asked which options it recognizes in both cases), and the option is correctly spelled (again, stderr showing that the option value was correctly received). The utility of (3) is questionable (so there should be a specific option to switch it off), and the warning it provides is indirect (by referring to an option rather than the processor) and inaccurate (the option *is* recognized).

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      mkdir -p proc classes
      javac -d proc Proc.java
      javac -d classes \
        -processorpath proc \
        -processor Proc \
        -Aproc=foo \
        Test1.java
      javac -d classes \
        -processorpath proc \
        -processor Proc \
        -Aproc=foo \
        Test2.java


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      $ mkdir -p proc classes
      $ javac -d proc Proc.java
      $ javac -d classes \
      > -processorpath proc \
      > -processor Proc \
      > -Aproc=foo \
      > Test1.java
      Initializing, with option foo
      Returning options
      $ javac -d classes \
      > -processorpath proc \
      > -processor Proc \
      > -Aproc=foo \
      > Test2.java
      Initializing, with option foo
      Returning options
      Round
      Round
      warning: Implicitly compiled files were not subject to annotation processing.
        Use -implicit to specify a policy for implicit compilation.
      1 warning

      ACTUAL -
      $ mkdir -p proc classes
      $ javac -d proc Proc.java
      $ javac -d classes \
      > -processorpath proc \
      > -processor Proc \
      > -Aproc=foo \
      > Test1.java
      Initializing, with option foo
      Returning options
      warning: The following options were not recognized by any processor: '[proc]'
      $ javac -d classes \
      > -processorpath proc \
      > -processor Proc \
      > -Aproc=foo \
      > Test2.java
      Initializing, with option foo
      Returning options
      Round
      Round
      warning: Implicitly compiled files were not subject to annotation processing.
        Use -implicit to specify a policy for implicit compilation.
      1 warning


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      cat > Example.java << EOF
      /* Example.java */
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;

      @Target(ElementType.TYPE)
      @Retention(RetentionPolicy.SOURCE)
      public @interface Example { }
      EOF

      cat > Proc.java << EOF
      /* Proc.java */
      import java.util.Collections;
      import java.util.Set;

      import javax.annotation.processing.AbstractProcessor;
      import javax.annotation.processing.ProcessingEnvironment;
      import javax.annotation.processing.RoundEnvironment;
      import javax.lang.model.SourceVersion;
      import javax.lang.model.element.TypeElement;

      public class Proc extends AbstractProcessor {
          private static final String OPTION_NAME = "proc";

          private ProcessingEnvironment env;

          @Override
          public Set<String> getSupportedOptions() {
              System.err.println("Returning options");
              return Collections.singleton(OPTION_NAME);
          }

          @Override
          public Set<String> getSupportedAnnotationTypes() {
              return Collections.singleton(Example.class.getName());
          }

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

          @Override
          public void init(ProcessingEnvironment processingEnv) {
              env = processingEnv;
              System.err.printf("Initializing, with option %s%n",
                                env.getOptions().get(OPTION_NAME));
          }

          @Override
          public boolean process(Set<? extends TypeElement> annotations,
                                 RoundEnvironment roundEnv) {
              System.err.println("Round");
              return false;
          }
      }
      EOF

      cat > Test1.java << EOF
      /* Test1.java */
      public class Test1 { }
      EOF

      cat > Test2.java << EOF
      /* Test2.java */
      @Example
      public class Test2 { }
      EOF

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

      CUSTOMER SUBMITTED WORKAROUND :
      Ignore the warning.

      I've marked the severity as 'No Impact', although ignoring the warning has a small impact in that it is noise that could drown out an occasional legitimate message.

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated: