moxy-community / Moxy

Moxy is MVP library for Android with incremental annotation processor and ktx features
MIT License
327 stars 33 forks source link

Change strategy inheritance algorithm #70

Closed aasitnikov closed 4 years ago

aasitnikov commented 4 years ago

In current compiler implementation child interface state strategy propogated to superinterface, which can be source of hard to find bugs.

Consider following snippet:

interface ErrorView : MvpView {
    fun showErrorDialog(error: String)
}

@StateStrategyType(OneExecutionStateStrategy::class)
interface OneExecutionView : ErrorView {
    fun oneExecutionFunction()
}

@StateStrategyType(AddToEndSingleStrategy::class)
interface AddToEndSingleView : ErrorView {
    fun addToEndFunction()
}

Note that the ErrorView interface does not define any strategy, and two different child interfaces define different strategies. In the current implementation generated viewstates will have following state strategies:

class AddToEndSingleView$$State : AddToEndSingleView {
    fun addToEndFunction() -> AddToEndSingleStrategy::class
    fun showErrorDialog(error: String) -> AddToEndSingleStrategy::class
}

class OneExecutionView$$State : OneExecutionView {
    fun oneExecutionFunction() ->  OneExecutionStateStrategy:class
    fun showErrorDialog(String error) -> OneExecutionStateStrategy::class
}

As you can see method showErrorDialog() has different strategies in different views.

Superinterface strategies should be evaluated without influence from child interfaces and vice-versa. So following behaviour proposed:

  1. Each view interface must have all strategies defined in it, even if it's not used directly and only used as superinteface.
  2. If interface has methods without strategies, compilation should fail.
  3. If superinterface method is overriden by child interface, than it should have child strategy, whether it's defined directly on the method or on the child interface. Methods are compared by name and parameter types.
  4. Superinterface strategy is not inherited. If child interface has no interface strategy and some method in it is defined without any strategy, than compilation should fail.