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

Providing a function instead of property seems to not always work #321

Closed
degill opened this issue Nov 22, 2023 · 1 comment · Fixed by #328
Closed

Providing a function instead of property seems to not always work #321

degill opened this issue Nov 22, 2023 · 1 comment · Fixed by #328
Labels
bug Something isn't working
Milestone

Comments

@degill
Copy link

degill commented Nov 22, 2023

Hello there 👋
Thanks for the fantastic library - made it really easy to convert an android app using dagger to a multi-platform app using kotlin-inject. I couldn't wish for anything more.

Background

We need to have our component expose a type Foo that is also used inside the component by another type Bar. This did work when the provisioning was declared as a property on the component, but seems to not work when instead using a function. It looks like the generated code still tries to call the function as a property. At first I thought we are having caching issues here.

Minimal example

I created a minimal example repo here: https://github.com/degill/kotlin-inject-fun-bug-example

But it boils down to these lines:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val appComponent = AppComponent::class.create()
        appComponent.provideBar()
    }
}

@Component
abstract class AppComponent {
    @Provides
    fun FooImpl.bind(): Foo = this
//    abstract fun provideFoo(): Foo // Will not compile with error "Function invocation 'provideFoo()' expected"
    abstract val provideFoo: Foo // Will compile fine
    abstract fun provideBar(): Bar
}

interface Foo
@Inject
class FooImpl : Foo

@Inject
class Bar(val foo: Foo)

Actual behaviour:

The code that gets generated tries to call provideFoo as a property:

public class InjectAppComponent() : AppComponent() {
  override fun provideFoo(): Foo = FooImpl().bind()

  override fun provideBar(): Bar = Bar(
    foo = provideFoo // With error "Function invocation 'provideFoo()' expected"
  )
}

Expected behaviour

In the README.md it says using either way should work:

In your component you can declare abstract read-only properties or functions to return an instance of a given type.

But maybe I overlooked something.

@evant
Copy link
Owner

evant commented Nov 27, 2023

Thanks for the reproduction! This would've been quite tricky to track down without it.

evant added a commit that referenced this issue Nov 27, 2023
evant added a commit that referenced this issue Nov 27, 2023
@evant evant added this to the v0.7.0 milestone Nov 27, 2023
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
2 participants