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

Support gradle incremental compilation #256

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 16 additions & 11 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,23 @@ ext {
targetVersionCode = 45
targetVersionName = "1.5.5"

def autoServiceVersion = '1.0-rc5'
def gradleIncapHelperVersion = '0.2'
deps = [
android : 'com.google.android:android:1.6_r2',
javapoet : 'com.squareup:javapoet:1.10.0',
junit : 'junit:junit:4.12',
mockito : 'org.mockito:mockito-core:1.10.19',
truth : 'com.google.truth:truth:0.34',
robolectric : 'org.robolectric:robolectric:3.0',
compiletesting: 'com.google.testing.compile:compile-testing:0.15',
asm : ['org.ow2.asm:asm:6.0', 'org.ow2.asm:asm-util:6.0'],
autoservice : 'com.google.auto.service:auto-service:1.0-rc4',
autocommon : 'com.google.auto:auto-common:0.10',
guava : 'com.google.guava:guava:21.0',
android : 'com.google.android:android:1.6_r2',
javapoet : 'com.squareup:javapoet:1.10.0',
junit : 'junit:junit:4.12',
mockito : 'org.mockito:mockito-core:1.10.19',
truth : 'com.google.truth:truth:0.34',
robolectric : 'org.robolectric:robolectric:3.0',
compiletesting : 'com.google.testing.compile:compile-testing:0.15',
asm : ['org.ow2.asm:asm:6.0', 'org.ow2.asm:asm-util:6.0'],
autoserviceAnnotations : "com.google.auto.service:auto-service-annotations:$autoServiceVersion",
autoserviceProcessor : "com.google.auto.service:auto-service:$autoServiceVersion",
autocommon : 'com.google.auto:auto-common:0.10',
guava : 'com.google.guava:guava:21.0',
gradleIncapHelperAnnotations: "net.ltgt.gradle.incap:incap:$gradleIncapHelperVersion",
gradleIncapHelperProcessor : "net.ltgt.gradle.incap:incap-processor:$gradleIncapHelperVersion",
]
}

Expand Down
7 changes: 5 additions & 2 deletions moxy-compiler/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,15 @@ dependencies {
implementation deps.javapoet

compileOnly deps.autocommon
compileOnly deps.autoservice
compileOnly deps.autoserviceAnnotations
annotationProcessor deps.autoserviceProcessor
compileOnly deps.guava
compileOnly deps.gradleIncapHelperAnnotations
annotationProcessor deps.gradleIncapHelperProcessor

javadocDeps project(':moxy')
javadocDeps deps.javapoet
javadocDeps deps.autoservice
javadocDeps deps.autoserviceAnnotations

testImplementation deps.junit
testImplementation deps.truth
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.arellomobile.mvp.compiler;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;

import static javax.lang.model.SourceVersion.latestSupported;

public abstract class MoxyBaseCompiler extends AbstractProcessor {

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
ProcessingEnvironmentHolder.initialize(processingEnv);
}

@Override
public SourceVersion getSupportedSourceVersion() {
return latestSupported();
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (annotations.isEmpty()) {
return false;
}
try {
throwableProcess(roundEnv);
} catch (RuntimeException e) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.OTHER, "Moxy compilation failed. Could you copy stack trace above and write us (or make issue on Github)?");
e.printStackTrace();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Moxy compilation failed; see the compiler error output for details (" + e + ")");
}
return false;
}

protected abstract void throwableProcess(RoundEnvironment roundEnv);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package com.arellomobile.mvp.compiler;

import com.arellomobile.mvp.GenerateViewState;
import com.arellomobile.mvp.InjectViewState;
import com.arellomobile.mvp.RegisterMoxyReflectorPackages;
import com.arellomobile.mvp.compiler.presenterbinder.InjectPresenterProcessor;
import com.arellomobile.mvp.compiler.reflector.MoxyReflectorGenerator;
import com.arellomobile.mvp.compiler.viewstate.ViewInterfaceProcessor;
import com.arellomobile.mvp.compiler.viewstateprovider.InjectViewStateProcessor;
import com.arellomobile.mvp.presenter.InjectPresenter;
import com.google.auto.service.AutoService;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.tools.Diagnostic;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@AutoService(Processor.class)
@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.AGGREGATING)
public class MoxyReflectorCompiler extends MoxyBaseCompiler {

public static final String MOXY_REFLECTOR_DEFAULT_PACKAGE = "com.arellomobile.mvp";
private static final String OPTION_MOXY_REFLECTOR_PACKAGE = "moxyReflectorPackage";

private final Map<String, String> processorOptions = new HashMap<>();

@Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
super.init(processingEnv);
processorOptions.putAll(processingEnv.getOptions());
}

@Override
public Set<String> getSupportedOptions() {
return Collections.singleton(OPTION_MOXY_REFLECTOR_PACKAGE);
}

@Override
public Set<String> getSupportedAnnotationTypes() {
final Set<String> supportedAnnotationTypes = new HashSet<>();
Collections.addAll(supportedAnnotationTypes,
InjectPresenter.class.getCanonicalName(),
InjectViewState.class.getCanonicalName(),
GenerateViewState.class.getCanonicalName(),
RegisterMoxyReflectorPackages.class.getCanonicalName());
return supportedAnnotationTypes;
}

@Override
protected void throwableProcess(RoundEnvironment roundEnv) {
String moxyReflectorPackage = processorOptions.get(OPTION_MOXY_REFLECTOR_PACKAGE);
if (moxyReflectorPackage == null) {
moxyReflectorPackage = MOXY_REFLECTOR_DEFAULT_PACKAGE;
}

final InjectViewStateProcessor injectViewStateProcessor = new InjectViewStateProcessor();
final InjectPresenterProcessor injectPresenterProcessor = new InjectPresenterProcessor();
final ViewInterfaceProcessor viewInterfaceProcessor = new ViewInterfaceProcessor();
processInjectors(roundEnv, InjectViewState.class, ElementKind.CLASS, injectViewStateProcessor);
processInjectors(roundEnv, InjectPresenter.class, ElementKind.FIELD, injectPresenterProcessor);
final List<String> additionalMoxyReflectorPackages = getAdditionalMoxyReflectorPackages(roundEnv);
try {
MoxyReflectorGenerator.generate(
moxyReflectorPackage,
injectViewStateProcessor.getPresenterClassNames(),
injectPresenterProcessor.getPresentersContainers(),
viewInterfaceProcessor.getUsedStrategies(),
additionalMoxyReflectorPackages
).writeTo(processingEnv.getFiler());
} catch (IOException e) {
e.printStackTrace();
}
}

private <E extends Element, R> void processInjectors(RoundEnvironment roundEnv,
Class<? extends Annotation> clazz,
ElementKind kind,
ElementProcessor<E, R> processor) {

for (Element element : roundEnv.getElementsAnnotatedWith(clazz)) {
if (element.getKind() != kind) {
ProcessingEnvironmentHolder.getMessager().printMessage(Diagnostic.Kind.ERROR,
element + " must be " + kind.name() + ", or not mark it as @" + clazz.getSimpleName());
}

if (element.getKind() != kind) {
ProcessingEnvironmentHolder.getMessager().printMessage(Diagnostic.Kind.ERROR, element + " must be " + kind.name());
}

//noinspection unchecked
processor.process((E) element);
}
}

private List<String> getAdditionalMoxyReflectorPackages(RoundEnvironment roundEnv) {
List<String> result = new ArrayList<>();

for (Element element : roundEnv.getElementsAnnotatedWith(RegisterMoxyReflectorPackages.class)) {
if (element.getKind() != ElementKind.CLASS) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, element + " must be " + ElementKind.CLASS.name() + ", or not mark it as @" + RegisterMoxyReflectorPackages.class.getSimpleName());
}

String[] packages = element.getAnnotation(RegisterMoxyReflectorPackages.class).value();

Collections.addAll(result, packages);
}

return result;
}
}