/** Returns a {@link DeclaredType} for {@code AndroidInjector.Factory<implementationType>}. */ private DeclaredType injectorFactoryOf(TypeMirror implementationType) { return types.getDeclaredType(factoryElement(), implementationType); }
/** Report an error if the method's return type is not {@code AndroidInjector.Factory<?>}. */ private void validateReturnType(ExecutableElement method) { TypeMirror returnType = method.getReturnType(); DeclaredType requiredReturnType = injectorFactoryOf(types.getWildcardType(null, null)); if (!types.isSameType(returnType, requiredReturnType)) { messager.printMessage( Kind.ERROR, String.format( "%s should bind %s, not %s. See https://google.github.io/dagger/android", method, requiredReturnType, returnType), method); } }
@Override public Set<Element> process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) { ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder(); elementsByAnnotation .entries() .forEach( entry -> { try { validateMethod(entry.getKey(), MoreElements.asExecutable(entry.getValue())); } catch (TypeNotPresentException e) { deferredElements.add(entry.getValue()); } }); return deferredElements.build(); }
if (!types.isAssignable(types.erasure(returnType), factoryElement().asType())) { DeclaredType intendedReturnType = injectorFactoryOf(types.getWildcardType(frameworkType, null)); if (!MoreTypes.equivalence().equivalent(returnType, intendedReturnType)) { messager.printMessage( validateMapKeyMatchesBindsParameter(annotation, method);
if (!types.isAssignable(types.erasure(returnType), factoryElement().asType())) { validateReturnType(method); validateMapKeyMatchesBindsParameter(annotation, method);
@Override protected Iterable<? extends ProcessingStep> initSteps() { Filer filer = new FormattingFiler(processingEnv.getFiler()); Messager messager = processingEnv.getMessager(); Elements elements = processingEnv.getElementUtils(); Types types = processingEnv.getTypeUtils(); AndroidInjectKeyFinder keyFinder = new AndroidInjectKeyFinder(elements, messager); return ImmutableList.of( keyFinder, new AndroidMapKeyValidator(elements, types, messager), new ContributesAndroidInjectorGenerator( filer, new AndroidInjectorDescriptor.Validator(types, messager, keyFinder))); }
@Override protected Iterable<? extends ProcessingStep> initSteps() { Filer filer = new FormattingFiler(processingEnv.getFiler()); Messager messager = processingEnv.getMessager(); Elements elements = processingEnv.getElementUtils(); Types types = processingEnv.getTypeUtils(); return ImmutableList.of( new AndroidMapKeyValidator(elements, types, messager), new ContributesAndroidInjectorGenerator( new AndroidInjectorDescriptor.Validator(types, elements, messager), useStringKeys(), filer, elements, processingEnv.getSourceVersion())); }
private void validateMapKeyMatchesBindsParameter( Class<? extends Annotation> annotation, ExecutableElement method) { TypeMirror parameterType = getOnlyElement(method.getParameters()).asType(); AnnotationMirror annotationMirror = getAnnotationMirror(method, annotation).get(); TypeMirror mapKeyValue = (TypeMirror) getAnnotationValue(annotationMirror, "value").getValue(); if (!types.isAssignable(parameterType, injectorFactoryOf(mapKeyValue))) { messager.printMessage( Kind.ERROR, String.format("%s does not implement AndroidInjector<%s>", parameterType, mapKeyValue), method, annotationMirror); } }
@Override public Set<Element> process( SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) { elementsByAnnotation.forEach( (annotation, element) -> validateMethod(annotation, MoreElements.asExecutable(element))); return ImmutableSet.of(); }
/** Returns a {@link DeclaredType} for {@code AndroidInjector.Factory<implementationType>}. */ private DeclaredType injectorFactoryOf(TypeMirror implementationType) { return types.getDeclaredType(factoryElement(), implementationType); }
/** * A valid @Binds method could bind an {@link AndroidInjector.Factory} for one type, while giving * it a map key of a different type. The return type and parameter type would pass typical @Binds * validation, but the map lookup in {@link dagger.android.DispatchingAndroidInjector} would * retrieve the wrong injector factory. * * <pre>{@code * {@literal @Binds} * {@literal @IntoMap} * {@literal @ClassKey(GreenActivity.class)} * abstract AndroidInjector.Factory<?> bindBlueActivity( * BlueActivityComponent.Builder builder); * }</pre> */ private void validateMapKeyMatchesBindsParameter( Class<? extends Annotation> annotation, ExecutableElement method) { TypeMirror parameterType = getOnlyElement(method.getParameters()).asType(); AnnotationMirror annotationMirror = getAnnotationMirror(method, annotation).get(); TypeMirror mapKeyType = elements.getTypeElement(injectedTypeFromMapKey(annotationMirror).get()).asType(); if (!types.isAssignable(parameterType, injectorFactoryOf(mapKeyType))) { messager.printMessage( Kind.ERROR, String.format("%s does not implement AndroidInjector<%s>", parameterType, mapKeyType), method, annotationMirror); } }