From 7efce64860a3cb25e1db9bb1b6908419b7106889 Mon Sep 17 00:00:00 2001 From: Oleksandr Kucherenko Date: Tue, 23 Jun 2020 16:30:24 +0200 Subject: [PATCH] Merge of code changed proposed by EasyPark --- README.md | 117 +++++- .../java/com/olku/annotations/AutoProxy.java | 3 + .../annotations/AutoProxyClassGenerator.java | 2 + .../java/com/olku/annotations/RetBool.java | 2 +- .../java/com/olku/annotations/RetNumber.java | 2 +- .../com/olku/generators/RetBoolGenerator.java | 10 +- .../olku/generators/RetNumberGenerator.java | 10 +- .../com/olku/generators/ReturnsGenerator.java | 8 +- .../java/com/olku/generators/ReturnsPoet.java | 5 +- autoproxy-processor/build.gradle | 2 +- .../olku/processors/AutoProxyProcessor.java | 26 +- .../olku/processors/CommonClassGenerator.java | 345 +++++++++++++----- .../com/olku/processors/TypeProcessor.java | 45 ++- .../main/java/com/olku/annotations/RetRx.java | 2 +- .../com/olku/generators/JustRxGenerator.java | 7 +- .../com/olku/generators/RetRxGenerator.java | 10 +- gradle.properties | 2 +- .../autoproxy/sample/KotlinAbstractMvpView.kt | 18 +- .../olku/autoproxy/sample/MainActivity.java | 4 +- .../olku/autoproxy/sample/ParkingArea.java | 8 +- 20 files changed, 469 insertions(+), 159 deletions(-) diff --git a/README.md b/README.md index 3582166..091d7ab 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ include ':modules:autoproxy:autoproxy-processor' ## Step #3: Declare proxy class specifics ```java -@AutoProxy +@AutoProxy(flags = AutoProxy.Flags.ALL) public interface MvpView { /** Returns NULL if predicate returns False. */ @AutoProxy.Yield(Returns.NULL) @@ -220,7 +220,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final Observable dummyCall(final List generic) { - if (!predicate( Methods.DUMMYCALL, generic )) { + if (!predicate( M.DUMMYCALL, generic )) { // @com.olku.annotations.AutoProxy.Yield(adapter=com.olku.generators.RetRxGenerator.class, value="empty") return Observable.empty(); } @@ -228,7 +228,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final Observable dummyCall(final String message, final List args) { - if (!predicate( Methods.DUMMYCALL, message, args )) { + if (!predicate( M.DUMMYCALL, message, args )) { // @com.olku.annotations.AutoProxy.Yield throw new UnsupportedOperationException("cannot resolve return value."); } @@ -236,7 +236,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final Observable dummyCall(final String message, final Object... args) { - if (!predicate( Methods.DUMMYCALL, message, args )) { + if (!predicate( M.DUMMYCALL, message, args )) { // @com.olku.annotations.AutoProxy.Yield(adapter=com.olku.generators.RetRxGenerator.class, value="error") return Observable.error(new UnsupportedOperationException("unsupported method call")); } @@ -244,7 +244,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final double numericCall() { - if (!predicate( Methods.NUMERICCALL )) { + if (!predicate( M.NUMERICCALL )) { // @com.olku.annotations.AutoProxy.Yield("0") return 0; } @@ -252,7 +252,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final boolean booleanCall() { - if (!predicate( Methods.BOOLEANCALL )) { + if (!predicate( M.BOOLEANCALL )) { // @com.olku.annotations.AutoProxy.Yield("false") return false; } @@ -260,7 +260,7 @@ public abstract class Proxy_MvpView implements MvpView { } public final boolean dispatchDeepLink(@NonNull final Uri deepLink) { - if (!predicate( Methods.DISPATCHDEEPLINK, deepLink )) { + if (!predicate( M.DISPATCHDEEPLINK, deepLink )) { // @com.olku.annotations.AutoProxy.Yield("direct") // direct call, ignore predicate result } @@ -268,23 +268,48 @@ public abstract class Proxy_MvpView implements MvpView { } public final Observable startHearthAnimation() { - if (!predicate( Methods.STARTHEARTHANIMATION )) { + if (!predicate( M.STARTHEARTHANIMATION )) { // @com.olku.annotations.AutoProxy.Yield(adapter=com.olku.generators.JustRxGenerator.class, value="true") return Observable.just(true); } return this.inner.startHearthAnimation(); } - @StringDef({Methods.BOOLEANCALL, Methods.DISPATCHDEEPLINK, Methods.DUMMYCALL, Methods.NUMERICCALL, Methods.STARTHEARTHANIMATION}) - public @interface Methods { + @StringDef({M.BOOLEANCALL, M.DISPATCHDEEPLINK_DEEPLINK, M.DUMMYCALL, M.DUMMYCALL_GENERIC, M.DUMMYCALL_MESSAGE_ARGS, M.NUMERICCALL, M.STARTHEARTHANIMATION}) + public @interface M { + /** + * {@link #booleanCall()} + */ String BOOLEANCALL = "booleanCall"; - String DISPATCHDEEPLINK = "dispatchDeepLink"; + /** + * {@link #dispatchDeepLink(android.net.Uri)} + */ + String DISPATCHDEEPLINK_DEEPLINK = "dispatchDeepLink_deepLink"; + /** + * {@link #dummyCall()} + */ String DUMMYCALL = "dummyCall"; + /** + * {@link #dummyCall(java.util.List)} + */ + String DUMMYCALL_GENERIC = "dummyCall_generic"; + + /** + * {@link #dummyCall(java.lang.String, java.lang.Object[])} + */ + String DUMMYCALL_MESSAGE_ARGS = "dummyCall_message_args"; + + /** + * {@link #numericCall()} + */ String NUMERICCALL = "numericCall"; + /** + * {@link #startHearthAnimation()} + */ String STARTHEARTHANIMATION = "startHearthAnimation"; } } @@ -311,6 +336,76 @@ public abstract class Proxy_MvpView implements MvpView { ``` +## Customization of Generated Code + +By providing special flags you can customize output of AutoProxy generator: + +```kotlin +@AutoProxy(flags = AutoProxy.Flags.ALL) +abstract class KotlinAbstractMvpView { + /* ... */ +} +``` + +Outputs: + +```java + public abstract T afterCall(@M @NonNull final String methodName, final T result); + + /** + * Copy this declaration to fix method demands for old APIs: + * + *
+   * package java.util.function;
+   *
+   * public interface BiFunction<T, U, R> {
+   *     R apply(T t, U u);
+   * }
+   * 
+ */ + public static KotlinAbstractMvpView create(final KotlinAbstractMvpView instance, + final BiFunction action) { + return new Proxy_KotlinAbstractMvpView(instance) { + + @Override + public boolean predicate(final String methodName, final Object... args) { + return action.apply(methodName, args); + } + + @Override + public T afterCall(final String methodName, final T result) { + return result; + }; + }; + } + + public T dispatchByName(@M @NonNull final String methodName, final Object... args) { + final Object result; + if(M.BOOLEANCALL.equals(methodName)) { + return (T)(result = this.inner.booleanCall()); + } + if(M.DISPATCHDEEPLINK_DEEPLINK.equals(methodName)) { + return (T)(result = this.inner.dispatchDeepLink((android.net.Uri)args[0] /*deepLink*/)); + } + if(M.DUMMYCALL.equals(methodName)) { + return (T)(result = this.inner.dummyCall()); + } + if(M.DUMMYCALL_GENERIC.equals(methodName)) { + return (T)(result = this.inner.dummyCall((java.util.List)args[0] /*generic*/)); + } + if(M.DUMMYCALL_MESSAGE_ARGS.equals(methodName)) { + return (T)(result = this.inner.dummyCall((java.lang.String)args[0] /*message*/, (java.lang.Object[])args[1] /*args*/)); + } + if(M.NUMERICCALL.equals(methodName)) { + return (T)(result = this.inner.numericCall()); + } + if(M.STARTHEARTHANIMATION.equals(methodName)) { + return (T)(result = this.inner.startHearthAnimation()); + } + return (T)null; + } +``` + # Troubles http://www.vogella.com/tutorials/GitSubmodules/article.html diff --git a/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxy.java b/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxy.java index b9ba04b..976d42d 100644 --- a/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxy.java +++ b/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxy.java @@ -55,6 +55,9 @@ abstract class Common implements AutoProxyClassGenerator { int AFTER_CALL = 0x0002; /** Compose callByName(...) method that maps string name to a method call. */ int MAPPING = 0x004; + + /** Compose all additional methods. */ + int ALL = CREATOR | AFTER_CALL | MAPPING; } /** diff --git a/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxyClassGenerator.java b/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxyClassGenerator.java index cd27b16..70e44a8 100644 --- a/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxyClassGenerator.java +++ b/autoproxy-annotations/src/main/java/com/olku/annotations/AutoProxyClassGenerator.java @@ -16,9 +16,11 @@ public interface AutoProxyClassGenerator { @NonNull String getErrors(); + /** Get file Name. */ @NonNull String getName(); + /** Get generated elements. */ @NonNull List getOriginating(); } diff --git a/autoproxy-annotations/src/main/java/com/olku/annotations/RetBool.java b/autoproxy-annotations/src/main/java/com/olku/annotations/RetBool.java index 1274835..99ff364 100644 --- a/autoproxy-annotations/src/main/java/com/olku/annotations/RetBool.java +++ b/autoproxy-annotations/src/main/java/com/olku/annotations/RetBool.java @@ -1,6 +1,6 @@ package com.olku.annotations; -import androidx.annotation.*; +import androidx.annotation.StringDef; import java.lang.annotation.Retention; diff --git a/autoproxy-annotations/src/main/java/com/olku/annotations/RetNumber.java b/autoproxy-annotations/src/main/java/com/olku/annotations/RetNumber.java index 0397dfd..e83a241 100644 --- a/autoproxy-annotations/src/main/java/com/olku/annotations/RetNumber.java +++ b/autoproxy-annotations/src/main/java/com/olku/annotations/RetNumber.java @@ -1,6 +1,6 @@ package com.olku.annotations; -import androidx.annotation.*; +import androidx.annotation.StringDef; import java.lang.annotation.Retention; diff --git a/autoproxy-generators/src/main/java/com/olku/generators/RetBoolGenerator.java b/autoproxy-generators/src/main/java/com/olku/generators/RetBoolGenerator.java index 21041ba..e5b4fe2 100644 --- a/autoproxy-generators/src/main/java/com/olku/generators/RetBoolGenerator.java +++ b/autoproxy-generators/src/main/java/com/olku/generators/RetBoolGenerator.java @@ -1,12 +1,12 @@ package com.olku.generators; -import androidx.annotation.*; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.olku.annotations.RetBool; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; -import com.olku.annotations.RetBool; - /** Compose return types for boolean. */ public class RetBoolGenerator implements ReturnsPoet { @NonNull @@ -15,7 +15,7 @@ public static RetBoolGenerator getInstance() { } public boolean compose(@NonNull final Type returnType, - @RetBool final String type, + @Nullable @RetBool final String type, @NonNull final MethodSpec.Builder builder) { if (RetBool.FALSE.equals(type)) { builder.addStatement("return false"); @@ -29,6 +29,6 @@ public boolean compose(@NonNull final Type returnType, } private static final class Singleton { - static final RetBoolGenerator INSTANCE = new RetBoolGenerator(); + /* package */ static final RetBoolGenerator INSTANCE = new RetBoolGenerator(); } } diff --git a/autoproxy-generators/src/main/java/com/olku/generators/RetNumberGenerator.java b/autoproxy-generators/src/main/java/com/olku/generators/RetNumberGenerator.java index 3549e4e..afa77e1 100644 --- a/autoproxy-generators/src/main/java/com/olku/generators/RetNumberGenerator.java +++ b/autoproxy-generators/src/main/java/com/olku/generators/RetNumberGenerator.java @@ -1,12 +1,12 @@ package com.olku.generators; -import androidx.annotation.*; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.olku.annotations.RetNumber; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; -import com.olku.annotations.RetNumber; - import java.util.Map; import java.util.TreeMap; @@ -30,7 +30,7 @@ public static RetNumberGenerator getInstance() { } public boolean compose(@NonNull final Type returnType, - @NonNull @RetNumber final String type, + @Nullable @RetNumber final String type, @NonNull final MethodSpec.Builder builder) { final Class output = PRIMITIVES.get(returnType.toString()); @@ -56,6 +56,6 @@ public boolean compose(@NonNull final Type returnType, } private static final class Singleton { - static final RetNumberGenerator INSTANCE = new RetNumberGenerator(); + /* package */ static final RetNumberGenerator INSTANCE = new RetNumberGenerator(); } } diff --git a/autoproxy-generators/src/main/java/com/olku/generators/ReturnsGenerator.java b/autoproxy-generators/src/main/java/com/olku/generators/ReturnsGenerator.java index 6ee15d7..1d177be 100644 --- a/autoproxy-generators/src/main/java/com/olku/generators/ReturnsGenerator.java +++ b/autoproxy-generators/src/main/java/com/olku/generators/ReturnsGenerator.java @@ -1,12 +1,12 @@ package com.olku.generators; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.olku.annotations.Returns; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; -import com.olku.annotations.Returns; - /** Compose return types for boolean. */ public class ReturnsGenerator implements ReturnsPoet { @NonNull @@ -15,7 +15,7 @@ public static ReturnsGenerator getInstance() { } public boolean compose(@NonNull final Type returnType, - @NonNull @Returns final String type, + @Nullable @Returns final String type, @NonNull final MethodSpec.Builder builder) { // empty string if (Returns.EMPTY.equals(type)) { @@ -52,6 +52,6 @@ public boolean compose(@NonNull final Type returnType, } private static final class Singleton { - static final ReturnsGenerator INSTANCE = new ReturnsGenerator(); + /* package */ static final ReturnsGenerator INSTANCE = new ReturnsGenerator(); } } diff --git a/autoproxy-generators/src/main/java/com/olku/generators/ReturnsPoet.java b/autoproxy-generators/src/main/java/com/olku/generators/ReturnsPoet.java index 6545310..6e50004 100644 --- a/autoproxy-generators/src/main/java/com/olku/generators/ReturnsPoet.java +++ b/autoproxy-generators/src/main/java/com/olku/generators/ReturnsPoet.java @@ -1,6 +1,7 @@ package com.olku.generators; -import androidx.annotation.*; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; @@ -9,6 +10,6 @@ public interface ReturnsPoet { /** Compose return statement for provided method based on return type and modifier. */ boolean compose(@NonNull final Type returnType, - @NonNull final String modifier, + @Nullable final String modifier, @NonNull final MethodSpec.Builder builder); } diff --git a/autoproxy-processor/build.gradle b/autoproxy-processor/build.gradle index b27e874..f7b4e81 100644 --- a/autoproxy-processor/build.gradle +++ b/autoproxy-processor/build.gradle @@ -18,7 +18,7 @@ dependencies { /* CODE GENERATION */ implementation 'com.google.auto.service:auto-service:1.0-rc7' - kapt 'com.google.auto.service:auto-service:1.0-rc6' + kapt 'com.google.auto.service:auto-service:1.0-rc7' implementation 'com.squareup:javapoet:1.13.0' implementation "androidx.annotation:annotation:${supportVersion}" diff --git a/autoproxy-processor/src/main/java/com/olku/processors/AutoProxyProcessor.java b/autoproxy-processor/src/main/java/com/olku/processors/AutoProxyProcessor.java index 2ade1b6..996c5cf 100644 --- a/autoproxy-processor/src/main/java/com/olku/processors/AutoProxyProcessor.java +++ b/autoproxy-processor/src/main/java/com/olku/processors/AutoProxyProcessor.java @@ -1,12 +1,12 @@ package com.olku.processors; import com.google.auto.service.AutoService; - import com.olku.annotations.AutoProxy; import com.olku.annotations.AutoProxyClassGenerator; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -65,6 +65,11 @@ public Set getSupportedAnnotationTypes() { return annotations; } + @Override + public Set getSupportedOptions() { + return Collections.singleton("org.gradle.annotation.processing.aggregating"); + } + @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latestSupported(); @@ -104,10 +109,25 @@ public boolean process(final Set annotations, final Round } final long end = System.nanoTime(); - if (!IS_DEBUG) logger.printMessage(NOTE, (null != tp ? tp.toShortString() : "TypeProcessor FAILED!") + - " takes: " + TimeUnit.NANOSECONDS.toMillis(end - now) + "ms\n"); + if (!IS_DEBUG) { + logger.printMessage(NOTE, (null != tp ? tp.toShortString() : "TypeProcessor FAILED!") + + " takes: " + TimeUnit.NANOSECONDS.toMillis(end - now) + "ms\n"); + } } + // TODO: compose utility class that used for CREATOR's methods + + // /** + // * Represents a function with two arguments. + // * + // * @param the first argument type + // * @param the second argument type + // * @param the result type + // */ + // public interface Func2 { + // R call(T1 t1, T2 t2); + // } + if (failed > 0) { logger.printMessage(ERROR, errors.toString()); } diff --git a/autoproxy-processor/src/main/java/com/olku/processors/CommonClassGenerator.java b/autoproxy-processor/src/main/java/com/olku/processors/CommonClassGenerator.java index c3d7ab0..8561e50 100644 --- a/autoproxy-processor/src/main/java/com/olku/processors/CommonClassGenerator.java +++ b/autoproxy-processor/src/main/java/com/olku/processors/CommonClassGenerator.java @@ -2,8 +2,20 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringDef; +import com.olku.annotations.AutoProxy; +import com.olku.annotations.AutoProxy.Flags; +import com.olku.annotations.AutoProxyClassGenerator; +import com.olku.annotations.RetBool; +import com.olku.annotations.RetNumber; +import com.olku.annotations.Returns; +import com.olku.generators.RetBoolGenerator; +import com.olku.generators.RetNumberGenerator; +import com.olku.generators.ReturnsGenerator; +import com.olku.generators.ReturnsPoet; import com.squareup.javapoet.AnnotationSpec; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.JavaFile; import com.squareup.javapoet.MethodSpec; @@ -16,17 +28,6 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; -import com.olku.annotations.AutoProxy; -import com.olku.annotations.AutoProxy.Flags; -import com.olku.annotations.AutoProxyClassGenerator; -import com.olku.annotations.RetBool; -import com.olku.annotations.RetNumber; -import com.olku.annotations.Returns; -import com.olku.generators.RetBoolGenerator; -import com.olku.generators.RetNumberGenerator; -import com.olku.generators.ReturnsGenerator; -import com.olku.generators.ReturnsPoet; - import java.io.PrintWriter; import java.io.StringWriter; import java.lang.annotation.Annotation; @@ -36,8 +37,11 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiFunction; import javax.annotation.processing.Filer; import javax.lang.model.element.Element; @@ -47,15 +51,17 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeKind; -import rx.functions.Func2; import sun.reflect.annotation.AnnotationParser; import static javax.tools.Diagnostic.Kind.NOTE; /** Common Proxy Class generator. Class designed for inheritance. */ -@SuppressWarnings("WeakerAccess") +@SuppressWarnings({"WeakerAccess", "SameParameterValue", "UnnecessaryLocalVariable"}) public class CommonClassGenerator implements AutoProxyClassGenerator { + /** Enable/Disable debug information. */ public static boolean IS_DEBUG = AutoProxyProcessor.IS_DEBUG; + + //region Constants /** Represents Generic non-NULL value. */ public static final Attribute.Compound GLOBAL_AFTER_CALL = new Attribute.Compound(null, com.sun.tools.javac.util.List.nil()); /** Pre-call / predicate method name. */ @@ -66,7 +72,23 @@ public class CommonClassGenerator implements AutoProxyClassGenerator { protected static final String CREATOR = "create"; /** mapping method that allows to dispatch call to a proper method by it name. */ protected static final String MAPPER = "dispatchByName"; - + /** Annotation type name that is used for constants definition. */ + protected static final String METHODS = "M"; + /** parameter name. */ + protected static final String METHOD_NAME = "methodName"; + /** JavaDoc comment that inform developer how to fix issue with missed interface for old android API's. */ + private static final String BI_FUNCTION_FIX = "Copy this declaration to fix method demands for old APIs:\n\n" + + "
\n" +
+            "package java.util.function;\n" +
+            "\n" +
+            "public interface BiFunction<T, U, R> {\n" +
+            "    R apply(T t, U u);\n" +
+            "}\n" +
+            "
"; + + //endregion + + //region Members /** Data type for processing. */ protected final TypeProcessor type; /** Writer for captured errors. */ @@ -77,71 +99,92 @@ public class CommonClassGenerator implements AutoProxyClassGenerator { protected final AtomicBoolean isAnyAfterCalls = new AtomicBoolean(); /** Lookup of "method name"-to-"arguments line". */ protected final Map mappedCalls = new TreeMap<>(); + /** List of method names. */ + protected final Set knownMethods = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); /** Result file. */ protected JavaFile javaFile; + //endregion + + //region Constructor - /** Main constructor. */ + /** + * Main constructor. + * + * @param type reference on data type processor. + */ public CommonClassGenerator(@NonNull final TypeProcessor type) { this.type = type; superType = TypeName.get(this.type.element.asType()); } + //endregion + //region Code generator + + /** + * {@inheritDoc} + */ @Override public boolean compose(@NonNull final Filer filer) { try { - // is generation flag for forced afterCall set - final boolean hasAfterCalls = ((this.type.annotation.flags() & Flags.AFTER_CALL) == Flags.AFTER_CALL); - isAnyAfterCalls.set(hasAfterCalls); + composeInternal(filer); + } catch (final Throwable ex) { + ex.printStackTrace(new PrintWriter(errors)); + return false; + } - // compose class - final FieldSpec[] members = createMembers(); - final TypeSpec.Builder classSpec = createClass(members); + return true; + } - // constructor and predicate - classSpec.addMethod(createConstructor().build()); - classSpec.addMethod(createPredicate().build()); + /** Compose Plain logic without exception handling wrapper. */ + protected void composeInternal(@NonNull Filer filer) throws Exception { + // is generation flag for forced afterCall set + final boolean hasAfterCalls = ((this.type.annotation.flags() & Flags.AFTER_CALL) == Flags.AFTER_CALL); + isAnyAfterCalls.set(hasAfterCalls); - // auto-generate method proxy calls - createMethods(classSpec); + // compose class + final FieldSpec[] members = createMembers(); + final TypeSpec.Builder classSpec = createClass(members); - // if any after call annotation found in class/methods - if (isAnyAfterCalls.get()) { - classSpec.addMethod(createAfterCall().build()); - } + // constructor and predicate + classSpec.addMethod(createConstructor().build()); + classSpec.addMethod(createPredicate().build()); - // if allowed creator method - if ((this.type.annotation.flags() & Flags.CREATOR) == Flags.CREATOR) { - classSpec.addMethod(createCreator().build()); - } + // auto-generate method proxy calls + createMethods(classSpec); - // if allowed mapper method - if ((this.type.annotation.flags() & Flags.MAPPING) == Flags.MAPPING) { - classSpec.addMethod(createMapper().build()); - } + // if any after call annotation found in class/methods + if (isAnyAfterCalls.get()) { + classSpec.addMethod(createAfterCall().build()); + } - classSpec.addType(createMethodsMapper().build()); + // if allowed creator method + if ((this.type.annotation.flags() & Flags.CREATOR) == Flags.CREATOR) { + classSpec.addMethod(createCreator().build()); + } - classSpec.addOriginatingElement(type.element); + // if allowed mapper method + if ((this.type.annotation.flags() & Flags.MAPPING) == Flags.MAPPING) { + classSpec.addMethod(createMapper().build()); + } - // save class to disk - javaFile = JavaFile.builder(type.packageName.toString(), classSpec.build()).build(); - javaFile.writeTo(filer); + classSpec.addType(createMethodsMapper().build()); - } catch (final Throwable ex) { - ex.printStackTrace(new PrintWriter(errors)); - return false; - } + classSpec.addOriginatingElement(type.element); - return true; + // save class to disk + javaFile = JavaFile.builder(type.packageName.toString(), classSpec.build()).build(); + javaFile.writeTo(filer); } + /** {@inheritDoc} */ @Override @NonNull public String getErrors() { return errors.toString(); } + /** {@inheritDoc} */ @NonNull @Override public String getName() { @@ -150,6 +193,7 @@ public String getName() { return javaFile.toJavaFileObject().getName(); } + /** {@inheritDoc} */ @NonNull @Override public List getOriginating() { @@ -157,7 +201,9 @@ public List getOriginating() { return javaFile.typeSpec.originatingElements; } + //endregion + //region Implementation @NonNull protected FieldSpec[] createMembers() { final List fields = new ArrayList<>(); @@ -217,6 +263,7 @@ private void copyTypeGenericVariables(final TypeSpec.Builder builder) { } /** copy generic parameters for method. */ + @SuppressWarnings("unused") private void copyMethodGenericVariables(final MethodSpec.Builder builder) { if (!(superType instanceof ParameterizedTypeName)) return; @@ -242,7 +289,12 @@ protected MethodSpec.Builder createConstructor() { return builder; } - /** Compose proxy method for provided method definition. */ + /** + * Create methods for provided class. + * + * @param classSpec instance of class specification builder + * @throws Exception give a change to exceptions in depth to deliver the real cause + */ protected void createMethods(@NonNull final TypeSpec.Builder classSpec) throws Exception { // compose methods RuntimeException runtimeError = null; @@ -264,15 +316,26 @@ protected void createMethods(@NonNull final TypeSpec.Builder classSpec) throws E } } - /** Create predicate method declaration. */ + /** + * Create predicate method declaration. + * + * @return instance of the method builder. + */ @NonNull protected MethodSpec.Builder createPredicate() { // TODO: resolve potential name conflict - final MethodSpec.Builder builder = MethodSpec.methodBuilder(PREDICATE); + final String methodName = PREDICATE; + final MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName); builder.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT); builder.returns(boolean.class); - builder.addParameter(String.class, "methodName", Modifier.FINAL); + + final ParameterSpec pMethodNames = ParameterSpec.builder(String.class, METHOD_NAME, Modifier.FINAL) + .addAnnotation(AnnotationSpec.builder(ClassName.bestGuess(METHODS)).build()) + .addAnnotation(AnnotationSpec.builder(NonNull.class).build()) + .build(); + + builder.addParameter(pMethodNames); // varargs builder.varargs(true); @@ -281,19 +344,27 @@ protected MethodSpec.Builder createPredicate() { return builder; } - /** Create afterCall method declaration. */ + /** + * Create afterCall method declaration. + * + * @return instance of the method builder. + */ @NonNull protected MethodSpec.Builder createAfterCall() { final MethodSpec.Builder builder = MethodSpec.methodBuilder(AFTER_CALL); builder.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT); - builder.addTypeVariable(TypeVariableName.get("R", Object.class)); + builder.addTypeVariable(TypeVariableName.get("T", Object.class)); - builder.returns(TypeVariableName.get("R")); + builder.returns(TypeVariableName.get("T")); - builder.addParameter(String.class, "methodName", Modifier.FINAL); + final ParameterSpec pMethodNames = ParameterSpec.builder(String.class, METHOD_NAME, Modifier.FINAL) + .addAnnotation(AnnotationSpec.builder(ClassName.bestGuess(METHODS)).build()) + .addAnnotation(AnnotationSpec.builder(NonNull.class).build()) + .build(); + builder.addParameter(pMethodNames); - builder.addParameter(TypeVariableName.get("R"), "result", Modifier.FINAL); + builder.addParameter(TypeVariableName.get("T"), "result", Modifier.FINAL); return builder; } @@ -302,7 +373,7 @@ protected MethodSpec.Builder createAfterCall() { @NonNull protected MethodSpec.Builder createCreator() { // Output: -// public static UiChange creator(@NonNull final UiChange instance, Func2 action){ +// public static UiChange creator(@NonNull final UiChange instance, Func2 action) { // return new Proxy_UiChange(instance) { // @Override // public boolean predicate(final String methodName, final Object... args) { @@ -322,18 +393,26 @@ protected MethodSpec.Builder createCreator() { builder.returns(superType); builder.addParameter(superType, "instance", Modifier.FINAL); - builder.addParameter(ParameterizedTypeName.get(Func2.class, String.class, Object[].class, Boolean.class), "action", Modifier.FINAL); +// builder.addParameter(ParameterizedTypeName.get(Func2.class, String.class, Object[].class, Boolean.class), "action", Modifier.FINAL); + builder.addParameter(ParameterizedTypeName.get(BiFunction.class, String.class, Object[].class, Boolean.class), "action", Modifier.FINAL); + builder.addJavadoc(BI_FUNCTION_FIX); - builder.addCode("" + - "return new $L(instance) {\n" + + final String afterCallOverride = '\n' + " @Override\n" + - " public boolean predicate(final String methodName, final Object... args) {\n" + - " return action.call(methodName, args);\n" + - " }\n" + (!isAnyAfterCalls.get() ? "" : + " public T afterCall(final String methodName, final T result) {\n" + + " return result;\n" + + " };\n"; + + final String predicateOverride = '\n' + " @Override\n" + - " public R afterCall(final String methodName, final R result) {\n" + - " return result;\n" + - " };\n") + + " public boolean predicate(final String methodName, final Object... args) {\n" + + " return action.apply(methodName, args);\n" + + " }\n"; + + builder.addCode("" + + "return new $L(instance) {\n" + + predicateOverride + + (isAnyAfterCalls.get() ? afterCallOverride : "") + "};\n", "Proxy_" + type.flatClassName); return builder; @@ -344,15 +423,22 @@ protected MethodSpec.Builder createMapper() { final MethodSpec.Builder builder = MethodSpec.methodBuilder(MAPPER); builder.addModifiers(Modifier.PUBLIC); - builder.addTypeVariable(TypeVariableName.get("R", Object.class)); - builder.returns(TypeVariableName.get("R")); + builder.addTypeVariable(TypeVariableName.get("T", Object.class)); + builder.returns(TypeVariableName.get("T")); - builder.addParameter(String.class, "methodName", Modifier.FINAL); + final ParameterSpec pMethodNames = ParameterSpec.builder(String.class, METHOD_NAME, Modifier.FINAL) + .addAnnotation(AnnotationSpec.builder(ClassName.bestGuess(METHODS)).build()) + .addAnnotation(AnnotationSpec.builder(NonNull.class).build()) + .build(); + builder.addParameter(pMethodNames); // varargs builder.varargs(true); builder.addParameter(Object[].class, "args", Modifier.FINAL); + // add boxing/unboxing trick + builder.addCode("final Object result;\n"); + for (final String name : mappedCalls.keySet()) { final Symbol.MethodSymbol ms = mappedCalls.get(name); final Type returnType = ms.getReturnType(); @@ -360,18 +446,18 @@ protected MethodSpec.Builder createMapper() { final String methodName = ms.getSimpleName().toString(); final String params = composeCallParamsFromArray(ms, "args"); - builder.beginControlFlow("if(M.$L.equals(methodName))", name); + builder.beginControlFlow("if($L.$L.equals(methodName))", METHODS, toConstantName(name)); if (hasReturn) { - builder.addStatement("return (R)this.inner.$N($L)", methodName, params); + builder.addStatement("return (T)(result = this.inner.$N($L))", methodName, params); } else { builder.addStatement("this.inner.$N($L)", methodName, params); - builder.addStatement("return (R)null"); + builder.addStatement("return (T)null"); } builder.endControlFlow(); } // fallback - builder.addCode("return (R)null;\n"); + builder.addCode("return (T)null;\n"); return builder; } @@ -379,19 +465,36 @@ protected MethodSpec.Builder createMapper() { /** Compose inner interface with all method names. */ @NonNull protected TypeSpec.Builder createMethodsMapper() { - final TypeSpec.Builder builder = TypeSpec.interfaceBuilder("M") + final TypeSpec.Builder builder = TypeSpec.annotationBuilder(METHODS) .addModifiers(Modifier.PUBLIC); + final List constants = new ArrayList<>(knownMethods.size()); + final StringBuilder format = new StringBuilder().append("{"); + + String prefix = ""; + for (final String name : mappedCalls.keySet()) { final Symbol.MethodSymbol ms = mappedCalls.get(name); final String methodName = ms.getSimpleName().toString(); - builder.addField(FieldSpec.builder(String.class, name) + constants.add(METHODS + "." + toConstantName(name)); + format.append(prefix).append("$L"); + + builder.addField(FieldSpec.builder(String.class, toConstantName(name)) .addJavadoc("{@link #$L($L)}", methodName, composeCallParamsTypes(ms)) .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .initializer("$S", name) .build()); + + prefix = ", "; } + + format.append("}"); // close array + + builder.addAnnotation(AnnotationSpec.builder(StringDef.class) + .addMember("value", format.toString(), constants.toArray()) + .build()); + return builder; } @@ -417,7 +520,8 @@ private String composeCallParamsTypes(@NonNull final Symbol.MethodSymbol ms) { /** Compose extracting of method parameters from vararg array with data type casting. */ @NonNull - private String composeCallParamsFromArray(@NonNull final Symbol.MethodSymbol ms, @NonNull final String arrayName) { + private String composeCallParamsFromArray(@NonNull final Symbol.MethodSymbol ms, + @NonNull final String arrayName) { String delimiter = ""; final StringBuilder result = new StringBuilder(); @@ -475,12 +579,15 @@ protected MethodSpec.Builder createMethod(final Symbol.MethodSymbol ms) throws E // method name with unique signature final String uniqueMethodName = methodName + asMethodNamePart(arguments); mappedCalls.put(uniqueMethodName, ms); + knownMethods.add(uniqueMethodName); + knownMethods.add(methodName); // extract throws mimicThrows(builder, ms); - // expected: if (!predicate( M.translateX_diff, diff )) - builder.beginControlFlow("if (!$L( M.$L$L ))", PREDICATE, uniqueMethodName, + // expected: if (!predicate( Methods.translateX_diff, diff )) + builder.beginControlFlow("if (!$L( $L.$L$L ))", PREDICATE, + METHODS, toConstantName(uniqueMethodName), (arguments.length() == 0 ? "" : ", ") + arguments); // generate default return value @@ -500,7 +607,9 @@ protected MethodSpec.Builder createMethod(final Symbol.MethodSymbol ms) throws E isAnyAfterCalls.set(true); if (hasReturn) { - builder.addStatement("return $L($S, this.inner.$N($L))", AFTER_CALL, uniqueMethodName, methodName, arguments); + builder.addStatement("return $L($L.$L, this.inner.$N($L))", AFTER_CALL, + METHODS, toConstantName(uniqueMethodName), + methodName, arguments); } else { builder.addStatement("this.inner.$N($L)", methodName, arguments); builder.addStatement("$L($S, null)", AFTER_CALL, uniqueMethodName); @@ -510,6 +619,23 @@ protected MethodSpec.Builder createMethod(final Symbol.MethodSymbol ms) throws E return builder; } + /** + * Convert provided name to CONSTANT name. + * + * @param name name of the method that should be converted to suitable constant field name. + * @return name suitable for Constant field declaration + */ + @NonNull + protected String toConstantName(@NonNull final String name) { + return name.toUpperCase(Locale.US); + } + + /** + * Convert array of arguments string as a valid method name. + * + * @param arguments String representation of arguments array. + * @return name suitable for Constant field declaration + */ @NonNull private String asMethodNamePart(@NonNull final StringBuilder arguments) { return ((arguments.length() > 0) ? "_" : "") + // delimiter @@ -594,7 +720,8 @@ protected AutoProxy.Yield extractYield(@Nullable final Attribute.Compound yield) map.put(key, value); } } else { // apply global configuration - if (IS_DEBUG) type.logger.printMessage(NOTE, "used global config: " + this.type.annotation.defaultYield()); + if (IS_DEBUG) + type.logger.printMessage(NOTE, "used global config: " + this.type.annotation.defaultYield()); map.put("value", this.type.annotation.defaultYield()); } @@ -602,8 +729,17 @@ protected AutoProxy.Yield extractYield(@Nullable final Attribute.Compound yield) // new instance return (AutoProxy.Yield) AnnotationParser.annotationForMap(AutoProxy.Yield.class, map); } + //endregion + + //region Helpers - /** Mimic annotations of the method, but exclude @Yield annotation during processing. */ + /** + * Mimic annotations of the method, but exclude @Yield annotation during processing. + * + * @param builder instance of poet builder used for composing method + * @param ms reference on instance of a method information + * @throws Exception method can fail in depth, allow raising of exception on top + */ public static void mimicMethodAnnotations(@NonNull final MethodSpec.Builder builder, @NonNull final Symbol.MethodSymbol ms) throws Exception { if (ms.hasAnnotations()) { @@ -641,7 +777,12 @@ public static Attribute.Compound findYieldMethodAnnotation(@NonNull final Symbol return null; } - /** Compose exceptions throwing signature. */ + /** + * Compose exceptions throwing signature. + * + * @param builder instance of poet method builder + * @param ms reference on source method information + */ public static void mimicThrows(@NonNull final MethodSpec.Builder builder, @NonNull final Symbol.MethodSymbol ms) { for (final Type typeThrown : ms.getThrownTypes()) { @@ -649,7 +790,14 @@ public static void mimicThrows(@NonNull final MethodSpec.Builder builder, } } - /** Compose method parameters that mimic original code. */ + /** + * Compose method parameters that mimic original code. + * + * @param builder reference on poet class instance that used for method composing + * @param ms reference on method signature details, symbols, parameters + * @return reference on string builder with enumerated parameters + * @throws Exception can fail during mimicing signature of the method + */ @NonNull public static StringBuilder mimicParameters(@NonNull final MethodSpec.Builder builder, @NonNull final Symbol.MethodSymbol ms) throws Exception { @@ -689,7 +837,14 @@ public static StringBuilder mimicParameters(@NonNull final MethodSpec.Builder bu return arguments; } - /** Compose annotation spec from mirror the original code. */ + /** + * Compose annotation spec from mirror the original code. + * + * @param am instance of compound attribute that contains class information + * @return instance of annotation builder or NULL + * @throws Exception can potentially raise exception + */ + @SuppressWarnings("RedundantThrows") @Nullable public static AnnotationSpec.Builder mimicAnnotation(@NonNull final Attribute.Compound am) throws Exception { final Class clazz; @@ -697,15 +852,22 @@ public static AnnotationSpec.Builder mimicAnnotation(@NonNull final Attribute.Co try { clazz = extractClass(am); return AnnotationSpec.builder(clazz); - } catch (Throwable ignored) { + } catch (final Throwable ignored) { // Not all annotations can be extracted, annotations marked as @Retention(SOURCE) // cannot be extracted by our code +// if(IS_DEBUG) throw ignored; } return null; } - /** Extract reflection Class<?> information from compound. */ + /** + * Extract reflection Class<?> information from compound. + * + * @param am reference on compound attribute that represents class + * @return found class reflection information + * @throws ClassNotFoundException provided wrong class reference + */ @NonNull public static Class extractClass(@NonNull final Attribute.Compound am) throws ClassNotFoundException { final TypeElement te = (TypeElement) am.getAnnotationType().asElement(); @@ -713,7 +875,13 @@ public static Class extractClass(@NonNull final Attribute.Compound am) throws return extractClass(te); } - /** Extract reflection Class<?> information from type element. */ + /** + * Extract reflection Class<?> information from type element. + * + * @param te reference on type element + * @return found class reflection information + * @throws ClassNotFoundException provided wrong class name. + */ @NonNull public static Class extractClass(@NonNull final TypeElement te) throws ClassNotFoundException { final Name name; @@ -739,4 +907,5 @@ public static Class extractClass(@NonNull final TypeElement te) throws ClassN final String innerFix2 = className.substring(0, dot) + "$" + className.substring(dot + 1); return Class.forName(innerFix2).asSubclass(Annotation.class); } + //endregion } diff --git a/autoproxy-processor/src/main/java/com/olku/processors/TypeProcessor.java b/autoproxy-processor/src/main/java/com/olku/processors/TypeProcessor.java index 5f5d81f..74ebe3d 100644 --- a/autoproxy-processor/src/main/java/com/olku/processors/TypeProcessor.java +++ b/autoproxy-processor/src/main/java/com/olku/processors/TypeProcessor.java @@ -3,13 +3,12 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.olku.annotations.AutoProxy; +import com.olku.annotations.AutoProxyClassGenerator; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Type; -import com.olku.annotations.AutoProxy; -import com.olku.annotations.AutoProxyClassGenerator; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -46,7 +45,12 @@ public class TypeProcessor { final Messager logger; final ArrayList methods; - /** Main constructor. */ + /** + * Main constructor. + * + * @param element reference on code element that we process now. + * @param logger instance of logger for debug information + */ public TypeProcessor(@NonNull final Element element, @NonNull final Messager logger) { this.element = element; this.logger = logger; @@ -54,7 +58,7 @@ public TypeProcessor(@NonNull final Element element, @NonNull final Messager log elementName = element.getSimpleName(); flatClassName = flatName(element); - final PackageElement packageInfo = findPackage(element); + final Symbol.PackageSymbol packageInfo = (Symbol.PackageSymbol) findPackage(element); packageName = packageInfo.getQualifiedName(); elementType = element.asType(); @@ -63,7 +67,13 @@ public TypeProcessor(@NonNull final Element element, @NonNull final Messager log methods = new ArrayList<>(); } - /** Compose flat name for provided class element. Nested classes will be divided by '$' symbol. */ + /** + * Compose flat name for provided class element. Nested classes will be divided by '$' symbol. + * + * @param classInfo reference on class element + * @return flatten name of the class. + */ + @NonNull public String flatName(@NonNull final Element classInfo) { StringBuilder builder = new StringBuilder(); @@ -73,7 +83,7 @@ public String flatName(@NonNull final Element classInfo) { while (null != start && !(start instanceof PackageElement)) { builder.insert(0, start.getSimpleName() + divider); - start = start.getEnclosingElement(); + start = ((Symbol) start).owner; divider = "$"; } @@ -81,13 +91,18 @@ public String flatName(@NonNull final Element classInfo) { return builder.toString(); } - /** Find package name for provided class element. */ + /** + * Find package name for provided class element. + * + * @param classInfo reference on class information. + * @return found package name element or raise runtime error. + */ @NonNull public PackageElement findPackage(@NonNull final Element classInfo) { Element start = classInfo; while (null != start && !(start instanceof PackageElement)) { - start = start.getEnclosingElement(); + start = ((Symbol) start).owner; } if (null != start) @@ -96,7 +111,11 @@ public PackageElement findPackage(@NonNull final Element classInfo) { throw new AssertionError("Cannot find a package name for class. " + classInfo); } - /** Extract methods from all inheritance methods. */ + /** + * Extract methods from all inheritance methods. + * + * @param typeUtils reference on type information. + */ public void extractMethods(@NonNull final Types typeUtils) { final Set elements = inheritance(typeUtils, (TypeElement) element); @@ -184,7 +203,11 @@ public String toShortString() { return "AutoProxy Processing : " + elementType.toString(); } - /** Get new instance of class generator. */ + /** + * Get new instance of class generator. + * + * @return instance of code generator. + */ @NonNull public AutoProxyClassGenerator generator() { // https://area-51.blog/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/ diff --git a/autoproxy-rx-annotations/src/main/java/com/olku/annotations/RetRx.java b/autoproxy-rx-annotations/src/main/java/com/olku/annotations/RetRx.java index 4a12d97..6088219 100644 --- a/autoproxy-rx-annotations/src/main/java/com/olku/annotations/RetRx.java +++ b/autoproxy-rx-annotations/src/main/java/com/olku/annotations/RetRx.java @@ -1,6 +1,6 @@ package com.olku.annotations; -import androidx.annotation.*; +import androidx.annotation.StringDef; import java.lang.annotation.Retention; diff --git a/autoproxy-rx-generators/src/main/java/com/olku/generators/JustRxGenerator.java b/autoproxy-rx-generators/src/main/java/com/olku/generators/JustRxGenerator.java index 2e26647..153cf8f 100644 --- a/autoproxy-rx-generators/src/main/java/com/olku/generators/JustRxGenerator.java +++ b/autoproxy-rx-generators/src/main/java/com/olku/generators/JustRxGenerator.java @@ -1,6 +1,7 @@ package com.olku.generators; -import androidx.annotation.*; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; @@ -13,7 +14,7 @@ public static JustRxGenerator getInstance() { } public boolean compose(@NonNull final Type returnType, - final String type, + @Nullable final String type, @NonNull final MethodSpec.Builder builder) { if (null != type && type.length() > 0) { builder.addStatement("return $T.just($L)", rx.Observable.class, type); @@ -24,6 +25,6 @@ public boolean compose(@NonNull final Type returnType, } private static final class Singleton { - static final JustRxGenerator INSTANCE = new JustRxGenerator(); + /* package */ static final JustRxGenerator INSTANCE = new JustRxGenerator(); } } diff --git a/autoproxy-rx-generators/src/main/java/com/olku/generators/RetRxGenerator.java b/autoproxy-rx-generators/src/main/java/com/olku/generators/RetRxGenerator.java index 4c0c5c4..a2f2719 100644 --- a/autoproxy-rx-generators/src/main/java/com/olku/generators/RetRxGenerator.java +++ b/autoproxy-rx-generators/src/main/java/com/olku/generators/RetRxGenerator.java @@ -1,12 +1,12 @@ package com.olku.generators; -import androidx.annotation.*; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.olku.annotations.RetRx; import com.squareup.javapoet.MethodSpec; import com.sun.tools.javac.code.Type; -import com.olku.annotations.RetRx; - /** RxJava return values generator. */ public class RetRxGenerator implements ReturnsPoet { @NonNull @@ -15,7 +15,7 @@ public static RetRxGenerator getInstance() { } public boolean compose(@NonNull final Type returnType, - @RetRx final String type, + @Nullable @RetRx final String type, @NonNull final MethodSpec.Builder builder) { if (RetRx.EMPTY.equals(type)) { // rx.Observable.empty(); @@ -37,6 +37,6 @@ public boolean compose(@NonNull final Type returnType, } private static final class Singleton { - static final RetRxGenerator INSTANCE = new RetRxGenerator(); + /* package */ static final RetRxGenerator INSTANCE = new RetRxGenerator(); } } diff --git a/gradle.properties b/gradle.properties index 32947e4..82bf590 100644 --- a/gradle.properties +++ b/gradle.properties @@ -57,7 +57,7 @@ GOOGLE_PLAY_VERSION=+ # WARNING! v1.3.50 has a bug in `kapt` # KOTLIN_VERSION=1.3.72 -ANDROID_KTX_VERSION=1.2.0 +ANDROID_KTX_VERSION=1.3.0 # ## Allow TEST configurations in solution, ## increase perfromance of IDE when switched OFF diff --git a/sample/src/main/java/com/olku/autoproxy/sample/KotlinAbstractMvpView.kt b/sample/src/main/java/com/olku/autoproxy/sample/KotlinAbstractMvpView.kt index dd1ba0b..d6b660d 100644 --- a/sample/src/main/java/com/olku/autoproxy/sample/KotlinAbstractMvpView.kt +++ b/sample/src/main/java/com/olku/autoproxy/sample/KotlinAbstractMvpView.kt @@ -6,37 +6,37 @@ import com.olku.generators.JustRxGenerator import com.olku.generators.RetRxGenerator import rx.Observable -@AutoProxy +@AutoProxy(flags = AutoProxy.Flags.ALL) abstract class KotlinAbstractMvpView { - /** Returns NULL if predicate returns False. */ + /** Returns NULL if predicate returns False. */ @AutoProxy.Yield(Returns.NULL) abstract fun dummyCall(): Observable? - /** Returns Observable.empty() */ + /** Returns Observable.empty() */ @AutoProxy.Yield(adapter = RetRxGenerator::class, value = RetRx.EMPTY) abstract fun dummyCall(generic: List?): Observable? - /** Throws exception on False result from predicate. */ + /** Throws exception on False result from predicate. */ @AutoProxy.Yield abstract fun dummyCall(message: String?, args: List?): Observable? - /** Returns Observable.error(...) on False result from predicate. */ + /** Returns Observable.error(...) on False result from predicate. */ @AutoProxy.Yield(adapter = RetRxGenerator::class, value = RetRx.ERROR) abstract fun dummyCall(message: String?, vararg args: Any?): Observable? - /** Returns ZERO on False result from predicate. */ + /** Returns ZERO on False result from predicate. */ @AutoProxy.Yield(RetNumber.ZERO) abstract fun numericCall(): Double - /** Returns FALSE on False result from predicate. */ + /** Returns FALSE on False result from predicate. */ @AutoProxy.Yield(RetBool.FALSE) abstract fun booleanCall(): Boolean - /** Does direct call independent to predicate result. */ + /** Does direct call independent to predicate result. */ @AutoProxy.Yield(Returns.DIRECT) abstract fun dispatchDeepLink(deepLink: Uri): Boolean - /** Returns Observable.just(true) on False result from predicate. */ + /** Returns Observable.just(true) on False result from predicate. */ @AutoProxy.Yield(adapter = JustRxGenerator::class, value = "true") abstract fun startHearthAnimation(): Observable? diff --git a/sample/src/main/java/com/olku/autoproxy/sample/MainActivity.java b/sample/src/main/java/com/olku/autoproxy/sample/MainActivity.java index 3a08bd9..ec5fa49 100644 --- a/sample/src/main/java/com/olku/autoproxy/sample/MainActivity.java +++ b/sample/src/main/java/com/olku/autoproxy/sample/MainActivity.java @@ -6,8 +6,6 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; -import org.jetbrains.annotations.NotNull; - import java.util.List; import rx.Observable; @@ -25,7 +23,7 @@ protected void onCreate(Bundle savedInstanceState) { public MvpView getProxy() { return new Proxy_MvpView(this) { @Override - public boolean predicate(@Methods @NotNull String methodName, Object... args) { + public boolean predicate(@M @NonNull String methodName, Object... args) { return !isFinishing(); } }; diff --git a/sample/src/main/java/com/olku/autoproxy/sample/ParkingArea.java b/sample/src/main/java/com/olku/autoproxy/sample/ParkingArea.java index e1a5e57..a933186 100644 --- a/sample/src/main/java/com/olku/autoproxy/sample/ParkingArea.java +++ b/sample/src/main/java/com/olku/autoproxy/sample/ParkingArea.java @@ -5,8 +5,6 @@ import com.google.auto.value.AutoValue; import com.olku.annotations.AutoProxy; -import org.jetbrains.annotations.NotNull; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -31,14 +29,14 @@ public abstract class ParkingArea { public ParkingArea.Builder toBuilder() { return new Proxy_ParkingArea$Builder(toBuilderInner()) { @Override - public boolean predicate(@NotNull final String methodName, final Object... args) { + public boolean predicate(@NonNull final String methodName, final Object... args) { return true; /* allow all calls */ } @Override - public R afterCall(@NotNull @Methods final String methodName, final R result) { + public R afterCall(@NonNull @M final String methodName, final R result) { // copy runtime fields from instance after clone creation - if (Methods.BUILD.equals(methodName) && result instanceof ParkingArea) { + if (M.BUILD.equals(methodName) && result instanceof ParkingArea) { ((ParkingArea) result).runtimeData = runtimeData; return result; }