google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.4k stars 2.01k forks source link

KAPT (non-AGP) fails to see correct superclasses in Hilt AndroidEntryPoint processor #4075

Open pswaminathan opened 11 months ago

pswaminathan commented 11 months ago

A demonstration of this issue can be seen with:

More detail:

When using Dagger in a Kotlin project built with Bazel (really, anything without bytecode injection), AndroidEntryPoint processor processes, e.g.:

@HiltAndroidApp(Application::class)
class DemoApplication : Hilt_DemoApplication()

But instead of recognizing Hilt_DemoApplication as the superclass of DemoApplication, sees Object. This causes the processor to fail with:

error: /var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd14073656098635999496/_kotlinc/app-lib_kt_jvm/temp/stubs/com/example/demo/MainActivity.java:5: error: [Hilt] @AndroidEntryPoint class expected to extend Hilt_MainActivity. Found: Object
public final class MainActivity {
             ^
  [Hilt] Processing did not complete. See error above for details.
error: /var/folders/71/0r_ylvb13vv2my1_676sx1gm0000gn/T/pwd14073656098635999496/_kotlinc/app-lib_kt_jvm/temp/stubs/com/example/demo/DemoApplication.java:5: error: [Hilt] @HiltAndroidApp class expected to extend Hilt_DemoApplication. Found: Object
public final class DemoApplication {
             ^
  [Hilt] Processing did not complete. See error above for details.
app/DemoApplication.kt:7:25: error: unresolved reference: Hilt_DemoApplication
class DemoApplication : Hilt_DemoApplication()
                        ^
app/MainActivity.kt:8:22: error: unresolved reference: Hilt_MainActivity
class MainActivity : Hilt_MainActivity() {
                     ^

This has not the same issue that bazelbuild/rules_kotlin#514 was opened with. That issue (annotation processor not being run) has been fixed. As you can see by this output, the annotation processor is being run. The code at issue is here. If you log out what superclass is being recognized, what you actually see is, e.g.

entry point element: com.example.demo.MainActivity
entry point superclass: java.lang.Object
entry point element: com.example.demo.DemoApplication
entry point superclass: java.lang.Object

If you change that to use the generated class, it works. This is not a resolution, of course—it does not do the same thing as before of respecting the intended superclass + validating that it matches what is correct. But it demonstrates where the issue lies.

danysantiago commented 11 months ago

Have you inspected the KAPT generated stubs? It is likely the stub is missing the superclass.

This is likely occurring because correctErrorTypes is turned off and KAPT will simply remove super-classes and super-interfaces instead of translating them to NonExistentClass. Meanwhile turning the flag ON will make KAPT generate stubs with the not-yet-generated class, enabling processing to continue fine since that class will be generated by a Hilt processor.

There is some history about this flag being hardcoded off in the bazel rules: https://github.com/bazelbuild/rules_kotlin/issues/804 and https://github.com/bazelbuild/rules_kotlin/issues/634, I don't think there is anything on Hilt's side to do.

pswaminathan commented 11 months ago

Wouldn't that result in it being NonExistentClass, not Object? The stubs show Object.

danysantiago commented 11 months ago

KAPT doesn't always replace missing classes with error.NonExistentClass, I don't know the details of why it doesn't for superclasses, maybe because it would generate a bad Java stub (is the missing type a class or an interface?), but the fact that the stub only contains Object is an indicator that correctErrorTypes is turned off and when using KAPT Dagger processes the Java stubs not the actual Kotlin sources.