Search code examples
androidannotationsgeneratordaggersubcomponent

Dagger 2.10 subcomponent generator - Injector validation fails


I'm trying to create an annotation processor which will process my MVP views (fragments) to auto-generated Subcomponents (similar to https://github.com/lukaspili/Auto-Dagger2, but for the new Dagger 2.10 android injectors)

So far, I've been able to generate appropriate files, but there is a strange error message when compiling generated components

Error:(22, 58) error: @dagger.android.support.FragmentKey methods should bind dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>, not dagger.android.AndroidInjector.Factory<? extends android.support.v4.app.Fragment>. See google.github.io/dagger/android

The structure of Factory module and Subcomponent files should be correct, because as soon as I copy-paste the generated classes and create a regular classes (both Factory module and Subcomponent) and use real classes instead of generated ones, the message is no longer shown and compilation succeeds

It seems like the problem lies in AndroidMapKeyValidator (link), where !MoreTypes.equivalence().equivalent(returnType, intendedReturnType) call apparently fails, but I don't have much of an experience debugging annotation processors, so I don't know why precisely...

Can maybe anyone help where to search for the problem? Thanks

FYI: MyFragment does extend android.support.v4.app.Fragment


My files:

Generated Factory @Module public interface BuildersModule { @Binds @IntoMap @FragmentKey(MyFragment.class) abstract AndroidInjector.Factory<? extends Fragment> factory(MySubcomponent.Builder builder); }

Generated subcomponent @Subcomponent(modules = MyModule.class) public interface MySubcomponent extends AndroidInjector<MyFragment> { MyPresenter presenter(); @Subcomponent.Builder abstract class Builder extends AndroidInjector.Builder<MyFragment> {} }


Solution

  • If anyone is interested in solution:

    I found out that for some reason, references of ClassType-s compared during project's compile time are not the same when validating generated method.

    And these references, despite the fact that they are pointing to the same class, are checked for equality in auto-common library in EqualVisitor.visitDeclared method. Apparently, this can be a bug in auto-common, because Elements in visitDeclared are compared by object reference, but not type reference.

    So workaround here is to use local fixed copy of auto-common library and exclude all dependencies of the original library.

    //TODO think if this is the correct solution to cast both elements
    //return aElement.equals(bElement)
    return ((TypeElement) aElement).getQualifiedName().equals(((TypeElement) bElement).getQualifiedName())
           && equal(a.getEnclosingType(), b.getEnclosingType(), newVisiting)
           && equalLists(a.getTypeArguments(), b.getTypeArguments(), newVisiting);
    


    I still have to check why those references are not the same, and I have to think how the equality check can be fixed properly in auto-common (I use just a quickfix) before filing an issue in auto-common repo.