google/dagger

Dagger 2.50 KSP fails to generate field in implementation for a @Named field

ggrell opened this issue · 4 comments

In the process of switching from KAPT to KSP, using Dagger 2.50. I have a top-level app component for my Android app which contains a @Named field, like this:

@AppScope
@Component(modules = [...])
interface AppComponent {
    val someInjectedString: String
        @Named("Something") get
}

The compile failed with: DaggerAppComponent.java:109: error: AppComponentImpl is not abstract and does not override abstract method getSomeInjectedString() in AppComponent private static final class AppComponentImpl implements AppComponent {

The generated code in DaggerAppComponent.java is missing the getter for the named field. All other fields and functions have implementations. This works correctly under KAPT.

I have a similar issue with injecting a named parameter

class DefaultClient @Inject constructor(
    ...,
    @Named(BuildConfig.LIBRARY_PACKAGE_NAME) private val loggingInterceptor: LoggingInterceptor
) : HttpClient {

causes

[ksp] dagger.internal.codegen.base.DaggerSuperficialValidation$ValidationException$UnexpectedException:
  Validation trace:
    => element (CLASS): ...DefaultClient
    => element (CONSTRUCTOR): DefaultClient(...,com.optomany.axept.pro.log.LoggingInterceptor)
    => element (PARAMETER): loggingInterceptor
    => annotation type: javax.inject.Named
	at dagger.internal.codegen.base.DaggerSuperficialValidation$ValidationException.from(DaggerSuperficialValidation.java:527)
...
Caused by: java.lang.ClassCastException: class dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.DefaultKspType cannot be cast to class java.lang.String (dagger.spi.internal.shaded.androidx.room.compiler.processing.ksp.DefaultKspType is in unnamed module of loader java.net.URLClassLoader @58c23d18; java.lang.String is in module java.base of loader 'bootstrap')

@ggrell thanks for reporting, we'll try to take a look at this and figure out why the getter method is missing in KSP.

In the meantime, you should be able to just swap this over to a normal function, which I would recommend anyway since it's cleaner and more intuitive. For example

@AppScope
@Component(modules = [...])
interface AppComponent {
    @Named("Something")
    fun getSomeInjectedString(): String
}

@henrik-klev that is a different issue -- it's a duplicate of #4051. You can see that issue for the current workaround, or the more general workaround here #4049 (comment)

i ran into DaggerSuperficialValidation$ValidationException$UnexpectedException as well...

it turned out to be a very misleading error that was caused by a dumb mistake.

it involved the following classes:

  1. class A
    • this is the class that showed up in the stack trace
    • it has no obvious problems
  2. class B:
    • this class is using constructor injection to inject class A into itself
    • this class also has a compiler error (in my case, it has 2 companion objects due to bad git merge...)

the solution in my case was to resolve the compiler error in class B, which fixed the error message.

my mistake was silly, but i think the error is misleading. i'd rather get a compiler error that points me to the correct file.

@ericytsang - Your issue I believe is separate than the original issue. However, we have been discussing the issue of missing compiler errors already internally. I spoke with the KSP team and they filed the tracking issue you should see mentioned above. You can follow along there for updates.