From 2d12358a25e814b91196640c8442e148214b26e5 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 8 May 2017 17:35:09 -0400 Subject: [PATCH 01/31] Adding kotlin module to aid in building out kotlin support --- build.gradle | 2 + sample-java-model/build.gradle | 4 +- sample-kotlin-model/.gitignore | 1 + sample-kotlin-model/build.gradle | 60 +++++++++++++++++++ sample-kotlin-model/proguard-rules.pro | 25 ++++++++ .../src/main/AndroidManifest.xml | 10 ++++ .../dummy/sample_kotlin/KotlinSamples.kt | 13 ++++ .../com/vimeo/dummy/sample_kotlin/Test.kt | 11 ++++ .../src/main/res/values/strings.xml | 3 + .../dummy/sample_kotlin/KotlinSamplesTest.kt | 16 +++++ .../com/vimeo/dummy/sample_kotlin/Utils.kt | 54 +++++++++++++++++ sample-model/build.gradle | 1 + sample/build.gradle | 5 +- settings.gradle | 2 +- stag-library-compiler/build.gradle | 2 +- 15 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 sample-kotlin-model/.gitignore create mode 100644 sample-kotlin-model/build.gradle create mode 100644 sample-kotlin-model/proguard-rules.pro create mode 100644 sample-kotlin-model/src/main/AndroidManifest.xml create mode 100644 sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt create mode 100644 sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt create mode 100644 sample-kotlin-model/src/main/res/values/strings.xml create mode 100644 sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt create mode 100644 sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/Utils.kt diff --git a/build.gradle b/build.gradle index c458d3cc..465a7e2f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { + ext.kotlin_version = '1.1.2-3' repositories { jcenter() mavenCentral() @@ -7,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/sample-java-model/build.gradle b/sample-java-model/build.gradle index 2d7160cd..44efac19 100644 --- a/sample-java-model/build.gradle +++ b/sample-java-model/build.gradle @@ -1,9 +1,11 @@ apply plugin: 'java' dependencies { - compile project(':stag-library') compile 'com.google.code.gson:gson:2.8.0' + + compile project(':stag-library') compileOnly project(':stag-library-compiler') + testCompile 'junit:junit:4.12' } diff --git a/sample-kotlin-model/.gitignore b/sample-kotlin-model/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/sample-kotlin-model/.gitignore @@ -0,0 +1 @@ +/build diff --git a/sample-kotlin-model/build.gradle b/sample-kotlin-model/build.gradle new file mode 100644 index 00000000..09009959 --- /dev/null +++ b/sample-kotlin-model/build.gradle @@ -0,0 +1,60 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 25 + buildToolsVersion "25.0.2" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + javaCompileOptions { + annotationProcessorOptions { + arguments = [ + stagGeneratedPackageName: 'com.vimeo.sample_kotlin.stag.generated', + stagDebug : 'true' + ] + } + } + + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + test.java.srcDirs += 'src/test/kotlin' + } +} + +kapt { + correctErrorTypes = true +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + testCompile 'junit:junit:4.12' + + compile project(':stag-library') + kapt project(':stag-library-compiler') + + compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" +} + +repositories { + mavenCentral() +} diff --git a/sample-kotlin-model/proguard-rules.pro b/sample-kotlin-model/proguard-rules.pro new file mode 100644 index 00000000..dfa36c56 --- /dev/null +++ b/sample-kotlin-model/proguard-rules.pro @@ -0,0 +1,25 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/restainoa/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/sample-kotlin-model/src/main/AndroidManifest.xml b/sample-kotlin-model/src/main/AndroidManifest.xml new file mode 100644 index 00000000..279ec6ac --- /dev/null +++ b/sample-kotlin-model/src/main/AndroidManifest.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt new file mode 100644 index 00000000..931f31bd --- /dev/null +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt @@ -0,0 +1,13 @@ +package com.vimeo.dummy.sample_kotlin + +import com.vimeo.stag.UseStag + +/** + * Created by restainoa on 5/8/17. + */ +@UseStag +class KotlinSamples { + var stringField: String? = null + + var testField: Any? = null +} \ No newline at end of file diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt new file mode 100644 index 00000000..27a04230 --- /dev/null +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt @@ -0,0 +1,11 @@ +package com.vimeo.dummy.sample_kotlin + +/** + * Created by restainoa on 5/8/17. + */ +class Test + +fun accessTest() { + val kot : KotlinSamples = KotlinSamples() + kot.stringField = "Test" +} \ No newline at end of file diff --git a/sample-kotlin-model/src/main/res/values/strings.xml b/sample-kotlin-model/src/main/res/values/strings.xml new file mode 100644 index 00000000..7645305a --- /dev/null +++ b/sample-kotlin-model/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + sample-kotlin + diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt new file mode 100644 index 00000000..cbdb1e42 --- /dev/null +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt @@ -0,0 +1,16 @@ +package com.vimeo.dummy.sample_kotlin + +import org.junit.Test + +/** + * Unit test for KotlinSamples + * + * Created by restainoa on 5/8/17. + */ +class KotlinSamplesTest { + + @Test fun verifyTypeAdapterGenerated() { + Utils.verifyTypeAdapterGeneration(KotlinSamples::class) + } + +} \ No newline at end of file diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/Utils.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/Utils.kt new file mode 100644 index 00000000..5ebce367 --- /dev/null +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/Utils.kt @@ -0,0 +1,54 @@ +package com.vimeo.dummy.sample_kotlin + +import com.google.gson.Gson +import com.google.gson.TypeAdapter +import com.google.gson.reflect.TypeToken +import com.vimeo.sample_kotlin.stag.generated.Stag +import junit.framework.Assert +import kotlin.reflect.KClass + +/** + * Created by restainoa on 5/8/17. + */ +class Utils { + + companion object Utils { + + private fun getTypeAdapter(clazz: KClass): TypeAdapter? { + val gson = Gson() + val factory = Stag.Factory() + val innerModelType = TypeToken.get(clazz.java) + return factory.create(gson, innerModelType) + } + + /** + * Verifies that a TypeAdapter was generated for the specified class. + + * @param clazz the class to check. + * * + * @param the type of the class, used internally. + * * + * @throws Exception throws an exception if an adapter was not generated. + */ + @Throws(Exception::class) + fun verifyTypeAdapterGeneration(clazz: KClass) { + val typeAdapter = getTypeAdapter(clazz) + Assert.assertNotNull("Type adapter should have been generated by Stag", typeAdapter) + } + + /** + * Verifies that a TypeAdapter was NOT generated for the specified class. + + * @param clazz the class to check. + * * + * @param the type of the class, used internally. + * * + * @throws Exception throws an exception if an adapter was generated. + */ + @Throws(Exception::class) + fun verifyNoTypeAdapterGeneration(clazz: KClass) { + val typeAdapter = getTypeAdapter(clazz) + Assert.assertNull("Type adapter should not have been generated by Stag", typeAdapter) + } + } +} \ No newline at end of file diff --git a/sample-model/build.gradle b/sample-model/build.gradle index 34d9e90b..eec6f0e7 100644 --- a/sample-model/build.gradle +++ b/sample-model/build.gradle @@ -42,6 +42,7 @@ dependencies { compile project(':stag-library') annotationProcessor project(':stag-library-compiler') + compile 'com.google.code.gson:gson:2.8.0' } diff --git a/sample/build.gradle b/sample/build.gradle index 0c357de9..cebc197f 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -43,10 +43,13 @@ dependencies { testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:25.3.1' - compile project(':stag-library') compile project(':sample-model') compile project(':sample-java-model') + compile project(':sample-kotlin-model') + + compile project(':stag-library') annotationProcessor project(':stag-library-compiler') + compile 'com.google.code.gson:gson:2.8.0' } diff --git a/settings.gradle b/settings.gradle index 48c96603..9d7ce27f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model' +include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model', ':sample-kotlin-model' diff --git a/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index 14f839e0..1ce1a4c5 100644 --- a/stag-library-compiler/build.gradle +++ b/stag-library-compiler/build.gradle @@ -18,7 +18,7 @@ dependencies { compile 'com.google.code.gson:gson:2.8.0' compile 'com.squareup:javapoet:1.8.0' compile 'com.intellij:annotations:12.0@jar' - compile 'com.google.auto.service:auto-service:1.0-rc2' + compile 'com.google.auto.service:auto-service:1.0-rc3' } test { From 87a948e8fc10fd16bd8c44c16a1e0ebd9a232691 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 8 May 2017 17:46:20 -0400 Subject: [PATCH 02/31] Report a warning if we are overriding member variables --- .../stag/processor/generators/model/AnnotatedClass.java | 6 +++--- .../com/vimeo/stag/processor/utils/MessagerUtils.java | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index fc41e93a..eb802e1a 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -52,7 +52,7 @@ public class AnnotatedClass { @NotNull private final Element mElement; @NotNull private final LinkedHashMap mMemberVariables; - AnnotatedClass(@NotNull Element element){ + AnnotatedClass(@NotNull Element element) { this(element, null); } @@ -103,8 +103,8 @@ private void addMemberVariable(@NotNull Element element, @NotNull TypeMirror typ Element previousElement = variableNames.put(element.getSimpleName().toString(), element); if (null != previousElement) { mMemberVariables.remove(previousElement); - DebugLog.log(TAG, "\t\tIgnoring inherited Member variable with the same variable name - " + - previousElement.asType().toString()); + MessagerUtils.reportWarning("Ignoring inherited Member variable with the same variable name in class" + + element.toString() + ", with variable name " + previousElement.asType().toString()); } mMemberVariables.put(element, typeMirror); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java index 48c69d28..975d9a66 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java @@ -28,7 +28,7 @@ import javax.annotation.processing.Messager; import javax.lang.model.element.Element; -import javax.tools.Diagnostic; +import javax.tools.Diagnostic.Kind; public final class MessagerUtils { @@ -50,7 +50,11 @@ private static Messager getMessager() { } public static void reportError(@NotNull String message, @NotNull Element element) { - getMessager().printMessage(Diagnostic.Kind.ERROR, message, element); + getMessager().printMessage(Kind.ERROR, message, element); + } + + public static void reportWarning(@NotNull String message) { + getMessager().printMessage(Kind.MANDATORY_WARNING, message); } } From dd5d1baa559278013ea3a1b76ea134b5e8fd3a1c Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 9 May 2017 07:54:12 -0400 Subject: [PATCH 03/31] Groundwork for setter/getter suppport Adding accessor classes to encapsulate field access --- .../model/accessor/DirectFieldAccessor.java | 31 +++ .../model/accessor/FieldAccessor.java | 182 ++++++++++++++++++ .../model/accessor/MethodFieldAccessor.java | 113 +++++++++++ 3 files changed, 326 insertions(+) create mode 100644 stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/DirectFieldAccessor.java create mode 100644 stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java create mode 100644 stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/DirectFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/DirectFieldAccessor.java new file mode 100644 index 00000000..55d97651 --- /dev/null +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/DirectFieldAccessor.java @@ -0,0 +1,31 @@ +package com.vimeo.stag.processor.generators.model.accessor; + +import org.jetbrains.annotations.NotNull; + +import javax.lang.model.element.VariableElement; + +/** + * A variation of the {@link FieldAccessor} + * which populates the field by directly + * accessing the field. + *

+ * Created by restainoa on 5/8/17. + */ +public class DirectFieldAccessor extends FieldAccessor { + + public DirectFieldAccessor(@NotNull VariableElement element) { + super(element); + } + + @NotNull + @Override + public String createGetterCode() { + return getVariableName(); + } + + @NotNull + @Override + public String createSetterCode(@NotNull String assignment) { + return getVariableName() + " = " + assignment; + } +} diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java new file mode 100644 index 00000000..cb6f3410 --- /dev/null +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java @@ -0,0 +1,182 @@ +package com.vimeo.stag.processor.generators.model.accessor; + +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.vimeo.stag.processor.utils.Preconditions; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.MirroredTypeException; +import javax.lang.model.type.TypeMirror; + +/** + * A class representing a field that must be + * populated from JSON. + *

+ * Created by restainoa on 5/8/17. + */ +public abstract class FieldAccessor { + + @NotNull + private final VariableElement mVariableElement; + + public FieldAccessor(@NotNull VariableElement element) { + mVariableElement = element; + } + + /** + * Create the code that reads from the field. + * In the format: + *

+ * + * object.{getterCode}; + * + * + * @return a not null string that represents + * code that can be used to access the field. + */ + @NotNull + public abstract String createGetterCode(); + + /** + * Create the code that assigns the field + * to the assigned code. In the format: + *

+ * + * object.{setterCode}; + * + * + * @param assignment the code that this field should + * be assigned to. + * @return a not null string that represents code + * that can be used to assign the field. + */ + @NotNull + public abstract String createSetterCode(@NotNull String assignment); + + /** + * The variable name of this field. + * + * @return the variable name of this field. + */ + @NotNull + protected final String getVariableName() { + return mVariableElement.getSimpleName().toString(); + } + + /** + * Determines if this field was marked with + * a not null annotation that requires the + * field to be populated. + * + * @return true if the field was marked not null, + * false otherwise. + */ + public final boolean requireNotNull() { + for (AnnotationMirror annotationMirror : mVariableElement.getAnnotationMirrors()) { + switch (annotationMirror.toString()) { + case "@javax.validation.constraints.NotNull": + case "@edu.umd.cs.findbugs.annotations.NonNull": + case "@javax.annotation.Nonnull": + case "@lombok.NonNull": + case "@org.eclipse.jdt.annotation.NonNull": + case "@org.jetbrains.annotations.NotNull": + case "@android.support.annotation.NonNull": + return true; + } + } + + return false; + } + + /** + * If the field was annotated with the + * {@link JsonAdapter} annotation, this + * method will get the class held by that + * annotation. + * + * @return the adapter that the field was annotated with. + */ + @Nullable + public final TypeMirror getJsonAdapterType() { + JsonAdapter annotation = mVariableElement.getAnnotation(JsonAdapter.class); + + if (annotation != null) { + // Using this trick to get the class type + // https://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/ + try { + annotation.value(); + } catch (MirroredTypeException mte) { + return mte.getTypeMirror(); + } + } + + return null; + } + + /** + * If {@link #getJsonAdapterType()} returns + * a type, this method will determine if that + * adapter is null safe or not. Otherwise, this + * method will throw an exception. + * + * @return true if the adapter is null safe, false otherwise. + */ + public final boolean isJsonAdapterNullSafe() { + JsonAdapter annotation = mVariableElement.getAnnotation(JsonAdapter.class); + + Preconditions.checkNotNull(annotation); + + return annotation.nullSafe(); + } + + /** + * Returns the accessor in its + * {@link TypeMirror} form. + * + * @return the {@link TypeMirror} associated + * with this accessor. + */ + @NotNull + public final TypeMirror asType() { + return mVariableElement.asType(); + } + + /** + * Gets the JSON name for the element the name passed to + * {@link SerializedName} will be used. If the element is + * not annotated with {@link SerializedName}, the variable + * name is used. + * + * @return a non null string to use as the JSON key. + */ + @NotNull + public final String getJsonName() { + + String name = null != mVariableElement.getAnnotation(SerializedName.class) ? + mVariableElement.getAnnotation(SerializedName.class).value() : + null; + + if (null == name || name.isEmpty()) { + name = mVariableElement.getSimpleName().toString(); + } + return name; + } + + /** + * Returns the alternate names for the {@link Element}. + * + * @return an array of alternate names, or null if there are none. + */ + @Nullable + public final String[] getAlternateJsonNames() { + return null != mVariableElement.getAnnotation(SerializedName.class) ? + mVariableElement.getAnnotation(SerializedName.class).alternate() : + null; + } + +} diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java new file mode 100644 index 00000000..8e7f4e74 --- /dev/null +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java @@ -0,0 +1,113 @@ +package com.vimeo.stag.processor.generators.model.accessor; + +import com.vimeo.stag.processor.utils.MessagerUtils; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeKind; + +/** + * A variation of the {@link FieldAccessor} + * which populates the field by accessing + * it through getters and setters. + *

+ * Created by restainoa on 5/8/17. + */ +public class MethodFieldAccessor extends FieldAccessor { + + @NotNull private final String mSetterName; + @NotNull private final String mGetterName; + + public MethodFieldAccessor(@NotNull VariableElement element) { + super(element); + + mSetterName = findSetterMethodName(element); + mGetterName = findGetterMethodName(element); + } + + @NotNull + @Override + public String createGetterCode() { + return mGetterName + "()"; + } + + @NotNull + @Override + public String createSetterCode(@NotNull String assignment) { + return mSetterName + '(' + assignment + ')'; + } + + @NotNull + private static List getSiblingMethods(@NotNull VariableElement variableElement) { + List methodElements = new ArrayList<>(); + List otherElements = variableElement.getEnclosingElement().getEnclosedElements(); + + MessagerUtils.reportWarning("Looking for setter and getter"); + + for (Element element : otherElements) { + if (element.getKind() == ElementKind.METHOD && element instanceof ExecutableElement) { + methodElements.add((ExecutableElement) element); + } + } + + return methodElements; + } + + @NotNull + private static String findSetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { + MessagerUtils.reportWarning("Looking for setter and getter"); + + for (ExecutableElement method : getSiblingMethods(variableElement)) { + + List parameters = method.getParameters(); + + if (method.getReturnType().getKind() == TypeKind.VOID && + parameters.size() == 1 && + parameters.get(0).asType().equals(variableElement.asType()) && + method.getSimpleName().toString().equals("set" + getVariableNameAsMethodName(variableElement))) { + MessagerUtils.reportWarning("Found setter"); + + return method.getSimpleName().toString(); + } + + } + + throw new UnsupportedOperationException("Unable to find setter for variable"); + } + + @NotNull + private static String findGetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { + MessagerUtils.reportWarning("Looking for setter and getter"); + + for (ExecutableElement method : getSiblingMethods(variableElement)) { + + if (method.getReturnType().equals(variableElement.asType()) && + method.getParameters().isEmpty() && + method.getSimpleName().toString().equals("get" + getVariableNameAsMethodName(variableElement))) { + + MessagerUtils.reportWarning("Found getter"); + + return method.getSimpleName().toString(); + } + + } + + throw new UnsupportedOperationException("Unable to find getter for variable"); + } + + @NotNull + private static String getVariableNameAsMethodName(@NotNull VariableElement variableElement) { + // if hungarian notation, need different logic + String variableName = variableElement.getSimpleName().toString(); + + return Character.toUpperCase(variableName.charAt(0)) + variableName.substring(1, variableName.length()); + } + +} From 8f122c9bddf2546556304bcfc57637592b31af9b Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 9 May 2017 15:38:06 -0400 Subject: [PATCH 04/31] Adding logInfo method to messagerutils --- .../java/com/vimeo/stag/processor/utils/MessagerUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java index 975d9a66..ba4aa4ab 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/MessagerUtils.java @@ -57,4 +57,8 @@ public static void reportWarning(@NotNull String message) { getMessager().printMessage(Kind.MANDATORY_WARNING, message); } + public static void logInfo(@NotNull String message) { + getMessager().printMessage(Kind.NOTE, message); + } + } From 9ae3941535561dd59bc5a63100af8344bb520980 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 9 May 2017 15:49:06 -0400 Subject: [PATCH 05/31] Refactoring some TypeUtils methods to make return types and parameters more clear Temporarily disabling the kotlin module to check build --- sample/build.gradle | 2 +- settings.gradle | 2 +- .../generators/model/AnnotatedClass.java | 7 ++++--- .../generators/model/SupportedTypesModel.java | 4 ++-- .../model/accessor/MethodFieldAccessor.java | 10 ++++----- .../stag/processor/utils/ElementUtils.java | 4 ++-- .../vimeo/stag/processor/utils/TypeUtils.java | 21 +++++++++---------- .../java/com/vimeo/stag/processor/Utils.java | 3 ++- 8 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sample/build.gradle b/sample/build.gradle index cebc197f..01dc6f2e 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -45,7 +45,7 @@ dependencies { compile project(':sample-model') compile project(':sample-java-model') - compile project(':sample-kotlin-model') +// compile project(':sample-kotlin-model') compile project(':stag-library') annotationProcessor project(':stag-library-compiler') diff --git a/settings.gradle b/settings.gradle index 9d7ce27f..04f50771 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model', ':sample-kotlin-model' +include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model'//, ':sample-kotlin-model' diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index eb802e1a..79730f85 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -41,6 +41,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; @@ -52,11 +53,11 @@ public class AnnotatedClass { @NotNull private final Element mElement; @NotNull private final LinkedHashMap mMemberVariables; - AnnotatedClass(@NotNull Element element) { + AnnotatedClass(@NotNull TypeElement element) { this(element, null); } - AnnotatedClass(@NotNull Element element, @Nullable FieldOption childFieldOption) { + AnnotatedClass(@NotNull TypeElement element, @Nullable FieldOption childFieldOption) { mType = element.asType(); mElement = element; Map variableNames = new HashMap<>(element.getEnclosedElements().size()); @@ -103,7 +104,7 @@ private void addMemberVariable(@NotNull Element element, @NotNull TypeMirror typ Element previousElement = variableNames.put(element.getSimpleName().toString(), element); if (null != previousElement) { mMemberVariables.remove(previousElement); - MessagerUtils.reportWarning("Ignoring inherited Member variable with the same variable name in class" + + MessagerUtils.logInfo("Ignoring inherited Member variable with the same variable name in class" + element.toString() + ", with variable name " + previousElement.asType().toString()); } mMemberVariables.put(element, typeMirror); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java index e6837bdc..e4e9888e 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java @@ -124,7 +124,7 @@ public AnnotatedClass addToKnownInheritedType(@NotNull TypeMirror type, @Nullabl if (null == model) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(TypeUtils.getElementFromSupportedTypeMirror(type), childFieldOption); + model = new AnnotatedClass(TypeUtils.safeTypeMirrorToTypeElement(type), childFieldOption); mKnownInheritedTypesMap.put(outerClassType, model); } } @@ -148,7 +148,7 @@ public AnnotatedClass addSupportedType(@NotNull TypeMirror type) { if (model == null) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(TypeUtils.getElementFromSupportedTypeMirror(type)); + model = new AnnotatedClass(TypeUtils.safeTypeMirrorToTypeElement(type)); } addSupportedType(model); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java index 8e7f4e74..c8f7e574 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java @@ -49,7 +49,7 @@ private static List getSiblingMethods(@NotNull VariableElemen List methodElements = new ArrayList<>(); List otherElements = variableElement.getEnclosingElement().getEnclosedElements(); - MessagerUtils.reportWarning("Looking for setter and getter"); + MessagerUtils.logInfo("Looking for setter and getter"); for (Element element : otherElements) { if (element.getKind() == ElementKind.METHOD && element instanceof ExecutableElement) { @@ -62,7 +62,7 @@ private static List getSiblingMethods(@NotNull VariableElemen @NotNull private static String findSetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { - MessagerUtils.reportWarning("Looking for setter and getter"); + MessagerUtils.logInfo("Looking for setter and getter"); for (ExecutableElement method : getSiblingMethods(variableElement)) { @@ -72,7 +72,7 @@ private static String findSetterMethodName(@NotNull VariableElement variableElem parameters.size() == 1 && parameters.get(0).asType().equals(variableElement.asType()) && method.getSimpleName().toString().equals("set" + getVariableNameAsMethodName(variableElement))) { - MessagerUtils.reportWarning("Found setter"); + MessagerUtils.logInfo("Found setter"); return method.getSimpleName().toString(); } @@ -84,7 +84,7 @@ private static String findSetterMethodName(@NotNull VariableElement variableElem @NotNull private static String findGetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { - MessagerUtils.reportWarning("Looking for setter and getter"); + MessagerUtils.logInfo("Looking for setter and getter"); for (ExecutableElement method : getSiblingMethods(variableElement)) { @@ -92,7 +92,7 @@ private static String findGetterMethodName(@NotNull VariableElement variableElem method.getParameters().isEmpty() && method.getSimpleName().toString().equals("get" + getVariableNameAsMethodName(variableElement))) { - MessagerUtils.reportWarning("Found getter"); + MessagerUtils.logInfo("Found getter"); return method.getSimpleName().toString(); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java index 7f6fdf5f..d9e4783e 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java @@ -71,7 +71,7 @@ public static TypeElement getTypeElementFromQualifiedName(@NotNull String qualif @NotNull public static String getPackage(@NotNull TypeMirror type) { - Element element = TypeUtils.getElementFromTypeMirror(type); + Element element = TypeUtils.unsafeTypeMirrorToTypeElement(type); PackageElement packageElement = getUtils().getPackageOf(element); return packageElement.getQualifiedName().toString(); } @@ -109,7 +109,7 @@ public static boolean isSupportedElementKind(@Nullable Element element) { @Nullable public static ExecutableElement getFirstConstructor(@Nullable TypeMirror typeMirror) { - Element typeElement = typeMirror != null ? TypeUtils.getElementFromTypeMirror(typeMirror) : null; + Element typeElement = typeMirror != null ? TypeUtils.unsafeTypeMirrorToTypeElement(typeMirror) : null; if (typeElement != null) { for (Element element : typeElement.getEnclosedElements()) { if (element instanceof ExecutableElement) { diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java index 81aa6e45..fa580e54 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java @@ -274,9 +274,8 @@ public static boolean containsTypeVarParams(@NotNull TypeMirror typeMirror) { * inherits from Object or Enum. */ @Nullable - public static TypeMirror getInheritedType(@Nullable Element element) { - TypeElement typeElement = (TypeElement) element; - TypeMirror typeMirror = typeElement != null ? typeElement.getSuperclass() : null; + public static TypeMirror getInheritedType(@Nullable TypeElement element) { + TypeMirror typeMirror = element != null ? element.getSuperclass() : null; String className = typeMirror != null ? getClassNameFromTypeMirror(typeMirror) : null; if (!Object.class.getName().equals(className) && !Enum.class.getName().equals(className)) { return typeMirror; @@ -557,12 +556,12 @@ public static String getClassNameFromTypeMirror(@NotNull TypeMirror typeMirror) * types. As a result it will guarantee non-null result values. * * @param typeMirror type mirror to convert - * @return element representation of the type mirror + * @return TypeElement representation of the type mirror */ @NotNull - public static Element getElementFromSupportedTypeMirror(@NotNull TypeMirror typeMirror) { - Element element = getElementFromTypeMirror(typeMirror); - // asElement may return null but not in the scenarios we are specifically using it for + public static TypeElement safeTypeMirrorToTypeElement(@NotNull TypeMirror typeMirror) { + TypeElement element = unsafeTypeMirrorToTypeElement(typeMirror); + // unsafeTypeMirrorToTypeElement may return null but not in the scenarios we are specifically using it for if (element == null) { throw new IllegalStateException("Supported type could not be converted into an Element"); } @@ -572,12 +571,12 @@ public static Element getElementFromSupportedTypeMirror(@NotNull TypeMirror type /** * Convert the provided {@link TypeMirror} into an {@link Element} instance. * - * @param typeMirror type mirror to convert - * @return element representation of the type mirror + * @param typeMirror TypeMirror to convert + * @return TypeElement representation of the TypeMirror */ @Nullable - public static Element getElementFromTypeMirror(@NotNull TypeMirror typeMirror) { - return getUtils().asElement(typeMirror); + public static TypeElement unsafeTypeMirrorToTypeElement(@NotNull TypeMirror typeMirror) { + return (TypeElement) getUtils().asElement(typeMirror); } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java index b1c30bca..091c849c 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java @@ -34,6 +34,7 @@ import java.util.List; import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; @@ -72,7 +73,7 @@ public static void testZeroArgumentConstructorFinalClass(Class clazz) thr } @Nullable - public static Element getElementFromClass(@NotNull Class clazz) { + public static TypeElement getElementFromClass(@NotNull Class clazz) { return elements.getTypeElement(clazz.getName()); } From 72a8e6044689aca96badc631755a35007de5e999 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 10 May 2017 21:08:19 -0400 Subject: [PATCH 06/31] Removing unnecessary data structures --- .../com/vimeo/stag/processor/StagProcessor.java | 7 ++++--- .../generators/model/AnnotatedClass.java | 14 +++++++++++++- .../generators/model/SupportedTypesModel.java | 15 +++------------ .../vimeo/stag/processor/utils/ElementUtils.java | 5 ++--- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java index ef2191fa..f8cac221 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java @@ -32,6 +32,7 @@ import com.vimeo.stag.processor.generators.ExternalAdapterInfo; import com.vimeo.stag.processor.generators.StagGenerator; import com.vimeo.stag.processor.generators.TypeAdapterGenerator; +import com.vimeo.stag.processor.generators.model.AnnotatedClass; import com.vimeo.stag.processor.generators.model.ClassInfo; import com.vimeo.stag.processor.generators.model.SupportedTypesModel; import com.vimeo.stag.processor.utils.DebugLog; @@ -124,7 +125,7 @@ public boolean process(Set annotations, RoundEnvironment } try { - Set supportedTypes = SupportedTypesModel.getInstance().getSupportedTypesMirror(); + Set supportedTypes = AnnotatedClass.annotatedClassToTypeMirror(SupportedTypesModel.getInstance().getSupportedTypes()); try { supportedTypes.addAll(KnownTypeAdapterFactoriesUtils.loadKnownTypes(processingEnv, packageName)); } catch (Exception ignored) {} @@ -133,8 +134,8 @@ public boolean process(Set annotations, RoundEnvironment StagGenerator stagFactoryGenerator = new StagGenerator(packageName, supportedTypes, externalAdapterInfoSet); - Set list = SupportedTypesModel.getInstance().getSupportedElements(); - for (Element element : list) { + for (AnnotatedClass annotatedClass : SupportedTypesModel.getInstance().getSupportedTypes()) { + Element element = annotatedClass.getElement(); if ((TypeUtils.isConcreteType(element) || TypeUtils.isParameterizedType(element)) && !TypeUtils.isAbstract(element)) { generateTypeAdapter(element, stagFactoryGenerator); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 79730f85..85864058 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -34,7 +34,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -47,6 +49,16 @@ public class AnnotatedClass { + @NotNull + public static Set annotatedClassToTypeMirror(@NotNull Collection annotatedClasses) { + Set typeMirrors = new HashSet<>(); + for (AnnotatedClass annotatedClass : annotatedClasses) { + typeMirrors.add(annotatedClass.getType()); + } + + return typeMirrors; + } + private static final String TAG = AnnotatedClass.class.getSimpleName(); @NotNull private final TypeMirror mType; @@ -105,7 +117,7 @@ private void addMemberVariable(@NotNull Element element, @NotNull TypeMirror typ if (null != previousElement) { mMemberVariables.remove(previousElement); MessagerUtils.logInfo("Ignoring inherited Member variable with the same variable name in class" + - element.toString() + ", with variable name " + previousElement.asType().toString()); + element.toString() + ", with variable name " + previousElement.asType().toString()); } mMemberVariables.put(element, typeMirror); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java index e4e9888e..50dc6caa 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java @@ -31,12 +31,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import javax.lang.model.element.Element; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; @@ -46,8 +46,6 @@ public final class SupportedTypesModel { @NotNull private final Map mSupportedTypesMap = new HashMap<>(); @NotNull private final Map mKnownInheritedTypesMap = new HashMap<>(); - @NotNull private final Set mSupportedTypes = new HashSet<>(); - @NotNull private final Set mSupportedTypesMirror = new HashSet<>(); @NotNull private final Set mExternalSupportedAdapters = new HashSet<>(); @Nullable private String mGeneratedStagFactoryName; @@ -75,8 +73,6 @@ public void initialize(@NotNull String generatedStagFactoryName) { */ private void addSupportedType(@NotNull AnnotatedClass object) { mSupportedTypesMap.put(TypeUtils.getOuterClassType(object.getType()), object); - mSupportedTypes.add(object.getElement()); - mSupportedTypesMirror.add(object.getType()); } /** @@ -163,13 +159,8 @@ public AnnotatedClass addSupportedType(@NotNull TypeMirror type) { * @return the set of supported types. */ @NotNull - public Set getSupportedElements() { - return new HashSet<>(mSupportedTypes); - } - - @NotNull - public Set getSupportedTypesMirror() { - return new HashSet<>(mSupportedTypesMirror); + public Collection getSupportedTypes() { + return mSupportedTypesMap.values(); } public void checkAndAddExternalAdapter(@NotNull VariableElement variableElement) { diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java index d9e4783e..0ff47d8a 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/ElementUtils.java @@ -85,9 +85,8 @@ public static String getPackage(@NotNull TypeMirror type) { * @param annotation type * @return {@code true} if the element is annotated, {@code false} otherwise */ - public static boolean isAnnotatedWith( - @NotNull Class annotationClass, - @Nullable Element element) { + public static boolean isAnnotatedWith(@NotNull Class annotationClass, + @Nullable Element element) { return element != null && element.getAnnotation(annotationClass) != null; } From fc2cbf162a1662fd79b0020d87289c5c09a6d5b0 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 10 May 2017 21:29:05 -0400 Subject: [PATCH 07/31] Getting rid of singleton --- .../vimeo/stag/processor/StagProcessor.java | 32 +++++++++++-------- .../processor/generators/StagGenerator.java | 15 +++++---- .../generators/TypeAdapterGenerator.java | 8 +++-- .../generators/model/AnnotatedClass.java | 12 ++++--- .../generators/model/SupportedTypesModel.java | 22 +++---------- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java index f8cac221..405e38c5 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java @@ -114,31 +114,32 @@ public boolean process(Set annotations, RoundEnvironment MessagerUtils.initialize(processingEnv.getMessager()); String stagFactoryGeneratedName = StagGenerator.getGeneratedFactoryClassAndPackage(packageName); - SupportedTypesModel.getInstance().initialize(stagFactoryGeneratedName); + + SupportedTypesModel supportedTypesModel = new SupportedTypesModel(stagFactoryGeneratedName); DebugLog.log("\nBeginning @UseStag annotation processing\n"); // Pick up the classes annotated with @UseStag Set useStagElements = roundEnv.getElementsAnnotatedWith(UseStag.class); for (Element useStagElement : useStagElements) { - processSupportedElements(useStagElement); + processSupportedElements(supportedTypesModel, useStagElement); } try { - Set supportedTypes = AnnotatedClass.annotatedClassToTypeMirror(SupportedTypesModel.getInstance().getSupportedTypes()); + Set supportedTypes = AnnotatedClass.annotatedClassToTypeMirror(supportedTypesModel.getSupportedTypes()); try { supportedTypes.addAll(KnownTypeAdapterFactoriesUtils.loadKnownTypes(processingEnv, packageName)); } catch (Exception ignored) {} - Set externalAdapterInfoSet = SupportedTypesModel.getInstance().getExternalSupportedAdapters(); + Set externalAdapterInfoSet = supportedTypesModel.getExternalSupportedAdapters(); - StagGenerator stagFactoryGenerator = new StagGenerator(packageName, supportedTypes, externalAdapterInfoSet); + StagGenerator stagFactoryGenerator = new StagGenerator(packageName, supportedTypes, externalAdapterInfoSet, supportedTypesModel); - for (AnnotatedClass annotatedClass : SupportedTypesModel.getInstance().getSupportedTypes()) { + for (AnnotatedClass annotatedClass : supportedTypesModel.getSupportedTypes()) { Element element = annotatedClass.getElement(); if ((TypeUtils.isConcreteType(element) || TypeUtils.isParameterizedType(element)) && !TypeUtils.isAbstract(element)) { - generateTypeAdapter(element, stagFactoryGenerator); + generateTypeAdapter(supportedTypesModel, element, stagFactoryGenerator); } } @@ -162,14 +163,15 @@ private void generateStagFactory(@NotNull StagGenerator stagGenerator, writeTypeSpecToFile(typeSpec, packageName); } - private void generateTypeAdapter(@NotNull Element element, + private void generateTypeAdapter(@NotNull SupportedTypesModel supportedTypesModel, + @NotNull Element element, @NotNull StagGenerator stagGenerator) throws IOException { ClassInfo classInfo = new ClassInfo(element.asType()); AdapterGenerator independentAdapter = element.getKind() == ElementKind.ENUM ? new EnumTypeAdapterGenerator(classInfo, element) : - new TypeAdapterGenerator(classInfo); + new TypeAdapterGenerator(supportedTypesModel, classInfo); // Create the type spec TypeSpec typeAdapterSpec = independentAdapter.createTypeAdapterSpec(stagGenerator); @@ -197,19 +199,21 @@ private void writeTypeSpecToFile(@NotNull TypeSpec typeSpec, @NotNull String pac * could be annotated are @interface and interface. Enums * and classes are supported. * - * @param useStagElement the element to add to the - * supported type model. + * @param supportedTypesModel the supported types model + * @param useStagElement the element to add to the + * supported type model. */ - private static void processSupportedElements(@NotNull Element useStagElement) { + private static void processSupportedElements(@NotNull SupportedTypesModel supportedTypesModel, + @NotNull Element useStagElement) { if (ElementUtils.isSupportedElementKind(useStagElement)) { TypeMirror rootType = useStagElement.asType(); DebugLog.log("Annotated type: " + rootType + "\n"); - SupportedTypesModel.getInstance().addSupportedType(rootType); + supportedTypesModel.addSupportedType(rootType); } List enclosedElements = useStagElement.getEnclosedElements(); for (Element element : enclosedElements) { - processSupportedElements(element); + processSupportedElements(supportedTypesModel, element); } } } \ No newline at end of file diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index b89c4b6e..95019229 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -67,8 +67,8 @@ public class StagGenerator { @NotNull private static final String CLASS_STAG = "Stag"; @NotNull private static final String CLASS_TYPE_ADAPTER_FACTORY = "Factory"; @NotNull private static final String TYPE_ADAPTER_SUFFIX = "TypeAdapter"; - @NotNull private final static Map KNOWN_MAP_GENERIC_CLASSES = new HashMap<>(); - @NotNull private final static Map KNOWN_COLLECTION_GENERIC_CLASSES = new HashMap<>(); + @NotNull private static final Map KNOWN_MAP_GENERIC_CLASSES = new HashMap<>(); + @NotNull private static final Map KNOWN_COLLECTION_GENERIC_CLASSES = new HashMap<>(); static { KNOWN_MAP_GENERIC_CLASSES.put(Map.class.getName(), new GenericClassInfo(false)); @@ -90,14 +90,18 @@ public class StagGenerator { @NotNull private final Map mExternalSupportedAdapters; @NotNull private final HashMap mKnownAdapterFieldMap = new HashMap<>(); @NotNull private final HashMap mKnownFieldToMethodNameMap = new HashMap<>(); + @NotNull private final SupportedTypesModel mSupportedTypesModel; public StagGenerator(@NotNull String generatedPackageName, @NotNull Set knownTypes, - @NotNull Set externalSupportedAdapters) { + @NotNull Set externalSupportedAdapters, + @NotNull SupportedTypesModel supportedTypesModel) { mKnownTypes = knownTypes; mGeneratedPackageName = generatedPackageName; mKnownClasses = new ArrayList<>(knownTypes.size()); mExternalSupportedAdapters = new HashMap<>(externalSupportedAdapters.size()); + mSupportedTypesModel = supportedTypesModel; + ; Map knownFieldNames = new HashMap<>(knownTypes.size()); Map> clashingClassNames = new HashMap<>(knownTypes.size()); @@ -152,8 +156,7 @@ public StagGenerator(@NotNull String generatedPackageName, for (ClassInfo knownGenericType : genericClasses) { List typeArguments = knownGenericType.getTypeArguments(); - AnnotatedClass annotatedClass = - SupportedTypesModel.getInstance().getSupportedType(knownGenericType.getType()); + AnnotatedClass annotatedClass = mSupportedTypesModel.getSupportedType(knownGenericType.getType()); if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in StagGenerator : " + knownGenericType.toString()); } @@ -435,7 +438,7 @@ private TypeSpec getAdapterFactorySpec() { * If the type is of parameterized type, use the normal way of creating typetokens */ typeTokenCode = "new TypeToken<" + classInfo.getType().toString() + - ">(){}"; + ">(){}"; } getAdapterMethodBuilder.addStatement(fieldName + " = gson.getAdapter(" + typeTokenCode + ")"); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index ade3f5a0..bfae45f7 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java @@ -75,6 +75,8 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; +import static java.awt.SystemColor.info; + public class TypeAdapterGenerator extends AdapterGenerator { private static final String TYPE_ADAPTER_FIELD_PREFIX = "mTypeAdapter"; @@ -82,8 +84,10 @@ public class TypeAdapterGenerator extends AdapterGenerator { private static boolean sStagFactoryUsed; @NotNull private final ClassInfo mInfo; + @NotNull private final SupportedTypesModel mSupportedTypesModel; - public TypeAdapterGenerator(@NotNull ClassInfo info) { + public TypeAdapterGenerator(@NotNull SupportedTypesModel supportedTypesModel, @NotNull ClassInfo info) { + mSupportedTypesModel = supportedTypesModel; mInfo = info; } @@ -862,7 +866,7 @@ public TypeSpec createTypeAdapterSpec(@NotNull StagGenerator stagGenerator) { } } - AnnotatedClass annotatedClass = SupportedTypesModel.getInstance().getSupportedType(typeMirror); + AnnotatedClass annotatedClass = mSupportedTypesModel.getSupportedType(typeMirror); if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in TypeAdapterGenerator : " + typeMirror.toString()); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 85864058..98e7e0f8 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -64,12 +64,14 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection mMemberVariables; + @NotNull private final SupportedTypesModel mSupportedTypesModel; - AnnotatedClass(@NotNull TypeElement element) { - this(element, null); + AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element) { + this(supportedTypesModel, element, null); } - AnnotatedClass(@NotNull TypeElement element, @Nullable FieldOption childFieldOption) { + AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element, @Nullable FieldOption childFieldOption) { + mSupportedTypesModel = supportedTypesModel; mType = element.asType(); mElement = element; Map variableNames = new HashMap<>(element.getEnclosedElements().size()); @@ -92,7 +94,7 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, genericInheritedType.getElement(), @@ -147,7 +149,7 @@ private void addToSupportedTypes(@NotNull Element element, @NotNull FieldOption if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.TRANSIENT)) { checkModifiers(variableElement, modifiers); if (!TypeUtils.isAbstract(element)) { - SupportedTypesModel.getInstance().checkAndAddExternalAdapter(variableElement); + mSupportedTypesModel.checkAndAddExternalAdapter(variableElement); } DebugLog.log(TAG, "\t\tMember variables - " + variableElement.asType().toString()); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java index 50dc6caa..19cf1d38 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java @@ -42,26 +42,12 @@ public final class SupportedTypesModel { - @Nullable private static SupportedTypesModel sInstance; - @NotNull private final Map mSupportedTypesMap = new HashMap<>(); @NotNull private final Map mKnownInheritedTypesMap = new HashMap<>(); @NotNull private final Set mExternalSupportedAdapters = new HashSet<>(); - @Nullable private String mGeneratedStagFactoryName; - - private SupportedTypesModel() { - } - - @NotNull - public static synchronized SupportedTypesModel getInstance() { - if (sInstance == null) { - sInstance = new SupportedTypesModel(); - } - - return sInstance; - } + @NotNull private final String mGeneratedStagFactoryName; - public void initialize(@NotNull String generatedStagFactoryName) { + public SupportedTypesModel(@NotNull String generatedStagFactoryName) { mGeneratedStagFactoryName = generatedStagFactoryName; } @@ -120,7 +106,7 @@ public AnnotatedClass addToKnownInheritedType(@NotNull TypeMirror type, @Nullabl if (null == model) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(TypeUtils.safeTypeMirrorToTypeElement(type), childFieldOption); + model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type), childFieldOption); mKnownInheritedTypesMap.put(outerClassType, model); } } @@ -144,7 +130,7 @@ public AnnotatedClass addSupportedType(@NotNull TypeMirror type) { if (model == null) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(TypeUtils.safeTypeMirrorToTypeElement(type)); + model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type)); } addSupportedType(model); } From 9e60cd1449139d05ef3721246bac2160839edcce Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 10 May 2017 21:56:38 -0400 Subject: [PATCH 08/31] Fixing some type warnings --- .../generators/ExternalAdapterInfo.java | 2 +- .../processor/generators/StagGenerator.java | 5 +---- .../generators/TypeAdapterGenerator.java | 17 +++++++---------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java index f2877d1e..e229b11e 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java @@ -52,7 +52,7 @@ public static void addExternalAdapters(@NotNull String stagFactoryGeneratedName, /* * Make sure the external model is annotated with @UseStag */ - if (null != useStag) { + if (useStag != null) { ClassInfo classInfo = new ClassInfo(typeElement.asType()); String classAdapterName = FileGenUtils.unescapeEscapedString(classInfo.getTypeAdapterQualifiedClassName()); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 95019229..72a306e5 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -90,7 +90,6 @@ public class StagGenerator { @NotNull private final Map mExternalSupportedAdapters; @NotNull private final HashMap mKnownAdapterFieldMap = new HashMap<>(); @NotNull private final HashMap mKnownFieldToMethodNameMap = new HashMap<>(); - @NotNull private final SupportedTypesModel mSupportedTypesModel; public StagGenerator(@NotNull String generatedPackageName, @NotNull Set knownTypes, @@ -100,8 +99,6 @@ public StagGenerator(@NotNull String generatedPackageName, mGeneratedPackageName = generatedPackageName; mKnownClasses = new ArrayList<>(knownTypes.size()); mExternalSupportedAdapters = new HashMap<>(externalSupportedAdapters.size()); - mSupportedTypesModel = supportedTypesModel; - ; Map knownFieldNames = new HashMap<>(knownTypes.size()); Map> clashingClassNames = new HashMap<>(knownTypes.size()); @@ -156,7 +153,7 @@ public StagGenerator(@NotNull String generatedPackageName, for (ClassInfo knownGenericType : genericClasses) { List typeArguments = knownGenericType.getTypeArguments(); - AnnotatedClass annotatedClass = mSupportedTypesModel.getSupportedType(knownGenericType.getType()); + AnnotatedClass annotatedClass = supportedTypesModel.getSupportedType(knownGenericType.getType()); if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in StagGenerator : " + knownGenericType.toString()); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index bfae45f7..16eb9041 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java @@ -75,8 +75,6 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; -import static java.awt.SystemColor.info; - public class TypeAdapterGenerator extends AdapterGenerator { private static final String TYPE_ADAPTER_FIELD_PREFIX = "mTypeAdapter"; @@ -96,7 +94,7 @@ public TypeAdapterGenerator(@NotNull SupportedTypesModel supportedTypesModel, @N */ @Nullable private static String getTypeTokenCodeForGenericType(@NotNull TypeMirror fieldType, - @NotNull Map typeVarsMap) { + @NotNull Map typeVarsMap) { // This method should only be called if the type is a generic type Preconditions.checkTrue(!TypeUtils.isConcreteType(fieldType) && TypeUtils.containsTypeVarParams(fieldType)); @@ -137,7 +135,7 @@ private static String getTypeTokenCodeForGenericType(@NotNull TypeMirror fieldTy @Nullable private String getTypeAdapterCodeForGenericTypes(@NotNull TypeMirror fieldType, @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, - @NotNull Map typeVarsMap, + @NotNull Map typeVarsMap, @NotNull StagGenerator stagGenerator, @NotNull AdapterFieldInfo adapterFieldInfo) { @@ -414,7 +412,7 @@ private static String getFieldAccessorForKnownJsonAdapterType(@NotNull Executabl */ private String getAdapterAccessor(@NotNull TypeMirror fieldType, @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, - @NotNull Map typeVarsMap, + @NotNull Map typeVarsMap, @NotNull StagGenerator stagGenerator, @NotNull AdapterFieldInfo adapterFieldInfo) { @@ -660,7 +658,7 @@ private static String addFieldForUnknownType(@NotNull TypeMirror fieldType, private static String getAdapterForUnknownGenericType(@NotNull TypeMirror fieldType, @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, - @NotNull Map typeVarsMap, + @NotNull Map typeVarsMap, @NotNull AdapterFieldInfo adapterFieldInfo) { String fieldName = adapterFieldInfo.getFieldName(fieldType); @@ -682,7 +680,7 @@ private AdapterFieldInfo addAdapterFields(@Nullable GenericClassInfo genericClas @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, @NotNull Map memberVariables, - @NotNull Map typeVarsMap, + @NotNull Map typeVarsMap, @NotNull StagGenerator stagGenerator) { AdapterFieldInfo result = new AdapterFieldInfo(memberVariables.size()); @@ -831,7 +829,7 @@ public TypeSpec createTypeAdapterSpec(@NotNull StagGenerator stagGenerator) { .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .superclass(ParameterizedTypeName.get(ClassName.get(TypeAdapter.class), typeVariableName)); - Map typeVarsMap = new HashMap<>(); + Map typeVarsMap = new HashMap<>(); int idx = 0; StagGenerator.GenericClassInfo genericClassInfo = null; @@ -841,8 +839,7 @@ public TypeSpec createTypeAdapterSpec(@NotNull StagGenerator stagGenerator) { if (innerTypeMirror.getKind() == TypeKind.TYPEVAR) { TypeVariable typeVariable = (TypeVariable) innerTypeMirror; String simpleName = typeVariable.asElement().getSimpleName().toString(); - adapterBuilder.addTypeVariable(TypeVariableName.get(simpleName, TypeVariableName.get( - typeVariable.getUpperBound()))); + adapterBuilder.addTypeVariable(TypeVariableName.get(simpleName, TypeVariableName.get(typeVariable.getUpperBound()))); String paramName; if (genericClassInfo != null && genericClassInfo.mHasUnknownVarTypeFields) { //If the classInfo has unknown types, pass type... as param in constructor. From 2ca3f9e0f517486ed119b451cdf03b2857e95dd0 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 10 May 2017 22:04:47 -0400 Subject: [PATCH 09/31] Switch to map interface --- .../vimeo/stag/processor/generators/StagGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 72a306e5..07229750 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -81,15 +81,15 @@ public class StagGenerator { } @NotNull private final List mKnownClasses; - @NotNull private final HashMap mFieldNameMap = new HashMap<>(); - @NotNull private final HashMap mUnknownAdapterFieldMap = new HashMap<>(); + @NotNull private final Map mFieldNameMap = new HashMap<>(); + @NotNull private final Map mUnknownAdapterFieldMap = new HashMap<>(); @NotNull private final List mUnknownClasses = new ArrayList<>(); - @NotNull private final HashMap mGenericClassInfo = new HashMap<>(); + @NotNull private final Map mGenericClassInfo = new HashMap<>(); @NotNull private final String mGeneratedPackageName; @NotNull private final Set mKnownTypes; @NotNull private final Map mExternalSupportedAdapters; - @NotNull private final HashMap mKnownAdapterFieldMap = new HashMap<>(); - @NotNull private final HashMap mKnownFieldToMethodNameMap = new HashMap<>(); + @NotNull private final Map mKnownAdapterFieldMap = new HashMap<>(); + @NotNull private final Map mKnownFieldToMethodNameMap = new HashMap<>(); public StagGenerator(@NotNull String generatedPackageName, @NotNull Set knownTypes, From 07d4ced8f8973747916cb630090ae566f3a7dcf6 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Sun, 14 May 2017 21:39:22 -0400 Subject: [PATCH 10/31] Update gradle plugin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f3f4f466..d97bc237 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.1' + classpath 'com.android.tools.build:gradle:2.3.2' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } From 19882b391ba16622d7ae2c78edf7a0ef4fe71b15 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Sun, 14 May 2017 21:43:57 -0400 Subject: [PATCH 11/31] Reducing member visibility and using TypeElement --- .../processor/generators/ExternalAdapterInfo.java | 12 +++++++++--- .../stag/processor/generators/StagGenerator.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java index e229b11e..1140060c 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/ExternalAdapterInfo.java @@ -24,17 +24,23 @@ public final class ExternalAdapterInfo { @NotNull private static final Set sCheckedClasses = new HashSet<>(); - @NotNull final Element mExternalClassType; + @NotNull private final TypeElement mExternalClassType; @NotNull private final TypeElement mAdapterType; @NotNull private final ExecutableElement mAdapterConstructor; - private ExternalAdapterInfo(@NotNull Element typeElement, @NotNull TypeElement adapterTypeElement, + private ExternalAdapterInfo(@NotNull TypeElement typeElement, + @NotNull TypeElement adapterTypeElement, @NotNull ExecutableElement adapterConstructor) { mExternalClassType = typeElement; mAdapterType = adapterTypeElement; mAdapterConstructor = adapterConstructor; } + @NotNull + public Element getExternalClass() { + return mExternalClassType; + } + /** * Add adapters for the external models. * @@ -47,7 +53,7 @@ public static void addExternalAdapters(@NotNull String stagFactoryGeneratedName, @NotNull Set externalAdapterInfoSet) { if (!TypeUtils.isSupportedPrimitive(typeMirror.toString()) && typeMirror instanceof DeclaredType) { DeclaredType declaredType = (DeclaredType) typeMirror; - Element typeElement = declaredType.asElement(); + TypeElement typeElement = (TypeElement) declaredType.asElement(); UseStag useStag = null != typeElement ? typeElement.getAnnotation(UseStag.class) : null; /* * Make sure the external model is annotated with @UseStag diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 07229750..38998323 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -147,7 +147,7 @@ public StagGenerator(@NotNull String generatedPackageName, } for (ExternalAdapterInfo entry : externalSupportedAdapters) { - TypeMirror externalType = entry.mExternalClassType.asType(); + TypeMirror externalType = entry.getExternalClass().asType(); mExternalSupportedAdapters.put(externalType.toString(), entry); } From 158d03f6d20a70a99240186b00fb370fe576e96b Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Sun, 14 May 2017 21:51:37 -0400 Subject: [PATCH 12/31] Using TypeElement instead of element --- .../main/java/com/vimeo/stag/processor/StagProcessor.java | 4 ++-- .../stag/processor/generators/EnumTypeAdapterGenerator.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java index 405e38c5..164d063d 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java @@ -136,7 +136,7 @@ public boolean process(Set annotations, RoundEnvironment StagGenerator stagFactoryGenerator = new StagGenerator(packageName, supportedTypes, externalAdapterInfoSet, supportedTypesModel); for (AnnotatedClass annotatedClass : supportedTypesModel.getSupportedTypes()) { - Element element = annotatedClass.getElement(); + TypeElement element = (TypeElement) annotatedClass.getElement(); if ((TypeUtils.isConcreteType(element) || TypeUtils.isParameterizedType(element)) && !TypeUtils.isAbstract(element)) { generateTypeAdapter(supportedTypesModel, element, stagFactoryGenerator); @@ -164,7 +164,7 @@ private void generateStagFactory(@NotNull StagGenerator stagGenerator, } private void generateTypeAdapter(@NotNull SupportedTypesModel supportedTypesModel, - @NotNull Element element, + @NotNull TypeElement element, @NotNull StagGenerator stagGenerator) throws IOException { ClassInfo classInfo = new ClassInfo(element.asType()); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/EnumTypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/EnumTypeAdapterGenerator.java index 28c85ae8..34d3097e 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/EnumTypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/EnumTypeAdapterGenerator.java @@ -46,6 +46,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; public class EnumTypeAdapterGenerator extends AdapterGenerator { @@ -54,9 +55,9 @@ public class EnumTypeAdapterGenerator extends AdapterGenerator { private final ClassInfo mInfo; @NotNull - private final Element mElement; + private final TypeElement mElement; - public EnumTypeAdapterGenerator(@NotNull ClassInfo info, @NotNull Element element) { + public EnumTypeAdapterGenerator(@NotNull ClassInfo info, @NotNull TypeElement element) { mInfo = info; mElement = element; } From 4e1b1852a2ad5505ff7d5bafcb9d4ea0889980c7 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Sun, 14 May 2017 22:10:43 -0400 Subject: [PATCH 13/31] Being more specific about Elements --- .../vimeo/stag/processor/StagProcessor.java | 2 +- .../generators/model/AnnotatedClass.java | 49 +++++++++---------- .../vimeo/stag/processor/utils/TypeUtils.java | 22 ++++----- .../stag/processor/TypeUtilsUnitTest.java | 25 ++++------ .../java/com/vimeo/stag/processor/Utils.java | 6 +-- 5 files changed, 49 insertions(+), 55 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java index 164d063d..527305ea 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java @@ -136,7 +136,7 @@ public boolean process(Set annotations, RoundEnvironment StagGenerator stagFactoryGenerator = new StagGenerator(packageName, supportedTypes, externalAdapterInfoSet, supportedTypesModel); for (AnnotatedClass annotatedClass : supportedTypesModel.getSupportedTypes()) { - TypeElement element = (TypeElement) annotatedClass.getElement(); + TypeElement element = annotatedClass.getElement(); if ((TypeUtils.isConcreteType(element) || TypeUtils.isParameterizedType(element)) && !TypeUtils.isAbstract(element)) { generateTypeAdapter(supportedTypesModel, element, stagFactoryGenerator); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 98e7e0f8..050593cb 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -62,8 +62,8 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection mMemberVariables; + @NotNull private final TypeElement mElement; + @NotNull private final LinkedHashMap mMemberVariables; @NotNull private final SupportedTypesModel mSupportedTypesModel; AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element) { @@ -74,7 +74,7 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection variableNames = new HashMap<>(element.getEnclosedElements().size()); + Map variableNames = new HashMap<>(element.getEnclosedElements().size()); TypeMirror inheritedType = TypeUtils.getInheritedType(element); UseStag useStag = element.getAnnotation(UseStag.class); @@ -96,26 +96,28 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, + LinkedHashMap inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, genericInheritedType.getElement(), genericInheritedType.getMemberVariables()); - for (Map.Entry entry : inheritedMemberVariables.entrySet()) { + for (Map.Entry entry : inheritedMemberVariables.entrySet()) { addMemberVariable(entry.getKey(), entry.getValue(), variableNames); } } if (!TypeUtils.isEnum(element)) { for (Element enclosedElement : element.getEnclosedElements()) { - addToSupportedTypes(enclosedElement, fieldOption, variableNames); + if (enclosedElement instanceof VariableElement) { + addToSupportedTypes((VariableElement) enclosedElement, fieldOption, variableNames); + } } } } - private void addMemberVariable(@NotNull Element element, @NotNull TypeMirror typeMirror, - @NotNull Map variableNames) { - Element previousElement = variableNames.put(element.getSimpleName().toString(), element); + private void addMemberVariable(@NotNull VariableElement element, @NotNull TypeMirror typeMirror, + @NotNull Map variableNames) { + VariableElement previousElement = variableNames.put(element.getSimpleName().toString(), element); if (null != previousElement) { mMemberVariables.remove(previousElement); MessagerUtils.logInfo("Ignoring inherited Member variable with the same variable name in class" + @@ -140,21 +142,18 @@ private static void checkModifiers(VariableElement variableElement, Set variableNames) { - if (element instanceof VariableElement) { - if (shouldIncludeField(element, fieldOption)) { - final VariableElement variableElement = (VariableElement) element; - Set modifiers = variableElement.getModifiers(); - if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.TRANSIENT)) { - checkModifiers(variableElement, modifiers); - if (!TypeUtils.isAbstract(element)) { - mSupportedTypesModel.checkAndAddExternalAdapter(variableElement); - } - DebugLog.log(TAG, "\t\tMember variables - " + variableElement.asType().toString()); - - addMemberVariable(variableElement, variableElement.asType(), variableNames); + private void addToSupportedTypes(@NotNull VariableElement element, @NotNull FieldOption fieldOption, + @NotNull Map variableNames) { + if (shouldIncludeField(element, fieldOption)) { + Set modifiers = element.getModifiers(); + if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.TRANSIENT)) { + checkModifiers(element, modifiers); + if (!TypeUtils.isAbstract(element)) { + mSupportedTypesModel.checkAndAddExternalAdapter(element); } + DebugLog.log(TAG, "\t\tMember variables - " + element.asType().toString()); + + addMemberVariable(element, element.asType(), variableNames); } } } @@ -178,7 +177,7 @@ public TypeMirror getType() { } @NotNull - public Element getElement() { + public TypeElement getElement() { return mElement; } @@ -195,7 +194,7 @@ public Element getElement() { * types. */ @NotNull - public LinkedHashMap getMemberVariables() { + public LinkedHashMap getMemberVariables() { return new LinkedHashMap<>(mMemberVariables); } } \ No newline at end of file diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java index fa580e54..d1a7c626 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java @@ -43,6 +43,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; @@ -172,7 +173,7 @@ public static List getTypeArguments(@Nullable TypeMirror t * @return true if the element is not generic and * contains no generic type arguments, false otherwise. */ - public static boolean isConcreteType(@NotNull Element element) { + public static boolean isConcreteType(@NotNull TypeElement element) { return isConcreteType(element.asType()); } @@ -207,7 +208,7 @@ public static boolean isAbstract(@Nullable TypeMirror typeMirror) { * @return true if the element is not generic and * contains no generic type arguments, false otherwise. */ - public static boolean isParameterizedType(@Nullable Element element) { + public static boolean isParameterizedType(@Nullable TypeElement element) { return element != null && isParameterizedType(element.asType()); } @@ -289,9 +290,8 @@ public static TypeMirror getInheritedType(@Nullable TypeElement element) { * @param element the element to check. * @return true if the element inherits from an enum, false otherwise. */ - public static boolean isEnum(@Nullable Element element) { - TypeElement typeElement = (TypeElement) element; - TypeMirror typeMirror = typeElement != null ? typeElement.getSuperclass() : null; + public static boolean isEnum(@Nullable TypeElement element) { + TypeMirror typeMirror = element != null ? element.getSuperclass() : null; String className = typeMirror != null ? getClassNameFromTypeMirror(typeMirror) : null; return Enum.class.getName().equals(className); @@ -337,18 +337,18 @@ public static boolean isEnum(@Nullable Element element) { * inherited class. (to maintain the ordering) */ @NotNull - public static LinkedHashMap getConcreteMembers(@NotNull TypeMirror concreteInherited, - @NotNull Element genericInherited, - @NotNull Map members) { + public static LinkedHashMap getConcreteMembers(@NotNull TypeMirror concreteInherited, + @NotNull TypeElement genericInherited, + @NotNull Map members) { DebugLog.log(TAG, "Inherited concrete type: " + concreteInherited.toString()); DebugLog.log(TAG, "Inherited generic type: " + genericInherited.asType().toString()); List concreteTypes = getParameterizedTypes(concreteInherited); List inheritedTypes = getParameterizedTypes(genericInherited); - LinkedHashMap map = new LinkedHashMap<>(); + LinkedHashMap map = new LinkedHashMap<>(); - for (Entry member : members.entrySet()) { + for (Entry member : members.entrySet()) { DebugLog.log(TAG, "\t\tEvaluating member - " + member.getValue().toString()); @@ -416,7 +416,7 @@ private static TypeMirror resolveTypeVars(@NotNull TypeMirror element, } @NotNull - private static List getParameterizedTypes(@NotNull Element element) { + private static List getParameterizedTypes(@NotNull TypeElement element) { return ((DeclaredType) element.asType()).getTypeArguments(); } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java index 4c984790..a1439906 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java @@ -82,7 +82,7 @@ public void getInheritedType_isCorrect() throws Exception { assertNotNull(concreteType); TypeMirror realConcreteType = - types.getDeclaredType((TypeElement) Utils.getElementFromClass(DummyGenericClass.class), + types.getDeclaredType(Utils.getElementFromClass(DummyGenericClass.class), Utils.getTypeMirrorFromClass(String.class)); assertTrue(realConcreteType.toString().equals(concreteType.toString())); @@ -124,7 +124,7 @@ public void getConcreteMembers_isCorrect() throws Exception { assertNotNull(genericType); LinkedHashMap members = - TypeUtils.getConcreteMembers(concreteType, types.asElement(genericType), genericMembers); + TypeUtils.getConcreteMembers(concreteType, (TypeElement) types.asElement(genericType), genericMembers); TypeMirror stringType = Utils.getTypeMirrorFromClass(String.class); @@ -139,39 +139,34 @@ public void getConcreteMembers_isCorrect() throws Exception { assertTrue(entry.getValue() .toString() - .equals(types.getDeclaredType( - (TypeElement) Utils.getElementFromClass(ArrayList.class), + .equals(types.getDeclaredType(Utils.getElementFromClass(ArrayList.class), stringType).toString())); } else if (entry.getKey().getSimpleName().contentEquals("testMap")) { assertTrue(entry.getValue() .toString() - .equals(types.getDeclaredType( - (TypeElement) Utils.getElementFromClass(HashMap.class), stringType, - stringType).toString())); + .equals(types.getDeclaredType(Utils.getElementFromClass(HashMap.class), stringType, + stringType).toString())); } else if (entry.getKey().getSimpleName().contentEquals("testSet")) { assertTrue(entry.getValue() .toString() - .equals(types.getDeclaredType( - (TypeElement) Utils.getElementFromClass(HashSet.class), stringType) + .equals(types.getDeclaredType(Utils.getElementFromClass(HashSet.class), stringType) .toString())); } else if (entry.getKey().getSimpleName().contentEquals("testArrayMap")) { - TypeMirror listString = types.getDeclaredType((TypeElement) Utils.getElementFromClass(List.class), stringType); + TypeMirror listString = types.getDeclaredType(Utils.getElementFromClass(List.class), stringType); assertTrue(entry.getValue() .toString() - .equals(types.getDeclaredType( - (TypeElement) Utils.getElementFromClass(HashMap.class), stringType, listString) + .equals(types.getDeclaredType(Utils.getElementFromClass(HashMap.class), stringType, listString) .toString())); } else if (entry.getKey().getSimpleName().contentEquals("testListMap")) { - TypeMirror mapStringString = types.getDeclaredType((TypeElement) Utils.getElementFromClass(Map.class), stringType, stringType); + TypeMirror mapStringString = types.getDeclaredType(Utils.getElementFromClass(Map.class), stringType, stringType); assertTrue(entry.getValue() .toString() - .equals(types.getDeclaredType( - (TypeElement) Utils.getElementFromClass(ArrayList.class), mapStringString) + .equals(types.getDeclaredType(Utils.getElementFromClass(ArrayList.class), mapStringString) .toString())); } } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java index 091c849c..01f60918 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java @@ -79,18 +79,18 @@ public static TypeElement getElementFromClass(@NotNull Class clazz) { @Nullable public static TypeMirror getTypeMirrorFromClass(@NotNull Class clazz) { - Element element = getElementFromClass(clazz); + TypeElement element = getElementFromClass(clazz); return element != null ? element.asType() : null; } @Nullable - public static Element getElementFromObject(@NotNull Object object) { + public static TypeElement getElementFromObject(@NotNull Object object) { return elements.getTypeElement(object.getClass().getName()); } @Nullable public static TypeMirror getTypeMirrorFromObject(@NotNull Object object) { - Element element = getElementFromObject(object); + TypeElement element = getElementFromObject(object); return element != null ? element.asType() : null; } From 2c7c0a816741ea3eabe7291249e662e1a144ba47 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Sun, 14 May 2017 22:14:47 -0400 Subject: [PATCH 14/31] Cleaning up test utils --- .../java/com/vimeo/stag/processor/Utils.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java index 01f60918..5a3b1a54 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java @@ -33,7 +33,6 @@ import java.lang.reflect.InvocationTargetException; import java.util.List; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; import javax.lang.model.type.TypeMirror; @@ -42,14 +41,25 @@ import static org.junit.Assert.assertTrue; -public final class Utils { +final class Utils { - private static Elements elements; - private static Types types; + @Nullable private static Elements elements; + @Nullable private static Types types; private Utils() { } + @NotNull + private static Elements safeElements() { + Preconditions.checkNotNull(elements); + return elements; + } + + private static Types safeTypes() { + Preconditions.checkNotNull(types); + return types; + } + public static void setup(@NotNull Elements elements, @NotNull Types types) { Preconditions.checkNotNull(elements); Preconditions.checkNotNull(types); @@ -74,7 +84,7 @@ public static void testZeroArgumentConstructorFinalClass(Class clazz) thr @Nullable public static TypeElement getElementFromClass(@NotNull Class clazz) { - return elements.getTypeElement(clazz.getName()); + return safeElements().getTypeElement(clazz.getName()); } @Nullable @@ -85,7 +95,7 @@ public static TypeMirror getTypeMirrorFromClass(@NotNull Class clazz) { @Nullable public static TypeElement getElementFromObject(@NotNull Object object) { - return elements.getTypeElement(object.getClass().getName()); + return safeElements().getTypeElement(object.getClass().getName()); } @Nullable @@ -97,13 +107,13 @@ public static TypeMirror getTypeMirrorFromObject(@NotNull Object object) { @NotNull public static TypeMirror getGenericVersionOfClass(@NotNull Class clazz) { List params = - elements.getTypeElement(clazz.getName()).getTypeParameters(); + safeElements().getTypeElement(clazz.getName()).getTypeParameters(); TypeMirror[] genericTypes = new TypeMirror[params.size()]; for (int n = 0; n < genericTypes.length; n++) { genericTypes[n] = params.get(n).asType(); } - return types.getDeclaredType(elements.getTypeElement(DummyGenericClass.class.getName()), - genericTypes); + return safeTypes().getDeclaredType(safeElements().getTypeElement(DummyGenericClass.class.getName()), + genericTypes); } } From 5629dc37080ddf68bb5c621772abd53cba169049 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 15 May 2017 11:50:28 -0400 Subject: [PATCH 15/31] Fixing problems with Element --- .../stag/processor/generators/StagGenerator.java | 3 ++- .../processor/generators/TypeAdapterGenerator.java | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 38998323..148f568e 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -58,6 +58,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; +import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -157,7 +158,7 @@ public StagGenerator(@NotNull String generatedPackageName, if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in StagGenerator : " + knownGenericType.toString()); } - Map memberVariables = annotatedClass.getMemberVariables(); + Map memberVariables = annotatedClass.getMemberVariables(); boolean hasUnknownTypeFields = false; for (TypeMirror type : memberVariables.values()) { if (!checkKnownAdapters(type)) { diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index 16eb9041..bed069cb 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java @@ -232,7 +232,7 @@ private static TypeName getAdapterFieldTypeName(@NotNull TypeMirror type) { @NotNull private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, - @NotNull Map elements, + @NotNull Map elements, @NotNull AdapterFieldInfo adapterFieldInfo) { MethodSpec.Builder builder = MethodSpec.methodBuilder("read") .addParameter(JsonReader.class, "reader") @@ -260,7 +260,7 @@ private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, final List nonNullFields = new ArrayList<>(); - for (Map.Entry element : elements.entrySet()) { + for (Map.Entry element : elements.entrySet()) { String name = getJsonName(element.getKey()); final String variableName = element.getKey().getSimpleName().toString(); final TypeMirror elementValue = element.getValue(); @@ -679,14 +679,14 @@ private static String getAdapterForUnknownGenericType(@NotNull TypeMirror fieldT private AdapterFieldInfo addAdapterFields(@Nullable GenericClassInfo genericClassInfo, @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, - @NotNull Map memberVariables, + @NotNull Map memberVariables, @NotNull Map typeVarsMap, @NotNull StagGenerator stagGenerator) { AdapterFieldInfo result = new AdapterFieldInfo(memberVariables.size()); boolean hasUnknownGenericField = genericClassInfo != null && genericClassInfo.mHasUnknownVarTypeFields; - for (Map.Entry entry : memberVariables.entrySet()) { + for (Map.Entry entry : memberVariables.entrySet()) { TypeMirror fieldType = entry.getValue(); JsonAdapter annotation = entry.getKey().getAnnotation(JsonAdapter.class); String adapterAccessor = null; @@ -740,7 +740,7 @@ private AdapterFieldInfo addAdapterFields(@Nullable GenericClassInfo genericClas @NotNull private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, - @NotNull Map memberVariables, + @NotNull Map memberVariables, @NotNull AdapterFieldInfo adapterFieldInfo) { final MethodSpec.Builder builder = MethodSpec.methodBuilder("write") .addParameter(JsonWriter.class, "writer") @@ -756,7 +756,7 @@ private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, builder.addStatement("return"); builder.endControlFlow(); - for (Map.Entry element : memberVariables.entrySet()) { + for (Map.Entry element : memberVariables.entrySet()) { String name = getJsonName(element.getKey()); final String variableName = element.getKey().getSimpleName().toString(); String variableType = element.getValue().toString(); @@ -867,7 +867,7 @@ public TypeSpec createTypeAdapterSpec(@NotNull StagGenerator stagGenerator) { if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in TypeAdapterGenerator : " + typeMirror.toString()); } - Map memberVariables = annotatedClass.getMemberVariables(); + Map memberVariables = annotatedClass.getMemberVariables(); AdapterFieldInfo adapterFieldInfo = addAdapterFields(genericClassInfo, adapterBuilder, constructorBuilder, memberVariables, From 6b6add48a56ec700f185247e108e1dbd680460e7 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 15 May 2017 13:12:29 -0400 Subject: [PATCH 16/31] Fixing unit tests --- .../java/com/vimeo/stag/processor/utils/TypeUtils.java | 2 +- .../java/com/vimeo/stag/processor/TypeUtilsUnitTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java index d1a7c626..e598f975 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java @@ -173,7 +173,7 @@ public static List getTypeArguments(@Nullable TypeMirror t * @return true if the element is not generic and * contains no generic type arguments, false otherwise. */ - public static boolean isConcreteType(@NotNull TypeElement element) { + public static boolean isConcreteType(@NotNull Element element) { return isConcreteType(element.asType()); } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java index a1439906..948cd405 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java @@ -107,10 +107,10 @@ public void getInheritedType_isCorrect() throws Exception { public void getConcreteMembers_isCorrect() throws Exception { Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); assertNotNull(genericElement); - Map genericMembers = new HashMap<>(); + Map genericMembers = new HashMap<>(); for (Element element : genericElement.getEnclosedElements()) { if (element instanceof VariableElement) { - genericMembers.put(element, element.asType()); + genericMembers.put((VariableElement) element, element.asType()); } } @@ -123,14 +123,14 @@ public void getConcreteMembers_isCorrect() throws Exception { assertNotNull(genericType); - LinkedHashMap members = + LinkedHashMap members = TypeUtils.getConcreteMembers(concreteType, (TypeElement) types.asElement(genericType), genericMembers); TypeMirror stringType = Utils.getTypeMirrorFromClass(String.class); assertNotNull(stringType); - for (Entry entry : members.entrySet()) { + for (Entry entry : members.entrySet()) { if (entry.getKey().getSimpleName().contentEquals("testObject")) { assertTrue(entry.getValue().toString().equals(stringType.toString())); From a194493c28b232dbe8985b20c6b60d8c62668cde Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Mon, 15 May 2017 23:14:12 -0400 Subject: [PATCH 17/31] Switching away from variable name and toward FieldAccessor --- .../processor/generators/StagGenerator.java | 11 +- .../generators/TypeAdapterGenerator.java | 133 +++++++----------- .../generators/model/AnnotatedClass.java | 22 +-- .../model/accessor/MethodFieldAccessor.java | 2 +- .../vimeo/stag/processor/utils/TypeUtils.java | 12 +- .../stag/processor/TypeUtilsUnitTest.java | 23 +-- 6 files changed, 91 insertions(+), 112 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 148f568e..4d3b98bd 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java @@ -38,6 +38,7 @@ import com.vimeo.stag.processor.generators.model.AnnotatedClass; import com.vimeo.stag.processor.generators.model.ClassInfo; import com.vimeo.stag.processor.generators.model.SupportedTypesModel; +import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import com.vimeo.stag.processor.utils.FileGenUtils; import com.vimeo.stag.processor.utils.KnownTypeAdapterUtils; import com.vimeo.stag.processor.utils.Preconditions; @@ -58,7 +59,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; -import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; @@ -158,7 +158,8 @@ public StagGenerator(@NotNull String generatedPackageName, if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in StagGenerator : " + knownGenericType.toString()); } - Map memberVariables = annotatedClass.getMemberVariables(); + + Map memberVariables = annotatedClass.getMemberVariables(); boolean hasUnknownTypeFields = false; for (TypeMirror type : memberVariables.values()) { if (!checkKnownAdapters(type)) { @@ -180,10 +181,10 @@ public static String getGeneratedFactoryClassAndPackage(String generatedPackageN @NotNull private static String removeSpecialCharacters(TypeMirror typeMirror) { String typeString = typeMirror.toString(); - /** + /* * This is done to avoid generating duplicate method names, where the inner class type - *has same name (in different packages). In that case we are using the complete package name - *of the class to avoid class. We'll come up with a better solution for this case. + * has same name (in different packages). In that case we are using the complete package name + * of the class to avoid class. We'll come up with a better solution for this case. */ if (TypeUtils.isSupportedNative(typeMirror.toString())) { typeString = typeString.substring(typeString.lastIndexOf(".") + 1); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index bed069cb..18e0d061 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java @@ -26,7 +26,6 @@ import com.google.gson.Gson; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; -import com.google.gson.annotations.JsonAdapter; import com.google.gson.internal.bind.TreeTypeAdapter; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; @@ -47,6 +46,7 @@ import com.vimeo.stag.processor.generators.model.AnnotatedClass; import com.vimeo.stag.processor.generators.model.ClassInfo; import com.vimeo.stag.processor.generators.model.SupportedTypesModel; +import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import com.vimeo.stag.processor.utils.ElementUtils; import com.vimeo.stag.processor.utils.FileGenUtils; import com.vimeo.stag.processor.utils.KnownTypeAdapterUtils; @@ -63,14 +63,11 @@ import java.util.List; import java.util.Map; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.VariableElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.lang.model.type.TypeVariable; @@ -232,7 +229,7 @@ private static TypeName getAdapterFieldTypeName(@NotNull TypeMirror type) { @NotNull private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, - @NotNull Map elements, + @NotNull Map elements, @NotNull AdapterFieldInfo adapterFieldInfo) { MethodSpec.Builder builder = MethodSpec.methodBuilder("read") .addParameter(JsonReader.class, "reader") @@ -258,16 +255,17 @@ private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, "\t\tString name = reader.nextName();\n" + "\t\tswitch (name) {\n"); - final List nonNullFields = new ArrayList<>(); + final List nonNullFields = new ArrayList<>(); + + for (Map.Entry element : elements.entrySet()) { + final FieldAccessor fieldAccessor = element.getKey(); + String name = fieldAccessor.getJsonName(); - for (Map.Entry element : elements.entrySet()) { - String name = getJsonName(element.getKey()); - final String variableName = element.getKey().getSimpleName().toString(); final TypeMirror elementValue = element.getValue(); builder.addCode("\t\t\tcase \"" + name + "\":\n"); - String[] alternateJsonNames = getAlternateJsonNames(element.getKey()); + String[] alternateJsonNames = fieldAccessor.getAlternateJsonNames(); if (alternateJsonNames != null && alternateJsonNames.length > 0) { for (String alternateJsonName : alternateJsonNames) { builder.addCode("\t\t\tcase \"" + alternateJsonName + "\":\n"); @@ -278,24 +276,22 @@ private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, boolean isPrimitive = TypeUtils.isSupportedPrimitive(variableType); if (isPrimitive) { - builder.addCode("\t\t\t\tobject." + variableName + " = " + - adapterFieldInfo.getAdapterAccessor(elementValue, name) + ".read(reader, object." + variableName + ");"); + builder.addCode("\t\t\t\tobject." + + fieldAccessor.createSetterCode(adapterFieldInfo.getAdapterAccessor(elementValue, name) + + ".read(reader, object." + fieldAccessor.createGetterCode() + ")") + ";"); } else { - builder.addCode("\t\t\t\tobject." + variableName + " = " + - adapterFieldInfo.getAdapterAccessor(elementValue, name) + ".read(reader);"); + builder.addCode("\t\t\t\tobject." + fieldAccessor.createSetterCode(adapterFieldInfo.getAdapterAccessor(elementValue, name) + + ".read(reader)") + ";"); } builder.addCode("\n\t\t\t\tbreak;\n"); - runIfAnnotationSupported(element.getKey().getAnnotationMirrors(), new Runnable() { - @Override - public void run() { - if (!TypeUtils.isSupportedPrimitive(elementValue.toString())) { - nonNullFields.add(variableName); - } + if (fieldAccessor.requireNotNull()) { + if (!TypeUtils.isSupportedPrimitive(elementValue.toString())) { + nonNullFields.add(fieldAccessor); } - }); + } } builder.addCode("\t\t\tdefault:\n" + @@ -306,9 +302,9 @@ public void run() { '\n' + "\treader.endObject();\n"); - for (String nonNullField : nonNullFields) { - builder.addCode("\n\tif (object." + nonNullField + " == null) {"); - builder.addCode("\n\t\tthrow new java.io.IOException(\"" + nonNullField + " cannot be null\");"); + for (FieldAccessor nonNullField : nonNullFields) { + builder.addCode("\n\tif (object." + nonNullField.createGetterCode() + " == null) {"); + builder.addCode("\n\t\tthrow new java.io.IOException(\"" + nonNullField.createGetterCode() + " cannot be null\");"); builder.addCode("\n\t}\n\n"); } @@ -317,23 +313,7 @@ public void run() { return builder.build(); } - private static void runIfAnnotationSupported(@NotNull List annotationMirrors, - @NotNull Runnable runnable) { - for (AnnotationMirror annotationMirror : annotationMirrors) { - switch (annotationMirror.toString()) { - case "@javax.validation.constraints.NotNull": - case "@edu.umd.cs.findbugs.annotations.NonNull": - case "@javax.annotation.Nonnull": - case "@lombok.NonNull": - case "@org.eclipse.jdt.annotation.NonNull": - case "@org.jetbrains.annotations.NotNull": - case "@android.support.annotation.NonNull": - runnable.run(); - break; - } - } - } - + @NotNull private static String getFieldAccessorForKnownJsonAdapterType(@NotNull ExecutableElement adapterType, @NotNull TypeSpec.Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, @@ -679,43 +659,37 @@ private static String getAdapterForUnknownGenericType(@NotNull TypeMirror fieldT private AdapterFieldInfo addAdapterFields(@Nullable GenericClassInfo genericClassInfo, @NotNull Builder adapterBuilder, @NotNull MethodSpec.Builder constructorBuilder, - @NotNull Map memberVariables, + @NotNull Map memberVariables, @NotNull Map typeVarsMap, @NotNull StagGenerator stagGenerator) { AdapterFieldInfo result = new AdapterFieldInfo(memberVariables.size()); boolean hasUnknownGenericField = genericClassInfo != null && genericClassInfo.mHasUnknownVarTypeFields; - for (Map.Entry entry : memberVariables.entrySet()) { + for (Map.Entry entry : memberVariables.entrySet()) { + FieldAccessor fieldAccessor = entry.getKey(); TypeMirror fieldType = entry.getValue(); - JsonAdapter annotation = entry.getKey().getAnnotation(JsonAdapter.class); + String adapterAccessor = null; - if (null != annotation) { - // Using this trick to get the class type - // https://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/ - try { - annotation.value(); - } catch (MirroredTypeException mte) { - TypeMirror typeMirror = mte.getTypeMirror(); - ExecutableElement constructor = ElementUtils.getFirstConstructor(typeMirror); - TypeUtils.JsonAdapterType jsonAdapterType1 = TypeUtils.getJsonAdapterType(typeMirror); - if (constructor != null) { - String fieldAdapterAccessor = getFieldAccessorForKnownJsonAdapterType(constructor, adapterBuilder, constructorBuilder, fieldType, - jsonAdapterType1, result, annotation.nullSafe(), getJsonName(entry.getKey())); - result.addFieldToAccessor(getJsonName(entry.getKey()), fieldAdapterAccessor); - } else { - throw new IllegalStateException("Not supported @JsonAdapter value"); - } + TypeMirror optionalJsonAdapter = fieldAccessor.getJsonAdapterType(); + if (optionalJsonAdapter != null) { + ExecutableElement constructor = ElementUtils.getFirstConstructor(optionalJsonAdapter); + TypeUtils.JsonAdapterType jsonAdapterType1 = TypeUtils.getJsonAdapterType(optionalJsonAdapter); + if (constructor != null) { + String fieldAdapterAccessor = getFieldAccessorForKnownJsonAdapterType(constructor, adapterBuilder, constructorBuilder, fieldType, + jsonAdapterType1, result, fieldAccessor.isJsonAdapterNullSafe(), fieldAccessor.getJsonName()); + result.addFieldToAccessor(fieldAccessor.getJsonName(), fieldAdapterAccessor); + } else { + throw new IllegalStateException("Unsupported @JsonAdapter value: " + optionalJsonAdapter); } - } else if (hasUnknownGenericField && TypeUtils.containsTypeVarParams(fieldType)) { adapterAccessor = getAdapterForUnknownGenericType(fieldType, adapterBuilder, constructorBuilder, - typeVarsMap, result); + typeVarsMap, result); } else if (KnownTypeAdapterUtils.hasNativePrimitiveTypeAdapter(fieldType)) { adapterAccessor = KnownTypeAdapterUtils.getNativePrimitiveTypeAdapter(fieldType); } else { adapterAccessor = getAdapterAccessor(fieldType, adapterBuilder, constructorBuilder, - typeVarsMap, stagGenerator, + typeVarsMap, stagGenerator, result); if (null != adapterAccessor && adapterAccessor.startsWith("new ")) { @@ -740,7 +714,7 @@ private AdapterFieldInfo addAdapterFields(@Nullable GenericClassInfo genericClas @NotNull private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, - @NotNull Map memberVariables, + @NotNull Map memberVariables, @NotNull AdapterFieldInfo adapterFieldInfo) { final MethodSpec.Builder builder = MethodSpec.methodBuilder("write") .addParameter(JsonWriter.class, "writer") @@ -756,39 +730,38 @@ private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, builder.addStatement("return"); builder.endControlFlow(); - for (Map.Entry element : memberVariables.entrySet()) { - String name = getJsonName(element.getKey()); - final String variableName = element.getKey().getSimpleName().toString(); + for (Map.Entry element : memberVariables.entrySet()) { + FieldAccessor fieldAccessor = element.getKey(); + final String getterCode = fieldAccessor.createGetterCode(); + + String name = fieldAccessor.getJsonName(); String variableType = element.getValue().toString(); boolean isPrimitive = TypeUtils.isSupportedPrimitive(variableType); builder.addCode("\n"); if (!isPrimitive) { - builder.beginControlFlow("if (object." + variableName + " != null) "); + builder.beginControlFlow("if (object." + getterCode + " != null) "); } builder.addStatement("writer.name(\"" + name + "\")"); if (!isPrimitive) { builder.addStatement( adapterFieldInfo.getAdapterAccessor(element.getValue(), name) + ".write(writer, object." + - variableName + ")"); + getterCode + ")"); /* * If the element is annotated with NonNull annotation, throw {@link IOException} if it is null. */ - runIfAnnotationSupported(element.getKey().getAnnotationMirrors(), new Runnable() { - @Override - public void run() { - builder.endControlFlow(); - builder.beginControlFlow("else if (object." + variableName + " == null)"); - builder.addStatement("throw new java.io.IOException(\"" + variableName + - " cannot be null\")"); - } - }); + if (fieldAccessor.requireNotNull()) { + builder.endControlFlow(); + builder.beginControlFlow("else if (object." + getterCode + " == null)"); + builder.addStatement("throw new java.io.IOException(\"" + getterCode + + " cannot be null\")"); + } builder.endControlFlow(); } else { - builder.addStatement("writer.value(object." + variableName + ")"); + builder.addStatement("writer.value(object." + getterCode + ")"); } } @@ -867,7 +840,7 @@ public TypeSpec createTypeAdapterSpec(@NotNull StagGenerator stagGenerator) { if (null == annotatedClass) { throw new IllegalStateException("The AnnotatedClass class can't be null in TypeAdapterGenerator : " + typeMirror.toString()); } - Map memberVariables = annotatedClass.getMemberVariables(); + Map memberVariables = annotatedClass.getMemberVariables(); AdapterFieldInfo adapterFieldInfo = addAdapterFields(genericClassInfo, adapterBuilder, constructorBuilder, memberVariables, diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 050593cb..911eab78 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -26,6 +26,8 @@ import com.google.gson.annotations.SerializedName; import com.vimeo.stag.UseStag; import com.vimeo.stag.UseStag.FieldOption; +import com.vimeo.stag.processor.generators.model.accessor.DirectFieldAccessor; +import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import com.vimeo.stag.processor.utils.DebugLog; import com.vimeo.stag.processor.utils.MessagerUtils; import com.vimeo.stag.processor.utils.Preconditions; @@ -63,7 +65,7 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection mMemberVariables; + @NotNull private final LinkedHashMap mMemberVariables; @NotNull private final SupportedTypesModel mSupportedTypesModel; AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element) { @@ -74,7 +76,7 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection variableNames = new HashMap<>(element.getEnclosedElements().size()); + Map variableNames = new HashMap<>(element.getEnclosedElements().size()); TypeMirror inheritedType = TypeUtils.getInheritedType(element); UseStag useStag = element.getAnnotation(UseStag.class); @@ -96,11 +98,11 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, + LinkedHashMap inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, genericInheritedType.getElement(), genericInheritedType.getMemberVariables()); - for (Map.Entry entry : inheritedMemberVariables.entrySet()) { + for (Map.Entry entry : inheritedMemberVariables.entrySet()) { addMemberVariable(entry.getKey(), entry.getValue(), variableNames); } } @@ -115,9 +117,9 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection variableNames) { - VariableElement previousElement = variableNames.put(element.getSimpleName().toString(), element); + private void addMemberVariable(@NotNull FieldAccessor element, @NotNull TypeMirror typeMirror, + @NotNull Map variableNames) { + FieldAccessor previousElement = variableNames.put(element.createGetterCode(), element); if (null != previousElement) { mMemberVariables.remove(previousElement); MessagerUtils.logInfo("Ignoring inherited Member variable with the same variable name in class" + @@ -143,7 +145,7 @@ private static void checkModifiers(VariableElement variableElement, Set variableNames) { + @NotNull Map variableNames) { if (shouldIncludeField(element, fieldOption)) { Set modifiers = element.getModifiers(); if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.TRANSIENT)) { @@ -153,7 +155,7 @@ private void addToSupportedTypes(@NotNull VariableElement element, @NotNull Fiel } DebugLog.log(TAG, "\t\tMember variables - " + element.asType().toString()); - addMemberVariable(element, element.asType(), variableNames); + addMemberVariable(new DirectFieldAccessor(element), element.asType(), variableNames); } } } @@ -194,7 +196,7 @@ public TypeElement getElement() { * types. */ @NotNull - public LinkedHashMap getMemberVariables() { + public LinkedHashMap getMemberVariables() { return new LinkedHashMap<>(mMemberVariables); } } \ No newline at end of file diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java index c8f7e574..fa4c8437 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java @@ -25,7 +25,7 @@ public class MethodFieldAccessor extends FieldAccessor { @NotNull private final String mSetterName; @NotNull private final String mGetterName; - public MethodFieldAccessor(@NotNull VariableElement element) { + public MethodFieldAccessor(@NotNull VariableElement element) throws UnsupportedOperationException { super(element); mSetterName = findSetterMethodName(element); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java index e598f975..d3d0a6d9 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/utils/TypeUtils.java @@ -27,6 +27,7 @@ import com.google.gson.JsonSerializer; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; +import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -43,7 +44,6 @@ import javax.lang.model.element.Element; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.type.ArrayType; import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; @@ -337,18 +337,18 @@ public static boolean isEnum(@Nullable TypeElement element) { * inherited class. (to maintain the ordering) */ @NotNull - public static LinkedHashMap getConcreteMembers(@NotNull TypeMirror concreteInherited, - @NotNull TypeElement genericInherited, - @NotNull Map members) { + public static LinkedHashMap getConcreteMembers(@NotNull TypeMirror concreteInherited, + @NotNull TypeElement genericInherited, + @NotNull Map members) { DebugLog.log(TAG, "Inherited concrete type: " + concreteInherited.toString()); DebugLog.log(TAG, "Inherited generic type: " + genericInherited.asType().toString()); List concreteTypes = getParameterizedTypes(concreteInherited); List inheritedTypes = getParameterizedTypes(genericInherited); - LinkedHashMap map = new LinkedHashMap<>(); + LinkedHashMap map = new LinkedHashMap<>(); - for (Entry member : members.entrySet()) { + for (Entry member : members.entrySet()) { DebugLog.log(TAG, "\t\tEvaluating member - " + member.getValue().toString()); diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java index 948cd405..a20457b3 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java @@ -30,6 +30,8 @@ import com.vimeo.stag.processor.dummy.DummyGenericClass; import com.vimeo.stag.processor.dummy.DummyInheritedClass; import com.vimeo.stag.processor.dummy.DummyMapClass; +import com.vimeo.stag.processor.generators.model.accessor.DirectFieldAccessor; +import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import com.vimeo.stag.processor.utils.TypeUtils; import org.junit.Assert; @@ -107,10 +109,11 @@ public void getInheritedType_isCorrect() throws Exception { public void getConcreteMembers_isCorrect() throws Exception { Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); assertNotNull(genericElement); - Map genericMembers = new HashMap<>(); + + Map genericMembers = new HashMap<>(); for (Element element : genericElement.getEnclosedElements()) { if (element instanceof VariableElement) { - genericMembers.put((VariableElement) element, element.asType()); + genericMembers.put(new DirectFieldAccessor((VariableElement) element), element.asType()); } } @@ -123,46 +126,46 @@ public void getConcreteMembers_isCorrect() throws Exception { assertNotNull(genericType); - LinkedHashMap members = + LinkedHashMap members = TypeUtils.getConcreteMembers(concreteType, (TypeElement) types.asElement(genericType), genericMembers); TypeMirror stringType = Utils.getTypeMirrorFromClass(String.class); assertNotNull(stringType); - for (Entry entry : members.entrySet()) { - if (entry.getKey().getSimpleName().contentEquals("testObject")) { + for (Entry entry : members.entrySet()) { + if (entry.getKey().createGetterCode().contentEquals("testObject = ")) { assertTrue(entry.getValue().toString().equals(stringType.toString())); - } else if (entry.getKey().getSimpleName().contentEquals("testList")) { + } else if (entry.getKey().createGetterCode().contentEquals("testList = ")) { assertTrue(entry.getValue() .toString() .equals(types.getDeclaredType(Utils.getElementFromClass(ArrayList.class), stringType).toString())); - } else if (entry.getKey().getSimpleName().contentEquals("testMap")) { + } else if (entry.getKey().createGetterCode().contentEquals("testMap = ")) { assertTrue(entry.getValue() .toString() .equals(types.getDeclaredType(Utils.getElementFromClass(HashMap.class), stringType, stringType).toString())); - } else if (entry.getKey().getSimpleName().contentEquals("testSet")) { + } else if (entry.getKey().createGetterCode().contentEquals("testSet = ")) { assertTrue(entry.getValue() .toString() .equals(types.getDeclaredType(Utils.getElementFromClass(HashSet.class), stringType) .toString())); - } else if (entry.getKey().getSimpleName().contentEquals("testArrayMap")) { + } else if (entry.getKey().createGetterCode().contentEquals("testArrayMap = ")) { TypeMirror listString = types.getDeclaredType(Utils.getElementFromClass(List.class), stringType); assertTrue(entry.getValue() .toString() .equals(types.getDeclaredType(Utils.getElementFromClass(HashMap.class), stringType, listString) .toString())); - } else if (entry.getKey().getSimpleName().contentEquals("testListMap")) { + } else if (entry.getKey().createGetterCode().contentEquals("testListMap = ")) { TypeMirror mapStringString = types.getDeclaredType(Utils.getElementFromClass(Map.class), stringType, stringType); assertTrue(entry.getValue() .toString() From 8d1de782488f879adc57a290ca668718e33650ee Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Mon, 15 May 2017 23:28:34 -0400 Subject: [PATCH 18/31] Adding support for kotlin and getters/setters instead of just field access --- settings.gradle | 2 +- .../generators/model/AnnotatedClass.java | 30 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/settings.gradle b/settings.gradle index 04f50771..9d7ce27f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model'//, ':sample-kotlin-model' +include ':stag-library', ':stag-library-compiler', ':sample', ':sample-model', ':sample-java-model', ':sample-kotlin-model' diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 911eab78..026d8ce8 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -28,6 +28,7 @@ import com.vimeo.stag.UseStag.FieldOption; import com.vimeo.stag.processor.generators.model.accessor.DirectFieldAccessor; import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; +import com.vimeo.stag.processor.generators.model.accessor.MethodFieldAccessor; import com.vimeo.stag.processor.utils.DebugLog; import com.vimeo.stag.processor.utils.MessagerUtils; import com.vimeo.stag.processor.utils.Preconditions; @@ -128,20 +129,9 @@ private void addMemberVariable(@NotNull FieldAccessor element, @NotNull TypeMirr mMemberVariables.put(element, typeMirror); } - private static void checkModifiers(VariableElement variableElement, Set modifiers) { - if (!modifiers.contains(Modifier.STATIC)) { - if (modifiers.contains(Modifier.FINAL)) { - MessagerUtils.reportError("Unable to access field \"" + - variableElement.getSimpleName().toString() + "\" in class " + - variableElement.getEnclosingElement().asType() + - ", field must not be final.", variableElement); - } else if (modifiers.contains(Modifier.PRIVATE)) { - MessagerUtils.reportError("Unable to access field \"" + - variableElement.getSimpleName().toString() + "\" in class " + - variableElement.getEnclosingElement().asType() + - ", field must not be private.", variableElement); - } - } + private static boolean checkPrivateFinalModifiers(@NotNull Set modifiers) { + Preconditions.checkTrue(!modifiers.contains(Modifier.STATIC)); + return modifiers.contains(Modifier.FINAL) || modifiers.contains(Modifier.PRIVATE); } private void addToSupportedTypes(@NotNull VariableElement element, @NotNull FieldOption fieldOption, @@ -149,13 +139,21 @@ private void addToSupportedTypes(@NotNull VariableElement element, @NotNull Fiel if (shouldIncludeField(element, fieldOption)) { Set modifiers = element.getModifiers(); if (!modifiers.contains(Modifier.STATIC) && !modifiers.contains(Modifier.TRANSIENT)) { - checkModifiers(element, modifiers); + if (!TypeUtils.isAbstract(element)) { mSupportedTypesModel.checkAndAddExternalAdapter(element); } DebugLog.log(TAG, "\t\tMember variables - " + element.asType().toString()); - addMemberVariable(new DirectFieldAccessor(element), element.asType(), variableNames); + if (checkPrivateFinalModifiers(modifiers)) { + try { + addMemberVariable(new MethodFieldAccessor(element), element.asType(), variableNames); + } catch (UnsupportedOperationException exception) { + MessagerUtils.reportError("Unable to find getter/setter for private/final field", element); + } + } else { + addMemberVariable(new DirectFieldAccessor(element), element.asType(), variableNames); + } } } } From 8a82e57a693425409337d75df30ff8a43643db26 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Mon, 15 May 2017 23:36:43 -0400 Subject: [PATCH 19/31] Updating build script for kotlin module --- fastlane/Fastfile | 3 ++- sample/build.gradle | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f9ca047c..ca1985f0 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -39,12 +39,13 @@ platform :android do "stag-library/build/test-results/test/*.xml", "stag-library-compiler/build/test-results/test/*.xml", "sample-java-model/build/test-results/test/*.xml", + "sample-kotlin-model/build/test-results/test/*.xml", "sample/build/test-results/testDebugUnitTest/*.xml", "sample-model/build/test-results/testDebugUnitTest/*.xml" ] begin gradle( - task: "stag-library:test stag-library-compiler:test sample:test sample-model:test sample-java-model:test sample:build" + task: "stag-library:test stag-library-compiler:test sample:test sample-model:test sample-java-model:test sample-kotlin-model:test sample:build" ) rescue => error begin diff --git a/sample/build.gradle b/sample/build.gradle index 01dc6f2e..cebc197f 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -45,7 +45,7 @@ dependencies { compile project(':sample-model') compile project(':sample-java-model') -// compile project(':sample-kotlin-model') + compile project(':sample-kotlin-model') compile project(':stag-library') annotationProcessor project(':stag-library-compiler') From b25432de3a40a5d6c4a035b0d195029ea5d98e61 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Mon, 15 May 2017 23:48:17 -0400 Subject: [PATCH 20/31] Fixing final/private logic and fixing sample build Removing kotlin as sample dependency until build is resolved --- .../com/vimeo/dummy/sample_kotlin/KotlinSamples.kt | 2 ++ .../kotlin/com/vimeo/dummy/sample_kotlin/Test.kt | 11 ----------- sample/build.gradle | 4 +++- .../processor/generators/model/AnnotatedClass.java | 12 ++++++++++-- 4 files changed, 15 insertions(+), 14 deletions(-) delete mode 100644 sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt index 931f31bd..fbfe92bc 100644 --- a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt @@ -3,6 +3,8 @@ package com.vimeo.dummy.sample_kotlin import com.vimeo.stag.UseStag /** + * Test kotlin model + * * Created by restainoa on 5/8/17. */ @UseStag diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt deleted file mode 100644 index 27a04230..00000000 --- a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/Test.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.vimeo.dummy.sample_kotlin - -/** - * Created by restainoa on 5/8/17. - */ -class Test - -fun accessTest() { - val kot : KotlinSamples = KotlinSamples() - kot.stringField = "Test" -} \ No newline at end of file diff --git a/sample/build.gradle b/sample/build.gradle index cebc197f..c3dad531 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -45,7 +45,9 @@ dependencies { compile project(':sample-model') compile project(':sample-java-model') - compile project(':sample-kotlin-model') + + // TODO add kotlin sample model as dependency when build issues are resolved + // compile project(':sample-kotlin-model') compile project(':stag-library') annotationProcessor project(':stag-library-compiler') diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index 026d8ce8..f2547436 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -129,8 +129,16 @@ private void addMemberVariable(@NotNull FieldAccessor element, @NotNull TypeMirr mMemberVariables.put(element, typeMirror); } - private static boolean checkPrivateFinalModifiers(@NotNull Set modifiers) { + private static boolean checkPrivateFinalModifiers(@NotNull VariableElement variableElement, @NotNull Set modifiers) { Preconditions.checkTrue(!modifiers.contains(Modifier.STATIC)); + + if (modifiers.contains(Modifier.FINAL)) { + MessagerUtils.reportError("Unable to access field \"" + + variableElement.getSimpleName().toString() + "\" in class " + + variableElement.getEnclosingElement().asType() + + ", field must not be final.", variableElement); + } + return modifiers.contains(Modifier.FINAL) || modifiers.contains(Modifier.PRIVATE); } @@ -145,7 +153,7 @@ private void addToSupportedTypes(@NotNull VariableElement element, @NotNull Fiel } DebugLog.log(TAG, "\t\tMember variables - " + element.asType().toString()); - if (checkPrivateFinalModifiers(modifiers)) { + if (checkPrivateFinalModifiers(element, modifiers)) { try { addMemberVariable(new MethodFieldAccessor(element), element.asType(), variableNames); } catch (UnsupportedOperationException exception) { From e8aa1f7c0984783a2a0c060f4d084569ad1ddb35 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Tue, 16 May 2017 00:02:16 -0400 Subject: [PATCH 21/31] Picking up kotlin test results --- fastlane/Fastfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index ca1985f0..a9f83772 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -39,13 +39,13 @@ platform :android do "stag-library/build/test-results/test/*.xml", "stag-library-compiler/build/test-results/test/*.xml", "sample-java-model/build/test-results/test/*.xml", - "sample-kotlin-model/build/test-results/test/*.xml", + "sample-kotlin-model/build/test-results/testDebugUnitTest/*.xml", "sample/build/test-results/testDebugUnitTest/*.xml", "sample-model/build/test-results/testDebugUnitTest/*.xml" ] begin gradle( - task: "stag-library:test stag-library-compiler:test sample:test sample-model:test sample-java-model:test sample-kotlin-model:test sample:build" + task: "sample:build stag-library:test stag-library-compiler:test sample:test sample-model:test sample-java-model:test sample-kotlin-model:test" ) rescue => error begin From 5466b9fa191fe50756cf7085510545869cd2efed Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Tue, 16 May 2017 21:07:45 -0400 Subject: [PATCH 22/31] Fixing kotlin module compilation as part of sample --- sample/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sample/build.gradle b/sample/build.gradle index c3dad531..223a1db5 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'com.android.application' - buildscript { repositories { jcenter() @@ -46,8 +45,9 @@ dependencies { compile project(':sample-model') compile project(':sample-java-model') - // TODO add kotlin sample model as dependency when build issues are resolved - // compile project(':sample-kotlin-model') + compile(project(':sample-kotlin-model')) { + exclude group: 'org.jetbrains', module: 'annotations' + } compile project(':stag-library') annotationProcessor project(':stag-library-compiler') From eced25c4a88c8343d25a0486dcb74ce14f1a2d85 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Tue, 16 May 2017 21:50:48 -0400 Subject: [PATCH 23/31] Test class for getters and setters in java classes --- .../sample_java_model/PrivateMembers.java | 49 +++++++++++++++++++ .../sample_java_model/PrivateMembersTest.java | 17 +++++++ .../StagProcessorFunctionalTest.java | 2 +- 3 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java create mode 100644 sample-java-model/src/test/java/com/vimeo/sample_java_model/PrivateMembersTest.java diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java new file mode 100644 index 00000000..ec04561d --- /dev/null +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java @@ -0,0 +1,49 @@ +package com.vimeo.sample_java_model; + +import com.google.gson.annotations.SerializedName; +import com.vimeo.stag.UseStag; + +import org.jetbrains.annotations.NotNull; + +/** + * Model testing private members with + * public setters. + *

+ * Created by anthonycr on 5/16/17. + */ +@UseStag +public class PrivateMembers { + + @NotNull + private String testString; + + @SerializedName("testString2") + private String anotherTestString; + + private Object testObject; + + @NotNull + public String getTestString() { + return testString; + } + + public void setTestString(@NotNull String testString) { + this.testString = testString; + } + + public String getAnotherTestString() { + return anotherTestString; + } + + public void setAnotherTestString(String anotherTestString) { + this.anotherTestString = anotherTestString; + } + + public Object getTestObject() { + return testObject; + } + + public void setTestObject(Object testObject) { + this.testObject = testObject; + } +} diff --git a/sample-java-model/src/test/java/com/vimeo/sample_java_model/PrivateMembersTest.java b/sample-java-model/src/test/java/com/vimeo/sample_java_model/PrivateMembersTest.java new file mode 100644 index 00000000..bf7d89ac --- /dev/null +++ b/sample-java-model/src/test/java/com/vimeo/sample_java_model/PrivateMembersTest.java @@ -0,0 +1,17 @@ +package com.vimeo.sample_java_model; + +import org.junit.Test; + +/** + * Tests for {@link PrivateMembers}. + *

+ * Created by anthonycr on 5/16/17. + */ +public class PrivateMembersTest { + + @Test + public void typeAdapterWasGenerated() throws Exception { + Utils.verifyTypeAdapterGeneration(PrivateMembers.class); + } + +} \ No newline at end of file diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.java index a25f0461..246c010f 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.java @@ -53,7 +53,7 @@ public void finalFieldsInAnnotatedClassReportsAsAnError() throws Exception { * from generated type adapters. */ @Test - public void privateFieldsInAnnotatedClassReportsAsAnError() throws Exception { + public void privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() throws Exception { assertCompilationReturned(Diagnostic.Kind.ERROR, 8, compileTestCase("bad/PrivateFields")); } From c2d3442b7b045a9f3247661a3fba58e938a98b4d Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Tue, 16 May 2017 22:05:32 -0400 Subject: [PATCH 24/31] Improving kotlin sample --- .../com/vimeo/dummy/sample_kotlin/KotlinSamples.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt index fbfe92bc..32fc9824 100644 --- a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamples.kt @@ -1,5 +1,6 @@ package com.vimeo.dummy.sample_kotlin +import com.google.gson.annotations.SerializedName import com.vimeo.stag.UseStag /** @@ -11,5 +12,14 @@ import com.vimeo.stag.UseStag class KotlinSamples { var stringField: String? = null + var nonNullStringField: String = "default" + + var intField: Int? = null + + var longField: Long = 1 + + @SerializedName("boolean_field") + var booleanField: Boolean? = null + var testField: Any? = null } \ No newline at end of file From 51b1433fc11b496a4082d763687d442ace22bc72 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 17 May 2017 21:04:56 -0400 Subject: [PATCH 25/31] Updating readme with kotlin and private member support --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9ebc5e8f..c9aabdb6 100644 --- a/README.md +++ b/README.md @@ -118,7 +118,14 @@ Last but not the least, Stag is almost in parity with GSON. ## Stag Rules -1. Make sure the member variables of your model class are not private (should be public, protected, or package-local visibility) +1. Make sure that any private member variables have setters/getters following these naming rules: +```java +private String myString; + +public String getMyString() { ... } + +public void setMyString(String parameter) { ... } +``` 2. Make sure your model class is not private and has a zero argument non-private constructor 3. Annotate the classes with `@UseStag` annotation. This will process all the member variables of the class, which makes it easy to use. 4. Use the `@SerializedName("key")` annotation to give the variables a different JSON name. (same as GSON) @@ -130,23 +137,30 @@ See the [example below](#example) or the [sample app](sample) to get more info o ## Example +#### Java ```java @UseStag public class Deer { + + // Private fields require getters and setters @SerializedName("name") - String mName; // mName = json value with key "name" + private String name; // name = json value with key "name" @SerializedName("species") - String mSpecies; // mSpecies = json value with key "species" + String species; // species = json value with key "species" @SerializedName("age") - int mAge; // mAge = json value with key "age" + int age; // age = json value with key "age" @SerializedName("points") - int mPoints; // mPoints = json value with key "points" + int points; // points = json value with key "points" @SerializedName("weight") - float mWeight; // mWeight = json value with key "weight" + float weight; // weight = json value with key "weight" + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } } @UseStag @@ -160,7 +174,44 @@ public class Herd { Map data_map; // data_map = json value with key "data_map" } +``` + +#### Kotlin +```kotlin +@UseStag +class Deer { + + @SerializedName("name") + var name: String? = null // name = json value with key "name" + + @SerializedName("species") + var species: String? = null // species = json value with key "species" + + @SerializedName("age") + var age: Int = 0 // age = json value with key "age" + @SerializedName("points") + var points: Int = 0 // points = json value with key "points" + + @SerializedName("weight") + var weight: Float = 0.toFloat() // weight = json value with key "weight" +} + +@UseStag +class Herd { + + // non null fields will be honored buy throwing an exception if the field is null + @SerializedName("data_list") + var data: ArrayList = ArrayList() // data = json value with key "data_list" + + var data_list_copy: List? = null // data_list_copy = json value with key "data_list_copy" + + var data_map: Map? = null // data_map = json value with key "data_map" +} +``` + +#### Consuming Model in Java +```java /** * The class where you receive JSON * containing a list of Deer objects. @@ -176,7 +227,6 @@ MyParsingClass { return gson.fromJson(json, Herd.class); } } - ``` ## Future Enhancements From 7611de9369d4cb9b06661bbf7d4a0e40a88b2947 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Wed, 17 May 2017 21:42:57 -0400 Subject: [PATCH 26/31] Adding support for Hungarian notation for private members --- README.md | 12 +++- sample-java-model/build.gradle | 5 +- .../sample_java_model/NativeJavaModel.java | 60 +++++++++++++++++-- .../NativeJavaModelExtension.java | 9 ++- ...veJavaModelExtensionWithoutAnnotation.java | 9 ++- .../sample_java_model/PrivateMembers.java | 18 +++--- .../vimeo/stag/processor/StagProcessor.java | 25 ++++++-- .../generators/model/AnnotatedClass.java | 28 +++++---- .../generators/model/SupportedTypesModel.java | 11 ++-- .../model/accessor/MethodFieldAccessor.java | 40 +++++++++---- 10 files changed, 166 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index c9aabdb6..eec22839 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ dependencies { // Optional annotation processor arguments (see below) apt { arguments { + stagAssumeHungarianNotation true stagGeneratedPackageName "com.vimeo.sample.stag.generated" stagDebug true } @@ -74,8 +75,9 @@ android { javaCompileOptions { annotationProcessorOptions { arguments = [ - stagGeneratedPackageName: 'com.vimeo.sample.stag.generated', - stagDebug : 'true' + stagAssumeHungarianNotation: 'true' + stagGeneratedPackageName : 'com.vimeo.sample.stag.generated', + stagDebug : 'true' ] } } @@ -89,7 +91,11 @@ android { by passing it as an argument to the apt compiler. - `stagDebug`: Turn on debugging in Stag. This will cause Stag to spit out a lot of output into the gradle console. This can aid you in figuring out what class is giving you trouble, if the exception gradle prints out - isn't sufficient. + isn't sufficient. Default is false. + - `stagAssumeHungarianNotation`: If your Java member variables are private and Stag needs to use setters and getters to access the field, + Stag will look for members named `set[variable_name]` and `get[variable_name]`. If your member variables are named using Hungarian notation, + then you will need to pass true to this parameter so that for a field named `mField`, Stag will look for `setField` and `getField` instead + of `setMField` and `getMField`. Default is false. ## Features diff --git a/sample-java-model/build.gradle b/sample-java-model/build.gradle index 44efac19..3ef2e2bf 100644 --- a/sample-java-model/build.gradle +++ b/sample-java-model/build.gradle @@ -14,8 +14,9 @@ gradle.projectsEvaluated { sourceCompatibility = '1.7' targetCompatibility = '1.7' options.compilerArgs << "-Xlint:all,-deprecation,-serial,-processing,-options" << "-Werror" \ - << "-AstagGeneratedPackageName=com.vimeo.sample_java_model.stag.generated" \ - << "-AstagDebug=true" + << "-AstagGeneratedPackageName=com.vimeo.sample_java_model.stag.generated" \ + << "-AstagDebug=true" \ + << "-AstagAssumeHungarianNotation=true" options.setIncremental true } } diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java index 9cd2282c..9e908c00 100644 --- a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java @@ -5,29 +5,77 @@ @UseStag public class NativeJavaModel { - String topLevel; + private String mTopLevel; + + public String getTopLevel() { + return mTopLevel; + } + + public void setTopLevel(String mTopLevel) { + this.mTopLevel = mTopLevel; + } @UseStag public static class Nested { - String nested; + String mNested; + + public String getNested() { + return mNested; + } + + public void setNested(String mNested) { + this.mNested = mNested; + } } public static class NestedWithoutAnnotation { - String nestedWithoutAnnotation; + String mNestedWithoutAnnotation; + + public String getNestedWithoutAnnotation() { + return mNestedWithoutAnnotation; + } + + public void setNestedWithoutAnnotation(String mNestedWithoutAnnotation) { + this.mNestedWithoutAnnotation = mNestedWithoutAnnotation; + } } @UseStag public static class NestedExtension extends NativeJavaModel { - String nestedExtension; + String mNestedExtension; + + public String getNestedExtension() { + return mNestedExtension; + } + + public void setNestedExtension(String mNestedExtension) { + this.mNestedExtension = mNestedExtension; + } } public static class NestedExtensionWithoutAnnotation extends NativeJavaModel { - String nestedExtensionWithoutAnnotation; + String mNestedExtensionWithoutAnnotation; + + public String getNestedExtensionWithoutAnnotation() { + return mNestedExtensionWithoutAnnotation; + } + + public void setNestedExtensionWithoutAnnotation(String mNestedExtensionWithoutAnnotation) { + this.mNestedExtensionWithoutAnnotation = mNestedExtensionWithoutAnnotation; + } } @UseStag public static class NestedExtensionFromNoAnnotation extends NestedWithoutAnnotation { - String nestedExtensionFromNoAnnotation; + String mNestedExtensionFromNoAnnotation; + + public String getNestedExtensionFromNoAnnotation() { + return mNestedExtensionFromNoAnnotation; + } + + public void setNestedExtensionFromNoAnnotation(String mNestedExtensionFromNoAnnotation) { + this.mNestedExtensionFromNoAnnotation = mNestedExtensionFromNoAnnotation; + } } } diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtension.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtension.java index 32bdb77f..b61d582a 100644 --- a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtension.java +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtension.java @@ -9,6 +9,13 @@ @UseStag public class NativeJavaModelExtension extends NativeJavaModel { - String additionalField; + private String mAdditionalField; + public String getAdditionalField() { + return mAdditionalField; + } + + public void setAdditionalField(String additionalField) { + this.mAdditionalField = additionalField; + } } diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtensionWithoutAnnotation.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtensionWithoutAnnotation.java index 57eee7a4..18414317 100644 --- a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtensionWithoutAnnotation.java +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModelExtensionWithoutAnnotation.java @@ -6,6 +6,13 @@ */ public class NativeJavaModelExtensionWithoutAnnotation extends NativeJavaModel { - String additionalField2; + private String mAdditionalField2; + public String getAdditionalField2() { + return mAdditionalField2; + } + + public void setAdditionalField2(String mAdditionalField2) { + this.mAdditionalField2 = mAdditionalField2; + } } diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java index ec04561d..1e049645 100644 --- a/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/PrivateMembers.java @@ -15,35 +15,35 @@ public class PrivateMembers { @NotNull - private String testString; + private String mTestString; @SerializedName("testString2") - private String anotherTestString; + private String mAnotherTestString; - private Object testObject; + private Object mTestObject; @NotNull public String getTestString() { - return testString; + return mTestString; } public void setTestString(@NotNull String testString) { - this.testString = testString; + this.mTestString = testString; } public String getAnotherTestString() { - return anotherTestString; + return mAnotherTestString; } public void setAnotherTestString(String anotherTestString) { - this.anotherTestString = anotherTestString; + this.mAnotherTestString = anotherTestString; } public Object getTestObject() { - return testObject; + return mTestObject; } public void setTestObject(Object testObject) { - this.testObject = testObject; + this.mTestObject = testObject; } } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java index 527305ea..f28c6301 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/StagProcessor.java @@ -35,6 +35,7 @@ import com.vimeo.stag.processor.generators.model.AnnotatedClass; import com.vimeo.stag.processor.generators.model.ClassInfo; import com.vimeo.stag.processor.generators.model.SupportedTypesModel; +import com.vimeo.stag.processor.generators.model.accessor.MethodFieldAccessor.Notation; import com.vimeo.stag.processor.utils.DebugLog; import com.vimeo.stag.processor.utils.ElementUtils; import com.vimeo.stag.processor.utils.FileGenUtils; @@ -64,13 +65,14 @@ @AutoService(Processor.class) @SupportedAnnotationTypes(value = {"com.vimeo.stag.UseStag"}) -@SupportedOptions(value = {StagProcessor.OPTION_PACKAGE_NAME, StagProcessor.OPTION_DEBUG}) +@SupportedOptions(value = {StagProcessor.OPTION_PACKAGE_NAME, StagProcessor.OPTION_DEBUG, StagProcessor.OPTION_HUNGARIAN_NOTATION}) @SupportedSourceVersion(SourceVersion.RELEASE_7) public final class StagProcessor extends AbstractProcessor { public static volatile boolean DEBUG; static final String OPTION_DEBUG = "stagDebug"; static final String OPTION_PACKAGE_NAME = "stagGeneratedPackageName"; + static final String OPTION_HUNGARIAN_NOTATION = "stagAssumeHungarianNotation"; private static final String DEFAULT_GENERATED_PACKAGE_NAME = "com.vimeo.stag.generated"; private boolean mHasBeenProcessed; @@ -88,6 +90,14 @@ private static boolean getDebugBoolean(@NotNull ProcessingEnvironment processing return false; } + private static boolean getAssumeHungarianNotation(@NotNull ProcessingEnvironment processingEnvironment) { + String debugString = processingEnvironment.getOptions().get(OPTION_HUNGARIAN_NOTATION); + if (debugString != null) { + return Boolean.valueOf(debugString); + } + return false; + } + @NotNull private static String getOptionalPackageName(@NotNull ProcessingEnvironment processingEnvironment) { String packageName = processingEnvironment.getOptions().get(OPTION_PACKAGE_NAME); @@ -109,13 +119,17 @@ public boolean process(Set annotations, RoundEnvironment String packageName = getOptionalPackageName(processingEnv); + boolean assumeHungarianNotation = getAssumeHungarianNotation(processingEnv); + TypeUtils.initialize(processingEnv.getTypeUtils()); ElementUtils.initialize(processingEnv.getElementUtils()); MessagerUtils.initialize(processingEnv.getMessager()); String stagFactoryGeneratedName = StagGenerator.getGeneratedFactoryClassAndPackage(packageName); - SupportedTypesModel supportedTypesModel = new SupportedTypesModel(stagFactoryGeneratedName); + Notation notation = assumeHungarianNotation ? Notation.HUNGARIAN : Notation.STANDARD; + + SupportedTypesModel supportedTypesModel = new SupportedTypesModel(stagFactoryGeneratedName, notation); DebugLog.log("\nBeginning @UseStag annotation processing\n"); @@ -129,7 +143,8 @@ public boolean process(Set annotations, RoundEnvironment Set supportedTypes = AnnotatedClass.annotatedClassToTypeMirror(supportedTypesModel.getSupportedTypes()); try { supportedTypes.addAll(KnownTypeAdapterFactoriesUtils.loadKnownTypes(processingEnv, packageName)); - } catch (Exception ignored) {} + } catch (Exception ignored) { + } Set externalAdapterInfoSet = supportedTypesModel.getExternalSupportedAdapters(); @@ -170,8 +185,8 @@ private void generateTypeAdapter(@NotNull SupportedTypesModel supportedTypesMode ClassInfo classInfo = new ClassInfo(element.asType()); AdapterGenerator independentAdapter = element.getKind() == ElementKind.ENUM ? - new EnumTypeAdapterGenerator(classInfo, element) : - new TypeAdapterGenerator(supportedTypesModel, classInfo); + new EnumTypeAdapterGenerator(classInfo, element) : + new TypeAdapterGenerator(supportedTypesModel, classInfo); // Create the type spec TypeSpec typeAdapterSpec = independentAdapter.createTypeAdapterSpec(stagGenerator); diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java index f2547436..581ef122 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/AnnotatedClass.java @@ -29,6 +29,7 @@ import com.vimeo.stag.processor.generators.model.accessor.DirectFieldAccessor; import com.vimeo.stag.processor.generators.model.accessor.FieldAccessor; import com.vimeo.stag.processor.generators.model.accessor.MethodFieldAccessor; +import com.vimeo.stag.processor.generators.model.accessor.MethodFieldAccessor.Notation; import com.vimeo.stag.processor.utils.DebugLog; import com.vimeo.stag.processor.utils.MessagerUtils; import com.vimeo.stag.processor.utils.Preconditions; @@ -68,12 +69,19 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection mMemberVariables; @NotNull private final SupportedTypesModel mSupportedTypesModel; + @NotNull private final Notation mNamingNotation; - AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element) { - this(supportedTypesModel, element, null); + AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, + @NotNull TypeElement element, + @NotNull Notation namingNotation) { + this(supportedTypesModel, element, namingNotation, null); } - AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, @NotNull TypeElement element, @Nullable FieldOption childFieldOption) { + AnnotatedClass(@NotNull SupportedTypesModel supportedTypesModel, + @NotNull TypeElement element, + @NotNull Notation namingNotation, + @Nullable FieldOption childFieldOption) { + mNamingNotation = namingNotation; mSupportedTypesModel = supportedTypesModel; mType = element.asType(); mElement = element; @@ -100,8 +108,8 @@ public static Set annotatedClassToTypeMirror(@NotNull Collection inheritedMemberVariables = TypeUtils.getConcreteMembers(inheritedType, - genericInheritedType.getElement(), - genericInheritedType.getMemberVariables()); + genericInheritedType.getElement(), + genericInheritedType.getMemberVariables()); for (Map.Entry entry : inheritedMemberVariables.entrySet()) { addMemberVariable(entry.getKey(), entry.getValue(), variableNames); @@ -124,7 +132,7 @@ private void addMemberVariable(@NotNull FieldAccessor element, @NotNull TypeMirr if (null != previousElement) { mMemberVariables.remove(previousElement); MessagerUtils.logInfo("Ignoring inherited Member variable with the same variable name in class" + - element.toString() + ", with variable name " + previousElement.asType().toString()); + element.toString() + ", with variable name " + previousElement.asType().toString()); } mMemberVariables.put(element, typeMirror); } @@ -134,9 +142,9 @@ private static boolean checkPrivateFinalModifiers(@NotNull VariableElement varia if (modifiers.contains(Modifier.FINAL)) { MessagerUtils.reportError("Unable to access field \"" + - variableElement.getSimpleName().toString() + "\" in class " + - variableElement.getEnclosingElement().asType() + - ", field must not be final.", variableElement); + variableElement.getSimpleName().toString() + "\" in class " + + variableElement.getEnclosingElement().asType() + + ", field must not be final.", variableElement); } return modifiers.contains(Modifier.FINAL) || modifiers.contains(Modifier.PRIVATE); @@ -155,7 +163,7 @@ private void addToSupportedTypes(@NotNull VariableElement element, @NotNull Fiel if (checkPrivateFinalModifiers(element, modifiers)) { try { - addMemberVariable(new MethodFieldAccessor(element), element.asType(), variableNames); + addMemberVariable(new MethodFieldAccessor(element, mNamingNotation), element.asType(), variableNames); } catch (UnsupportedOperationException exception) { MessagerUtils.reportError("Unable to find getter/setter for private/final field", element); } diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java index 19cf1d38..2bc2a03f 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/SupportedTypesModel.java @@ -25,6 +25,7 @@ import com.vimeo.stag.UseStag.FieldOption; import com.vimeo.stag.processor.generators.ExternalAdapterInfo; +import com.vimeo.stag.processor.generators.model.accessor.MethodFieldAccessor.Notation; import com.vimeo.stag.processor.utils.Preconditions; import com.vimeo.stag.processor.utils.TypeUtils; @@ -46,9 +47,11 @@ public final class SupportedTypesModel { @NotNull private final Map mKnownInheritedTypesMap = new HashMap<>(); @NotNull private final Set mExternalSupportedAdapters = new HashSet<>(); @NotNull private final String mGeneratedStagFactoryName; + @NotNull private final Notation mNamingNotation; - public SupportedTypesModel(@NotNull String generatedStagFactoryName) { + public SupportedTypesModel(@NotNull String generatedStagFactoryName, @NotNull Notation namingNotation) { mGeneratedStagFactoryName = generatedStagFactoryName; + mNamingNotation = namingNotation; } /** @@ -106,7 +109,7 @@ public AnnotatedClass addToKnownInheritedType(@NotNull TypeMirror type, @Nullabl if (null == model) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type), childFieldOption); + model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type), mNamingNotation, childFieldOption); mKnownInheritedTypesMap.put(outerClassType, model); } } @@ -130,7 +133,7 @@ public AnnotatedClass addSupportedType(@NotNull TypeMirror type) { if (model == null) { model = mKnownInheritedTypesMap.get(outerClassType); if (null == model) { - model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type)); + model = new AnnotatedClass(this, TypeUtils.safeTypeMirrorToTypeElement(type), mNamingNotation); } addSupportedType(model); } @@ -154,7 +157,7 @@ public void checkAndAddExternalAdapter(@NotNull VariableElement variableElement) Preconditions.checkNotNull(mGeneratedStagFactoryName); // If this is of a type which is not part of this module, but generated by Stag, we should use it. ExternalAdapterInfo.addExternalAdapters(mGeneratedStagFactoryName, variableElement.asType(), - mExternalSupportedAdapters); + mExternalSupportedAdapters); } @NotNull diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java index fa4c8437..0bfb3e2b 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java @@ -22,14 +22,24 @@ */ public class MethodFieldAccessor extends FieldAccessor { + /** + * Field naming notation, + * used to determine the + * names of the accessor methods. + */ + public enum Notation { + STANDARD, + HUNGARIAN + } + @NotNull private final String mSetterName; @NotNull private final String mGetterName; - public MethodFieldAccessor(@NotNull VariableElement element) throws UnsupportedOperationException { + public MethodFieldAccessor(@NotNull VariableElement element, @NotNull Notation notation) throws UnsupportedOperationException { super(element); - mSetterName = findSetterMethodName(element); - mGetterName = findGetterMethodName(element); + mSetterName = findSetterMethodName(element, notation); + mGetterName = findGetterMethodName(element, notation); } @NotNull @@ -61,7 +71,8 @@ private static List getSiblingMethods(@NotNull VariableElemen } @NotNull - private static String findSetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { + private static String findSetterMethodName(@NotNull VariableElement variableElement, + @NotNull Notation namingNotation) throws UnsupportedOperationException { MessagerUtils.logInfo("Looking for setter and getter"); for (ExecutableElement method : getSiblingMethods(variableElement)) { @@ -71,7 +82,7 @@ private static String findSetterMethodName(@NotNull VariableElement variableElem if (method.getReturnType().getKind() == TypeKind.VOID && parameters.size() == 1 && parameters.get(0).asType().equals(variableElement.asType()) && - method.getSimpleName().toString().equals("set" + getVariableNameAsMethodName(variableElement))) { + method.getSimpleName().toString().equals("set" + getVariableNameAsMethodName(variableElement, namingNotation))) { MessagerUtils.logInfo("Found setter"); return method.getSimpleName().toString(); @@ -83,14 +94,15 @@ private static String findSetterMethodName(@NotNull VariableElement variableElem } @NotNull - private static String findGetterMethodName(@NotNull VariableElement variableElement) throws UnsupportedOperationException { + private static String findGetterMethodName(@NotNull VariableElement variableElement, + @NotNull Notation namingNotation) throws UnsupportedOperationException { MessagerUtils.logInfo("Looking for setter and getter"); for (ExecutableElement method : getSiblingMethods(variableElement)) { if (method.getReturnType().equals(variableElement.asType()) && method.getParameters().isEmpty() && - method.getSimpleName().toString().equals("get" + getVariableNameAsMethodName(variableElement))) { + method.getSimpleName().toString().equals("get" + getVariableNameAsMethodName(variableElement, namingNotation))) { MessagerUtils.logInfo("Found getter"); @@ -103,11 +115,19 @@ private static String findGetterMethodName(@NotNull VariableElement variableElem } @NotNull - private static String getVariableNameAsMethodName(@NotNull VariableElement variableElement) { - // if hungarian notation, need different logic + private static String getVariableNameAsMethodName(@NotNull VariableElement variableElement, + @NotNull Notation notation) { String variableName = variableElement.getSimpleName().toString(); - return Character.toUpperCase(variableName.charAt(0)) + variableName.substring(1, variableName.length()); + switch (notation) { + case STANDARD: + return Character.toUpperCase(variableName.charAt(0)) + variableName.substring(1, variableName.length()); + case HUNGARIAN: + return variableName.substring(1, variableName.length()); + default: + throw new UnsupportedOperationException("Unknown notation type"); + } + } } From fbc8502c4279e2f93192f29521da6ed759e29287 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Thu, 18 May 2017 20:27:42 -0400 Subject: [PATCH 27/31] Generic and inherited examples for kotlin --- .../dummy/sample_kotlin/KotlinConcreteExample.kt | 15 +++++++++++++++ .../dummy/sample_kotlin/KotlinGenericExample.kt | 15 +++++++++++++++ .../sample_kotlin/KotlinConcreteExampleTest.kt | 16 ++++++++++++++++ .../sample_kotlin/KotlinGenericExampleTest.kt | 16 ++++++++++++++++ .../dummy/sample_kotlin/KotlinSamplesTest.kt | 2 +- 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExample.kt create mode 100644 sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExample.kt create mode 100644 sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExampleTest.kt create mode 100644 sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExampleTest.kt diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExample.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExample.kt new file mode 100644 index 00000000..3988092e --- /dev/null +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExample.kt @@ -0,0 +1,15 @@ +package com.vimeo.dummy.sample_kotlin + +import com.vimeo.stag.UseStag + +/** + * Kotlin type testing inheritance. + * + * Created by anthonycr on 5/18/17. + */ +@UseStag +class KotlinConcreteExample : KotlinGenericExample() { + + var kotlinObject: KotlinSamples? = null + +} \ No newline at end of file diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExample.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExample.kt new file mode 100644 index 00000000..1e14ce3e --- /dev/null +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExample.kt @@ -0,0 +1,15 @@ +package com.vimeo.dummy.sample_kotlin + +import com.vimeo.stag.UseStag + +/** + * Kotlin type testing abstract classes and generics. + * + * Created by anthonycr on 5/18/17. + */ +@UseStag +abstract class KotlinGenericExample { + + var genericField: T? = null + +} diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExampleTest.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExampleTest.kt new file mode 100644 index 00000000..0bf6457b --- /dev/null +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinConcreteExampleTest.kt @@ -0,0 +1,16 @@ +package com.vimeo.dummy.sample_kotlin + +import org.junit.Test + +/** + * Unit tests for [KotlinConcreteExample]. + * + * Created by anthonycr on 5/18/17. + */ +class KotlinConcreteExampleTest { + + @Test fun verifyTypeAdapterGenerated() { + Utils.verifyTypeAdapterGeneration(KotlinConcreteExample::class) + } + +} \ No newline at end of file diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExampleTest.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExampleTest.kt new file mode 100644 index 00000000..5f42cd8b --- /dev/null +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinGenericExampleTest.kt @@ -0,0 +1,16 @@ +package com.vimeo.dummy.sample_kotlin + +import org.junit.Test + +/** + * Unit tests for [KotlinGenericExample] + * + * Created by anthonycr on 5/18/17. + */ +class KotlinGenericExampleTest { + + @Test + fun verifyTypeAdapterGenerated() { + Utils.verifyNoTypeAdapterGeneration(KotlinGenericExample::class) + } +} \ No newline at end of file diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt index cbdb1e42..b311546d 100644 --- a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/KotlinSamplesTest.kt @@ -3,7 +3,7 @@ package com.vimeo.dummy.sample_kotlin import org.junit.Test /** - * Unit test for KotlinSamples + * Unit tests for [KotlinSamples]. * * Created by restainoa on 5/8/17. */ From a66a6ea6fea7a695799353a2f5f87abe4cddd9d5 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Wed, 24 May 2017 20:17:59 -0400 Subject: [PATCH 28/31] Responding to feedback --- .../stag/processor/generators/TypeAdapterGenerator.java | 4 ++-- .../processor/generators/model/accessor/FieldAccessor.java | 2 +- .../generators/model/accessor/MethodFieldAccessor.java | 2 +- .../src/test/java/com/vimeo/stag/processor/Utils.java | 5 +++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index 18e0d061..46aa2acf 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java @@ -287,7 +287,7 @@ private static MethodSpec getReadMethodSpec(@NotNull TypeName typeName, builder.addCode("\n\t\t\t\tbreak;\n"); - if (fieldAccessor.requireNotNull()) { + if (fieldAccessor.doesRequireNotNull()) { if (!TypeUtils.isSupportedPrimitive(elementValue.toString())) { nonNullFields.add(fieldAccessor); } @@ -752,7 +752,7 @@ private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, /* * If the element is annotated with NonNull annotation, throw {@link IOException} if it is null. */ - if (fieldAccessor.requireNotNull()) { + if (fieldAccessor.doesRequireNotNull()) { builder.endControlFlow(); builder.beginControlFlow("else if (object." + getterCode + " == null)"); builder.addStatement("throw new java.io.IOException(\"" + getterCode + diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java index cb6f3410..f708367c 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/FieldAccessor.java @@ -76,7 +76,7 @@ protected final String getVariableName() { * @return true if the field was marked not null, * false otherwise. */ - public final boolean requireNotNull() { + public final boolean doesRequireNotNull() { for (AnnotationMirror annotationMirror : mVariableElement.getAnnotationMirrors()) { switch (annotationMirror.toString()) { case "@javax.validation.constraints.NotNull": diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java index 0bfb3e2b..3ec59ec9 100644 --- a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java +++ b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/model/accessor/MethodFieldAccessor.java @@ -121,7 +121,7 @@ private static String getVariableNameAsMethodName(@NotNull VariableElement varia switch (notation) { case STANDARD: - return Character.toUpperCase(variableName.charAt(0)) + variableName.substring(1, variableName.length()); + return Character.toUpperCase(variableName.charAt(0)) + variableName.substring(1); case HUNGARIAN: return variableName.substring(1, variableName.length()); default: diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java index 5a3b1a54..c2c28669 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java @@ -55,6 +55,7 @@ private static Elements safeElements() { return elements; } + @NotNull private static Types safeTypes() { Preconditions.checkNotNull(types); return types; @@ -107,13 +108,13 @@ public static TypeMirror getTypeMirrorFromObject(@NotNull Object object) { @NotNull public static TypeMirror getGenericVersionOfClass(@NotNull Class clazz) { List params = - safeElements().getTypeElement(clazz.getName()).getTypeParameters(); + safeElements().getTypeElement(clazz.getName()).getTypeParameters(); TypeMirror[] genericTypes = new TypeMirror[params.size()]; for (int n = 0; n < genericTypes.length; n++) { genericTypes[n] = params.get(n).asType(); } return safeTypes().getDeclaredType(safeElements().getTypeElement(DummyGenericClass.class.getName()), - genericTypes); + genericTypes); } } From 5a917d9bd6b2557f1f3d92c68ce67e2b2a897c00 Mon Sep 17 00:00:00 2001 From: anthony restaino Date: Wed, 24 May 2017 20:19:32 -0400 Subject: [PATCH 29/31] Making fields private like they should be --- .../com/vimeo/sample_java_model/NativeJavaModel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java index 9e908c00..4208a5c2 100644 --- a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NativeJavaModel.java @@ -17,7 +17,7 @@ public void setTopLevel(String mTopLevel) { @UseStag public static class Nested { - String mNested; + private String mNested; public String getNested() { return mNested; @@ -29,7 +29,7 @@ public void setNested(String mNested) { } public static class NestedWithoutAnnotation { - String mNestedWithoutAnnotation; + private String mNestedWithoutAnnotation; public String getNestedWithoutAnnotation() { return mNestedWithoutAnnotation; @@ -42,7 +42,7 @@ public void setNestedWithoutAnnotation(String mNestedWithoutAnnotation) { @UseStag public static class NestedExtension extends NativeJavaModel { - String mNestedExtension; + private String mNestedExtension; public String getNestedExtension() { return mNestedExtension; @@ -54,7 +54,7 @@ public void setNestedExtension(String mNestedExtension) { } public static class NestedExtensionWithoutAnnotation extends NativeJavaModel { - String mNestedExtensionWithoutAnnotation; + private String mNestedExtensionWithoutAnnotation; public String getNestedExtensionWithoutAnnotation() { return mNestedExtensionWithoutAnnotation; @@ -67,7 +67,7 @@ public void setNestedExtensionWithoutAnnotation(String mNestedExtensionWithoutAn @UseStag public static class NestedExtensionFromNoAnnotation extends NestedWithoutAnnotation { - String mNestedExtensionFromNoAnnotation; + private String mNestedExtensionFromNoAnnotation; public String getNestedExtensionFromNoAnnotation() { return mNestedExtensionFromNoAnnotation; From 723ac09e3609cefdc2d25bfca3383e82e627bfa7 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 30 May 2017 19:07:32 -0400 Subject: [PATCH 30/31] Improving documentation about member and method visibility --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eec22839..3564e9c3 100644 --- a/README.md +++ b/README.md @@ -125,13 +125,15 @@ Last but not the least, Stag is almost in parity with GSON. ## Stag Rules 1. Make sure that any private member variables have setters/getters following these naming rules: -```java -private String myString; + ```java + private String myString; -public String getMyString() { ... } + public String getMyString() { ... } -public void setMyString(String parameter) { ... } -``` + public void setMyString(String parameter) { ... } + ``` + Java setters and getters must have `protected`, `public`, or package local visibility. If you don't want to use setters and getters, make sure your member variables have `protected`, `public`, or package local visibility. + If working with Kotlin, currently, you must make sure your getters all have `public` visibility. Because stag generates Java code, the only way it knows how to access the Kotlin fields is if the setters and getters are public. By default, the visibility set on a Kotlin member variable is also applied to its setters and getters. 2. Make sure your model class is not private and has a zero argument non-private constructor 3. Annotate the classes with `@UseStag` annotation. This will process all the member variables of the class, which makes it easy to use. 4. Use the `@SerializedName("key")` annotation to give the variables a different JSON name. (same as GSON) @@ -238,6 +240,8 @@ MyParsingClass { ## Future Enhancements - Add an option to absorb parsing errors rather than crashing and halting parsing (default gson behavior) +- Support `internal` visibility in Kotlin code +- Generate Kotlin code for Kotlin models ## Development ```sh From ecc8f488a4d061aed952f9f7e41a34aea16b1feb Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 30 May 2017 19:12:54 -0400 Subject: [PATCH 31/31] Version 2.2.0 --- CHANGELOG.md | 5 +++++ README.md | 8 ++++---- build.gradle | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 316d9c0c..788738af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Change Log ========== +Version 2.2.0 *(2017-05-30)* +---------------------------- +- Added support for private member variables in Java (leveraging getters/setters). +- Added support for models written in Kotlin. + Version 2.1.4 *(2017-05-10)* ---------------------------- - Added compiler support for all Java language versions. diff --git a/README.md b/README.md index 3564e9c3..2ddbf6df 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,8 @@ buildscript { apply plugin: 'net.ltgt.apt' dependencies { - compile 'com.vimeo.stag:stag-library:2.1.4' - apt 'com.vimeo.stag:stag-library-compiler:2.1.4' + compile 'com.vimeo.stag:stag-library:2.2.0' + apt 'com.vimeo.stag:stag-library-compiler:2.2.0' } // Optional annotation processor arguments (see below) @@ -63,8 +63,8 @@ apt { ```groovy dependencies { - compile 'com.vimeo.stag:stag-library:2.1.4' - annotationProcessor 'com.vimeo.stag:stag-library-compiler:2.1.4' + compile 'com.vimeo.stag:stag-library:2.2.0' + annotationProcessor 'com.vimeo.stag:stag-library-compiler:2.2.0' } android { diff --git a/build.gradle b/build.gradle index d97bc237..cfdfe96a 100644 --- a/build.gradle +++ b/build.gradle @@ -29,5 +29,5 @@ allprojects { subprojects { group = 'com.vimeo.stag' - version = '2.1.4' + version = '2.2.0' }