Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated broken code #449

Open
vRallev opened this issue Oct 31, 2024 · 0 comments
Open

Generated broken code #449

vRallev opened this issue Oct 31, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@vRallev
Copy link
Contributor

vRallev commented Oct 31, 2024

We migrated our project from Dagger 2 to kotlin-inject. It's a middle-sized project and the component is successfully generated, but fails to compile. I'm not able to reproduce the issue in a sample, but I can trigger the bug by changing provider methods.

The class is simple:

class MeteredCommunicationImpl(
    ...
) : MeteredCommunication

With these provider methods:

    @SingleIn(AppScope::class)
    @Provides
    fun provideMeteredCommunicationImpl(
        ...
    ): MeteredCommunicationImpl = MeteredCommunicationImpl(
        ...
    )

    @Provides
    fun provideMeteredCommunication(impl: MeteredCommunicationImpl): MeteredCommunication = impl

In the generated component there is this line for another provider method where MeteredCommunication is an input:

provideMiddlewareEventBus(
  meteredCommunication = meteredCommunication
)

This fails to compile. The argument meteredCommunication refers to a property, which doesn't exist. Instead, there is:

  private val function0MeteredCommunication: Function0<MeteredCommunication>
    get() = {
      provideMeteredCommunication(
        impl = meteredCommunicationImpl
      )
    }

I couldn't find out what triggers the bug as I don't see it with other provided types using the same pattern. But I found two workarounds. The first is removing the second provider method and making the first return the interface type:

    @SingleIn(AppScope::class)
    @Provides
    fun provideMeteredCommunicationImpl(
        ...
    ): MeteredCommunication = MeteredCommunicationImpl(
        ...
    )

With this the following property will be generated in the component:

  private val meteredCommunication: MeteredCommunication
    get() = _scoped.get("com.amazon.bivis.service.MeteredCommunication") {
      run<MeteredCommunication> {
        lateinit var meteredCommunication: MeteredCommunication
        provideMeteredCommunicationImpl(
          ...
        ).also {
          meteredCommunication = it
        }
      }

    }

(Sidenote here, the code does unnecessary things. The run block and the lateinit var meteredCommunication are redundant.)

The second workaround is adding the property manually to the component:

@Component
interface MyComponent {
  val meteredCommunication
}

This forces kotlin-inject to implement the property and then it can be referenced successfully in the generated code.

(Another side note with the 2nd workaround. By adding this single line the size of the generated component grows from 9k lines of code to close to 15k, which is very surprising)

@evant evant added the bug Something isn't working label Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants