diff options
Diffstat (limited to 'service/processor/src/main/java/com')
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(); } } |