Skip to content

Commit

Permalink
Enable AutoService verifications by default.
Browse files Browse the repository at this point in the history
Previously AutoService only verified that the annotated class actually implemented the service interface _if_ you compiled with `-Averify=true`. There doesn't seem to have been a good reason for that, so now AutoService verifies _unless_ you specify `-Averify=false`.

As an example, this will no longer compile:
```java
@autoservice(SomeService.class)
public class SomeServiceImpl {} // does not implement SomeService
```

Also add the ability to use `@SuppressWarnings("AutoService")` to disable this and other future verifications.

RELNOTES=AutoService now verifies by default that the annotated class does indeed implement the interface in `@AutoServce`. Previously this only happened when compiling with `-Averify=true`. The verification can be disabled either by compiling with `-Averify=false` or by adding `@SuppressWarnings("AutoService")` to the annotated class.
PiperOrigin-RevId: 531009313
  • Loading branch information
eamonnmcmanus authored and Google Java Core Libraries committed May 10, 2023
1 parent 6d508b7 commit 965e893
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ private boolean checkImplementer(
TypeElement providerType,
AnnotationMirror annotationMirror) {

String verify = processingEnv.getOptions().get("verify");
if (verify == null || !Boolean.parseBoolean(verify)) {
if (!Boolean.parseBoolean(processingEnv.getOptions().getOrDefault("verify", "true"))
|| suppresses(providerImplementer, "AutoService")) {
return true;
}

Expand All @@ -246,7 +246,7 @@ private boolean checkImplementer(
// So we allow that with a warning, which can be suppressed with @SuppressWarnings("rawtypes").
// See https://github.com/google/auto/issues/870.
if (types.isSubtype(providerImplementer.asType(), types.erasure(providerType.asType()))) {
if (!rawTypesSuppressed(providerImplementer)) {
if (!suppresses(providerImplementer, "rawtypes")) {
warning(
"Service provider "
+ providerType
Expand All @@ -261,10 +261,10 @@ private boolean checkImplementer(
return false;
}

private static boolean rawTypesSuppressed(Element element) {
private static boolean suppresses(Element element, String warning) {
for (; element != null; element = element.getEnclosingElement()) {
SuppressWarnings suppress = element.getAnnotation(SuppressWarnings.class);
if (suppress != null && Arrays.asList(suppress.value()).contains("rawtypes")) {
if (suppress != null && Arrays.asList(suppress.value()).contains(warning)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
package com.google.auto.service.processor;

import static com.google.auto.service.processor.AutoServiceProcessor.MISSING_SERVICES_ERROR;
import static com.google.testing.compile.CompilationSubject.assertThat;
import static com.google.common.truth.Truth.assertThat;
import static com.google.testing.compile.CompilationSubject.assertThat;

import com.google.common.io.Resources;
import com.google.testing.compile.Compilation;
Expand Down Expand Up @@ -87,11 +87,55 @@ public void badMultiService() {
assertThat(compilation).hadErrorContaining(MISSING_SERVICES_ERROR);
}

@Test
public void doesNotImplement_failsByDefault() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
.compile(
JavaFileObjects.forResource("test/DoesNotImplement.java"));
assertThat(compilation).failed();
assertThat(compilation)
.hadErrorContaining("test.DoesNotImplement does not implement test.SomeService");
}

@Test
public void doesNotImplement_succeedsWithVerifyFalse() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
.withOptions("-Averify=false")
.compile(
JavaFileObjects.forResource("test/DoesNotImplement.java"),
JavaFileObjects.forResource("test/SomeService.java"));
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedFile(StandardLocation.CLASS_OUTPUT, "META-INF/services/test.SomeService")
.contentsAsUtf8String()
.isEqualTo("test.DoesNotImplement\n");
}

@Test
public void doesNotImplement_suppressed() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
.compile(
JavaFileObjects.forResource("test/DoesNotImplementSuppressed.java"),
JavaFileObjects.forResource("test/SomeService.java"));
assertThat(compilation).succeededWithoutWarnings();
assertThat(compilation)
.generatedFile(StandardLocation.CLASS_OUTPUT, "META-INF/services/test.SomeService")
.contentsAsUtf8String()
.isEqualTo("test.DoesNotImplementSuppressed\n");
}

@Test
public void generic() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
.withOptions("-Averify=false")
.compile(
JavaFileObjects.forResource("test/GenericService.java"),
JavaFileObjects.forResource("test/GenericServiceProvider.java"));
Expand All @@ -103,7 +147,22 @@ public void generic() {
}

@Test
public void genericWithVerifyOption() {
public void genericWithNoVerifyOption() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
.compile(
JavaFileObjects.forResource("test/GenericService.java"),
JavaFileObjects.forResource("test/GenericServiceProvider.java"));
assertThat(compilation).succeeded();
assertThat(compilation)
.hadWarningContaining(
"Service provider test.GenericService is generic, so it can't be named exactly by"
+ " @AutoService. If this is OK, add @SuppressWarnings(\"rawtypes\").");
}

@Test
public void genericWithExplicitVerify() {
Compilation compilation =
Compiler.javac()
.withProcessors(new AutoServiceProcessor())
Expand Down
22 changes: 22 additions & 0 deletions service/processor/src/test/resources/test/DoesNotImplement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package test;

import com.google.auto.service.AutoService;

@AutoService(SomeService.class)
public class DoesNotImplement {}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package test;

import com.google.auto.service.AutoService;

@AutoService(SomeService.class)
@SuppressWarnings("AutoService")
public class DoesNotImplementSuppressed {}

0 comments on commit 965e893

Please sign in to comment.