Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE on missing service class #1189

Closed
astubbs opened this issue Nov 1, 2021 · 2 comments · Fixed by #1191
Closed

NPE on missing service class #1189

astubbs opened this issue Nov 1, 2021 · 2 comments · Fixed by #1191
Assignees

Comments

@astubbs
Copy link

astubbs commented Nov 1, 2021

I think this is happening to me after changing moving my implementations around

java: FATAL ERROR: java.lang.NullPointerException: Cannot invoke 
"com.google.common.collect.ImmutableSet.stream()" 
because the return value of 
"javax.lang.model.element.AnnotationValue.accept(javax.lang.model.element.AnnotationValueVisitor, Object)"
 is null
  	at com.google.auto.service.processor.AutoServiceProcessor$1.lambda$visitArray$0(AutoServiceProcessor.java:306)
  	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:273)
  	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
  	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
  	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
  	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
  	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
  	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
  	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
  	at com.google.auto.service.processor.AutoServiceProcessor$1.visitArray(AutoServiceProcessor.java:307)
  	at com.google.auto.service.processor.AutoServiceProcessor$1.visitArray(AutoServiceProcessor.java:294)
  	at jdk.compiler/com.sun.tools.javac.code.Attribute$Array.accept(Attribute.java:349)
  	at com.google.auto.service.processor.AutoServiceProcessor.getValueFieldOfClasses(AutoServiceProcessor.java:293)
  	at com.google.auto.service.processor.AutoServiceProcessor.processAnnotations(AutoServiceProcessor.java:137)
  	at com.google.auto.service.processor.AutoServiceProcessor.processImpl(AutoServiceProcessor.java:121)
  	at com.google.auto.service.processor.AutoServiceProcessor.process(AutoServiceProcessor.java:109)
  	at org.jetbrains.jps.javac.APIWrappers$ProcessorWrapper.process(APIWrappers.java:152)
  	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
  	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  	at java.base/java.lang.reflect.Method.invoke(Method.java:567)

Haven't quite been able to narrow it down exactly yet though.. Reproduced in this PR - see failing tests.

version: 1.0

@astubbs
Copy link
Author

astubbs commented Nov 1, 2021

I think it's something to do with the class originally being present, the service meta-inf file getting generated, the service class source file later being removed from the module, and it being compiled again without being cleaned first.

@astubbs astubbs changed the title NPE on missing class NPE on missing service class Nov 2, 2021
@eamonnmcmanus eamonnmcmanus self-assigned this Nov 2, 2021
@eamonnmcmanus
Copy link
Member

Looks like a simple one-line fix. If an @AutoService annotation references a missing class, the value on this line...

                    .flatMap(value -> value.accept(this, null).stream())

is the string "<error>", due to quirky javac behaviour. The visitor is expecting an array of class literals, or, in its recursive call, a single class literal, but not a string. Since the visitor has no override for visitString, a null default value is returned. We can simply provide an empty ImmutableSet as the default value to fix the problem. There is no need to handle this error case specially, since the compiler will be outputting its own errors about the missing class anyway.

copybara-service bot pushed a commit that referenced this issue Nov 2, 2021
Fixes #1189.
Closes https://github.com/google/auto/pull/1190/files.
Many thanks to @astubbs for the bug report and repro.

If an `@AutoService` annotation references a missing class, the `value` on [this line](https://github.com/google/auto/blob/15c76191f79a2a26a9f914541a5c9ac4965dd0c7/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java#L306)...
```java
                    .flatMap(value -> value.accept(this, null).stream())
```
is the string `"<error>"`, due to quirky javac behaviour. Currently, the visitor expects an array of class literals, or, in its recursive call, a single class literal, but not a string. Since the visitor has no override for [`visitString`](https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/element/AnnotationValueVisitor.html#visitString(java.lang.String,P)), a null default value is returned. We can simply provide an empty `ImmutableSet` as the default value to fix the problem. There is no need to handle this error case specially, since the compiler will be outputting its own errors about the missing class anyway.

RELNOTES=AutoService no longer throws an exception for a missing service class.
PiperOrigin-RevId: 407146682
copybara-service bot pushed a commit that referenced this issue Nov 3, 2021
Fixes #1189.
Closes https://github.com/google/auto/pull/1190/files.
Many thanks to @astubbs for the bug report and repro, which was the basis for the new test here.

If an `@AutoService` annotation references a missing class, the `value` on [this line](https://github.com/google/auto/blob/15c76191f79a2a26a9f914541a5c9ac4965dd0c7/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java#L306)...
```java
                    .flatMap(value -> value.accept(this, null).stream())
```
is the string `"<error>"`, due to quirky javac behaviour. Currently, the visitor expects an array of class literals, or, in its recursive call, a single class literal, but not a string. Since the visitor has no override for [`visitString`](https://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/lang/model/element/AnnotationValueVisitor.html#visitString(java.lang.String,P)), a null default value is returned. We can simply provide an empty `ImmutableSet` as the default value to fix the problem. There is no need to handle this error case specially, since the compiler will be outputting its own errors about the missing class anyway.

RELNOTES=AutoService no longer throws an exception for a missing service class.
PiperOrigin-RevId: 407146682
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants