Open G00fY2 opened 1 year ago
Hi @G00fY2, thanks for posting this!
I'm still working on reproducing the issue you're seeing locally, but I haven't been able to reproduce it yet.
In the meantime, could you try something for me? My guess is that KSP can't determine the return type in this case because it's having trouble figuring out the type of BuildConfig.API_BASE_URL
(e.g. maybe BuildConfig
is a transitive dependency that's no longer on the compilation classpath?).
To test that, can you replace BuildConfig.API_BASE_URL
with inline strings and see if you still get this issue? Something like this:
fun provideApiBaseUrl(currentEndpointProvider: CurrentEndpointProvider) =
when (currentEndpointProvider.provide()) {
CurrentEndpoint.PROD -> "someString"
else -> "someOtherString"
}
I believe the issue here is that AGP's BuildConfig
generated class is not wired correctly as an input in KSP and thus it is unable to resolve those constants and determine they are String which further prevent the type inference of the function's return type. See also: https://github.com/google/ksp/issues/350
Ah, thanks for the pointers @danysantiago! Exactly what I was thinking was happening.
Just to clarify, is this a bug in KSP or AGP (I see the bug is filed in ksp's issues, but from the contents of the bug it sounds like it could be an issue within AGP itself)?
Sorry, also had in mind that's this is related to referencing the Android BuildConfig but forgot to look this up in the KSP issues. Looks like generally explicit type specification is not mandatory. Feel free to close this issue. Maybe it will still help people facing this issue by pointing them in the right direction.
Also, I should probably also mention that in general I would recommend always making the return type explicit for @Provides
methods. It makes searching for where a particular Dagger key is bound easier, and it allows you to control the exact type that is used (which is important in Dagger).
I am having a very similar stacktrace:
e: [ksp] InjectProcessingStep was unable to process 'mainHeaderColorDataSource' because 'error.NonExistentClass' could not be resolved.
Dependency trace:
=> element (CLASS): com.company.project.maps.presentation.MapFragment
=> type (DECLARED superclass): com.company.project.presentation.base.BaseFragment<error.NonExistentClass>
=> type (ERROR type argument): error.NonExistentClass
If type 'error.NonExistentClass' is a generated type, check above for compilation errors that may have prevented the type from being generated. Otherwise, ensure that type 'error.NonExistentClass' is on your classpath.
In my case, the dependency targets to a ViewBinding file, so, as @danysantiago says, it seems to be also related to the AGP generated classes wiring:
class MapFragment : BaseFragment<FragmentMapBinding>(
FragmentMapBinding::inflate
)
For reference, here is the open issue regarding ViewBinding: https://github.com/google/dagger/issues/4049
I have the same issue, but In my case I am trying to Provide PreferenceDataStore
like shown below:
@Singleton
@Provides
fun providesDataStore(@ApplicationContext app: Context): DataStore<Preferences> {
return PreferenceDataStoreFactory.create(
corruptionHandler = null,
migrations = listOf(),
scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
produceFile = {app.preferencesDataStoreFile(VIKI_PREFERENCES)}
)
}
In this case I got this error:
ModuleProcessingStep was unable to process 'al.bruno.core.di.CoreModule' because 'error.NonExistentClass' could not be resolved.
Dependency trace:
=> element (CLASS): al.bruno.core.di.CoreModule
=> element (METHOD): userPreferencesStore(android.content.Context)
=> type (ERROR return type): error.NonExistentClass
If type 'error.NonExistentClass' is a generated type, check above for compilation errors that may have prevented the type from being generated. Otherwise, ensure that type 'error.NonExistentClass' is on your classpath.
We're working on a proper fix for the issue by exposing an API for generated java sources by the android gradle plugin to be consumed by KSP gradle plugin. Meanwhile, you can add the following snippet to your build file as a workaround to wire build config generated classes to the ksp task.
androidComponents {
onVariants(selector().all(), { variant ->
afterEvaluate {
// This is a workaround for https://issuetracker.google.com/301244513 which depends on internal
// implementations of the android gradle plugin and the ksp gradle plugin which might change in the future
// in an unpredictable way.
project.tasks.getByName("ksp" + variant.name.capitalize() + "Kotlin") {
def buildConfigTask = (com.android.build.gradle.tasks.GenerateBuildConfig) project.tasks.getByName("generate" + variant.name.capitalize() + "BuildConfig")
((org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool) it).setSource(
buildConfigTask.sourceOutputDir
)
}
}
})
}
thanks @AmrAfifiy. The snippet works well in my case
Had the same issue. I don't know how, but Code snippet provided by @AmrAfifiy worked.
I also, have the same issue for Generic classes
When using DataStore and Proto, add the below code. It works.
app.build.gradle.kts
android {
androidComponents {
onVariants(selector().all()) { variant ->
afterEvaluate {
project.tasks.getByName("ksp" + variant.name.capitalized() + "Kotlin") {
val buildConfigTask = project.tasks.getByName("generate${variant.name.capitalized()}Proto")
as com.google.protobuf.gradle.GenerateProtoTask
dependsOn(buildConfigTask)
(this as AbstractKotlinCompileTool<*>).setSource(buildConfigTask.outputBaseDir)
}
}
}
}
}
This is still an issue when using KPS2 (ksp.useKSP2= true), I have something like
@Module
@InstallIn(ActivityRetainedComponent::class)
internal interface NavigationModule {
@Binds
@IntoMap
@DeeplinkRouteFactoryKey(Route.VOLUME_DETAIL)
fun bindTaskDetailDeepLinkRouteFactory(
impl: VolumePageDeepLinkRouteFactory
): DeeplinkRouteFactory
}
@MapKey
annotation class DeeplinkRouteFactoryKey(val value: Route)
enum class Route { ... }
and Im getting (... is my package name :))
[ksp] dagger.internal.codegen.base.DaggerSuperficialValidation$ValidationException$UnexpectedException:
Validation trace:
=> element (INTERFACE): ...NavigationModule
=> element (METHOD): bindTaskDetailDeepLinkRouteFactory(...VolumePageDeepLinkRouteFactory)
=> annotation type: ...DeeplinkRouteFactoryKey
KPS version 2.0.0-1.0.21
@oscarg798 Looks like KSP2 is currently not yet support https://github.com/google/dagger/issues/4303#issuecomment-2100469486
This worked for me:
When using DataStore and Proto, add the below code. It works.
app.build.gradle.kts android { androidComponents { onVariants(selector().all()) { variant -> afterEvaluate { project.tasks.getByName("ksp" + variant.name.capitalized() + "Kotlin") { val buildConfigTask = project.tasks.getByName("generate${variant.name.capitalized()}Proto") as com.google.protobuf.gradle.GenerateProtoTask dependsOn(buildConfigTask) (this as AbstractKotlinCompileTool<*>).setSource(buildConfigTask.outputBaseDir) } } } } }
As an alternative, I found that not applying the com.google.dagger.hilt.android
plugin and instead adding the classes to the annotations directly also resolved the issue:
@HiltAndroidApp(Application::class)
class App : Application()
Just leaving this here in case it helps anyone else facing similar problems.
Previously when using kapt the following
@Provides
provideApiBaseUrl
method was working:With ksp compilation breaks with the following error message:
Adding explixit type specification to the
@Provides
method fixes this issue:Not sure if you could add a more helpful error message for such cases.
Mostly posting this for visibility reasons, since maybe more people run into such issues when migrating to ksp.