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

Add option to enable isolating incremental annotation processing mode #121

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,14 @@ To switch the error output method enable this option
enableEmptyStrategyHelper : 'true'
```

How to correctly use compilation flags check out the [sample-app build.gradle file](https://github.com/moxy-community/Moxy/blob/develop/sample-app/build.gradle)
To enable `Isolating` incremental annotation processor mode for Moxy processor use this option
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add something like "for faster incremental builds" for people, that don't know what isolating mode is?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. I also add link to gradle documentation page about incremental annotation processing support.

```kotlin
moxyEnableIsolatingProcessing : 'true'
```
Use this option for faster incremental builds. You can read about differences between `Isolating` and `Aggreagating` modes and Gradle incremental annotation processing support in [Gradle documentation](https://docs.gradle.org/5.0/userguide/java_plugin.html#sec:incremental_annotation_processing).
**Warning!** This option is experimental for now. It should work fine, but we prefer to make this transition as safe as possible. If you'll encounter compilation problems after enabling this option, please feel free to [report an ussue](https://github.com/moxy-community/Moxy/issues/new). Hopefully we will enable isolating annotation processor mode by default after several releases.

How to correctly use compilation flags check out the [sample-app build.gradle file](https://github.com/moxy-community/Moxy/blob/develop/sample-app/build.gradle.kts)

## ProGuard\R8
If you are using R8 then no additional configuration required. If you use ProGuard then you have to manually add rules from [this file](https://github.com/moxy-community/Moxy/blob/develop/moxy/src/main/resources/META-INF/proguard/moxy.pro).
Expand Down
3 changes: 2 additions & 1 deletion moxy-compiler/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ dependencies {

implementation(Deps.javapoet)

implementation(Deps.gradleIncapHelperAnnotations)

compileOnly(Deps.autocommon)
compileOnly(Deps.autoservice)
compileOnly(Deps.gradleIncapHelperAnnotations)

kapt(Deps.gradleIncapHelperProcessor)
kapt(Deps.autoservice)
Expand Down
54 changes: 47 additions & 7 deletions moxy-compiler/src/main/java/moxy/compiler/MvpCompiler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import moxy.compiler.viewstateprovider.InjectViewStateProcessor
import moxy.compiler.viewstateprovider.ViewStateProviderClassGenerator
import moxy.presenter.InjectPresenter
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.AGGREGATING
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.DYNAMIC
import java.io.IOException
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.Messager
Expand All @@ -29,7 +30,7 @@ import javax.lang.model.util.Types
import javax.tools.Diagnostic

@AutoService(Processor::class)
@IncrementalAnnotationProcessor(AGGREGATING)
@IncrementalAnnotationProcessor(DYNAMIC)
class MvpCompiler : AbstractProcessor() {

private val defaultStrategy: String? get() = options[DEFAULT_MOXY_STRATEGY]
Expand All @@ -42,13 +43,51 @@ class MvpCompiler : AbstractProcessor() {
typeUtils = processingEnv.typeUtils
elementUtils = processingEnv.elementUtils
options = processingEnv.options

if (isIsolatingProcessingEnabled) {
printIsolatingOptionWarning()
}
}

override fun getSupportedOptions(): Set<String> = setOf(
OPTION_ENABLE_EMPTY_STRATEGY_HELPER,
DEFAULT_MOXY_STRATEGY,
OPTION_DISABLE_EMPTY_STRATEGY_CHECK
)
private fun printIsolatingOptionWarning() {
messager.printMessage(
Diagnostic.Kind.NOTE,
"""
Isolating annotation processor mode was enabled for Moxy.
This option is experimental for now. We are pretty sure it should work correctly but we are not 100% sure.

If you'll notice problems after enabling this option such as:
- ViewState is not being recompiled after you change your view interface
- ViewState is not being compiled at all after you change your view interface
please report them using https://github.com/moxy-community/Moxy/issues/new.

In the same time to fix such problems while waiting for fix on our side you have two options:
1. Just disable isolating mode. This will switch Moxy processor back to aggregating mode, so incremental compilation will be ok. This could hurt you compilation time a bit, hopefully not very much.
2. Do clean build. This will force Gradle to recompile all generated sources from scratch. Sure, this is also bad for compilation time.

Hopefully we will enable isolating annotation processor mode by default after several releases.
""".trimIndent()
)
}

override fun getSupportedOptions(): Set<String> {
val gradleIncrementalProcessingTypeOption = if (isIsolatingProcessingEnabled) {
IncrementalAnnotationProcessorType.ISOLATING
} else {
IncrementalAnnotationProcessorType.AGGREGATING
}.processorOption
return setOf(
OPTION_ENABLE_EMPTY_STRATEGY_HELPER,
DEFAULT_MOXY_STRATEGY,
OPTION_DISABLE_EMPTY_STRATEGY_CHECK,
OPTION_ENABLE_ISOLATING_PROCESSING,
gradleIncrementalProcessingTypeOption
)
}

private val isIsolatingProcessingEnabled by lazy {
isOptionEnabled(OPTION_ENABLE_ISOLATING_PROCESSING)
}

override fun getSupportedAnnotationTypes(): Set<String> = setOf(
InjectPresenter::class.java.canonicalName,
Expand Down Expand Up @@ -198,6 +237,7 @@ class MvpCompiler : AbstractProcessor() {
private const val OPTION_DISABLE_EMPTY_STRATEGY_CHECK = "disableEmptyStrategyCheck"
const val DEFAULT_MOXY_STRATEGY = "defaultMoxyStrategy"
private const val OPTION_ENABLE_EMPTY_STRATEGY_HELPER = "enableEmptyStrategyHelper"
private const val OPTION_ENABLE_ISOLATING_PROCESSING = "moxyEnableIsolatingProcessing"

@get:JvmStatic
lateinit var messager: Messager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ class InjectPresenterProcessor : ElementProcessor<VariableElement, TargetClassIn
bindTagProvidersToFields(fields, collectTagProviders(presentersContainer))

return TargetClassInfo(
ClassName.get(presentersContainer),
fields,
findSuperPresenterContainer(presentersContainer)
element = presentersContainer,
name = ClassName.get(presentersContainer),
fields = fields,
superPresenterBinder = findSuperPresenterContainer(presentersContainer)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class PresenterBinderClassGenerator : JavaFilesGenerator<TargetClassInfo> {

val classBuilder = TypeSpec
.classBuilder(containerSimpleName + MvpProcessor.PRESENTER_BINDER_SUFFIX)
.addOriginatingElement(targetClassInfo.element)
.addModifiers(Modifier.PUBLIC)
.superclass(PresenterBinder::class.className().parametrizedWith(targetClassName))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package moxy.compiler.presenterbinder

import com.squareup.javapoet.ClassName
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement

/**
* Represents class into which presenters will be injected.
* `PresenterBinder` will be generated based on data from this class.
* [superPresenterBinder] will be set if any parent class also requires injection.
*/
class TargetClassInfo constructor(
class TargetClassInfo(
val element: Element,
val name: ClassName,
val fields: List<TargetPresenterField>,
val superPresenterBinder: TypeElement?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class ViewStateClassGenerator : JavaFilesGenerator<ViewInterfaceInfo> {

val typeName = Util.getSimpleClassName(viewInterfaceInfo.element) + MvpProcessor.VIEW_STATE_SUFFIX
val classBuilder: Builder = TypeSpec.classBuilder(typeName)
.addOriginatingElement(viewInterfaceInfo.element)
.addModifiers(Modifier.PUBLIC)
.superclass(MvpViewState::class.className().parametrizedWith(nameWithTypeVariables))
.addSuperinterface(nameWithTypeVariables)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import javax.lang.model.element.TypeElement
* Represents presenter class annotated with `@InjectViewState`.
* `ViewStateProvider` will be generated based on data from this class.
*/
class PresenterInfo constructor(name: TypeElement, viewStateName: String) {
val name: ClassName = ClassName.get(name)
class PresenterInfo(val element: TypeElement, viewStateName: String) {
val name: ClassName = ClassName.get(element)
val viewStateName: ClassName = ClassName.bestGuess(viewStateName)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ViewStateProviderClassGenerator : JavaFilesGenerator<PresenterInfo?> {

val typeSpec = TypeSpec
.classBuilder(className)
.addOriginatingElement(presenterInfo.element)
.addModifiers(Modifier.PUBLIC)
.superclass(ViewStateProvider::class.java)
.addMethod(presenterInfo.generateGetViewStateMethod())
Expand Down
3 changes: 2 additions & 1 deletion sample-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ android {
arguments.putAll(mapOf(
"disableEmptyStrategyCheck" to "false",
"enableEmptyStrategyHelper" to "true",
"defaultMoxyStrategy" to "moxy.viewstate.strategy.AddToEndSingleStrategy"
"defaultMoxyStrategy" to "moxy.viewstate.strategy.AddToEndSingleStrategy",
"moxyEnableIsolatingProcessing" to "true"
))
}
}
Expand Down