aboutsummaryrefslogtreecommitdiff
path: root/service/processor/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'service/processor/src/main/java/com')
-rw-r--r--service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java43
-rw-r--r--service/processor/src/main/java/com/google/auto/service/processor/ServicesFiles.java14
2 files changed, 37 insertions, 20 deletions
diff --git a/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java b/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java
index 85a24cb4..26c1435d 100644
--- a/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java
+++ b/service/processor/src/main/java/com/google/auto/service/processor/AutoServiceProcessor.java
@@ -46,6 +46,7 @@ import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
@@ -228,25 +229,30 @@ public class AutoServiceProcessor extends AbstractProcessor {
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;
}
- // TODO: We're currently only enforcing the subtype relationship
- // constraint. It would be nice to enforce them all.
+ // We check that providerImplementer does indeed inherit from providerType, and that it is not
+ // abstract (an abstract class or interface). For ServiceLoader, we could also check that it has
+ // a public no-arg constructor. But it turns out that people also use AutoService in contexts
+ // where the META-INF/services entries are read by things other than ServiceLoader. Those things
+ // still require the class to exist and inherit from providerType, but they don't necessarily
+ // require a public no-arg constructor.
+ // More background: https://github.com/google/auto/issues/1505.
Types types = processingEnv.getTypeUtils();
if (types.isSubtype(providerImplementer.asType(), providerType.asType())) {
- return true;
+ return checkNotAbstract(providerImplementer, annotationMirror);
}
// Maybe the provider has generic type, but the argument to @AutoService can't be generic.
// 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
@@ -255,16 +261,35 @@ public class AutoServiceProcessor extends AbstractProcessor {
providerImplementer,
annotationMirror);
}
- return true;
+ return checkNotAbstract(providerImplementer, annotationMirror);
}
+ String message =
+ "ServiceProviders must implement their service provider interface. "
+ + providerImplementer.getQualifiedName()
+ + " does not implement "
+ + providerType.getQualifiedName();
+ error(message, providerImplementer, annotationMirror);
+
return false;
}
- private static boolean rawTypesSuppressed(Element element) {
+ private boolean checkNotAbstract(
+ TypeElement providerImplementer, AnnotationMirror annotationMirror) {
+ if (providerImplementer.getModifiers().contains(Modifier.ABSTRACT)) {
+ error(
+ "@AutoService cannot be applied to an abstract class or an interface",
+ providerImplementer,
+ annotationMirror);
+ return false;
+ }
+ return true;
+ }
+
+ 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;
}
}
diff --git a/service/processor/src/main/java/com/google/auto/service/processor/ServicesFiles.java b/service/processor/src/main/java/com/google/auto/service/processor/ServicesFiles.java
index 75d6cca7..b08431e8 100644
--- a/service/processor/src/main/java/com/google/auto/service/processor/ServicesFiles.java
+++ b/service/processor/src/main/java/com/google/auto/service/processor/ServicesFiles.java
@@ -15,9 +15,8 @@
*/
package com.google.auto.service.processor;
-import static com.google.common.base.Charsets.UTF_8;
+import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.common.io.Closer;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
@@ -57,12 +56,9 @@ final class ServicesFiles {
*/
static Set<String> readServiceFile(InputStream input) throws IOException {
HashSet<String> serviceClasses = new HashSet<String>();
- Closer closer = Closer.create();
- try {
- // TODO(gak): use CharStreams
- BufferedReader r = closer.register(new BufferedReader(new InputStreamReader(input, UTF_8)));
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, UTF_8))) {
String line;
- while ((line = r.readLine()) != null) {
+ while ((line = reader.readLine()) != null) {
int commentStart = line.indexOf('#');
if (commentStart >= 0) {
line = line.substring(0, commentStart);
@@ -73,10 +69,6 @@ final class ServicesFiles {
}
}
return serviceClasses;
- } catch (Throwable t) {
- throw closer.rethrow(t);
- } finally {
- closer.close();
}
}