diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3b72e3fd..496471a1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,12 +1,9 @@ -#### Ticket -**Required for Vimeans only** -[TICKET_NUMBER](https://vimean.atlassian.net/browse/TICKET_NUMBER) +#### Issue +(If applicable) +- https://github.com/vimeo/stag-java/issues/NUMBER -#### Ticket Summary -A brief but thorough description of the ticket. - -#### Implementation Summary -A brief but thorough description of the changes put in place to address the ticket. +#### Summary +A brief but thorough description of the changes. #### How to Test -Detailed *list* of what to test and how to test it. Including all edge cases. +Detailed list of what to test and how to test it. Include all edge cases. diff --git a/CHANGELOG.md b/CHANGELOG.md index 95af9bf1..34a452b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Change Log ========== +Version 2.4.0 *(2017-10-24)* +---------------------------- +- Fixed bug where generated type adapters would write out an empty JSON object for a `null` value. +- Type adapters now write `null` to JSON instead of `{}` for `null` field values. +- Rewrote compiler tests in Kotlin and improved their readability. + Version 2.3.3 *(2017-09-15)* ---------------------------- - `isXYZ()` and `setXYZ()` are now accepted as getter and setter names for boolean fields named `isXYZ` or `mIsXYZ`. diff --git a/README.md b/README.md index f0093b62..c2f0c9b2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ buildscript { apply plugin: 'net.ltgt.apt' dependencies { - def stagVersion = '2.3.3' + def stagVersion = '2.4.0' compile "com.vimeo.stag:stag-library:$stagVersion" apt "com.vimeo.stag:stag-library-compiler:$stagVersion" } @@ -57,7 +57,7 @@ gradle.projectsEvaluated { ```groovy dependencies { - def stagVersion = '2.3.3' + def stagVersion = '2.4.0' compile "com.vimeo.stag:stag-library:$stagVersion" annotationProcessor "com.vimeo.stag:stag-library-compiler:$stagVersion" } diff --git a/build.gradle b/build.gradle index 63c2b8c1..95914842 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.1.4-3' + ext.kotlin_version = '1.1.51' ext.jacoco_version = '0.7.9' // See http://www.eclemma.org/jacoco/ // android dependencies @@ -40,5 +40,5 @@ allprojects { subprojects { group = 'com.vimeo.stag' - version = '2.3.3' + version = '2.4.0' } diff --git a/sample-java-model/src/main/java/com/vimeo/sample_java_model/NullFields.java b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NullFields.java new file mode 100644 index 00000000..1a1aa661 --- /dev/null +++ b/sample-java-model/src/main/java/com/vimeo/sample_java_model/NullFields.java @@ -0,0 +1,36 @@ +package com.vimeo.sample_java_model; + +import com.google.gson.annotations.SerializedName; +import com.vimeo.stag.UseStag; + +import org.jetbrains.annotations.Nullable; + +/** + * A test case for an object containing null fields. + *

+ * Created by restainoa on 10/20/17. + */ +@UseStag +public class NullFields { + + @Nullable + @SerializedName("hello") + public Object hello; + + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + NullFields that = (NullFields) o; + + return hello != null ? hello.equals(that.hello) : that.hello == null; + + } + + @Override + public int hashCode() { + return hello != null ? hello.hashCode() : 0; + } +} diff --git a/sample-kotlin-model/build.gradle b/sample-kotlin-model/build.gradle index 8d060c52..f97669dd 100644 --- a/sample-kotlin-model/build.gradle +++ b/sample-kotlin-model/build.gradle @@ -62,6 +62,7 @@ dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" + testCompile 'uk.co.jemos.podam:podam:7.1.0.RELEASE' } repositories { diff --git a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/BoolFields.kt b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/BoolFields.kt index 28cb19f0..2263ec44 100644 --- a/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/BoolFields.kt +++ b/sample-kotlin-model/src/main/kotlin/com/vimeo/dummy/sample_kotlin/BoolFields.kt @@ -9,12 +9,7 @@ import com.vimeo.stag.UseStag * Created by anthonycr on 9/2/17. */ @UseStag -class BoolFields { - - @SerializedName("test1") - var test1: Boolean? = null - - @SerializedName("test2") - var isTest2: Boolean? = null - -} \ No newline at end of file +data class BoolFields( + @SerializedName("test1") var test1: Boolean? = null, + @SerializedName("test2") var isTest2: Boolean? = null +) \ No newline at end of file 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 index 3988092e..83f07e9b 100644 --- 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 @@ -12,4 +12,22 @@ class KotlinConcreteExample : KotlinGenericExample() { var kotlinObject: KotlinSamples? = null + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as KotlinConcreteExample + + if (kotlinObject != other.kotlinObject) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + (kotlinObject?.hashCode() ?: 0) + return result + } + } \ 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 index 1e14ce3e..9104c0c1 100644 --- 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 @@ -12,4 +12,19 @@ abstract class KotlinGenericExample { var genericField: T? = null + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as KotlinGenericExample<*> + + if (genericField != other.genericField) return false + + return true + } + + override fun hashCode(): Int { + return genericField?.hashCode() ?: 0 + } + } 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 32fc9824..d0d145b9 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 @@ -9,17 +9,11 @@ import com.vimeo.stag.UseStag * Created by restainoa on 5/8/17. */ @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 +data class KotlinSamples( + @SerializedName("string_field") var stringField: String? = null, + @SerializedName("non_null_string_field") var nonNullStringField: String = "default", + @SerializedName("int_field") var intField: Int? = null, + @SerializedName("long_field") var longField: Long = 1, + @SerializedName("boolean_field") var booleanField: Boolean? = null, + var notAnnotatedField: Int? = null // will still be picked up by the compiler and will look for json field named "nonAnnotatedField" +) \ No newline at end of file diff --git a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/BoolFieldsTest.kt b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/BoolFieldsTest.kt index 3adb035d..e5e6699f 100644 --- a/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/BoolFieldsTest.kt +++ b/sample-kotlin-model/src/test/kotlin/com/vimeo/dummy/sample_kotlin/BoolFieldsTest.kt @@ -10,8 +10,12 @@ import org.junit.Test class BoolFieldsTest { @Test - fun name() { + fun verifyTypeAdapterWasGenerated() { Utils.verifyTypeAdapterGeneration(BoolFields::class) } + @Test + fun verifyTypeAdapterCorrect() { + Utils.verifyTypeAdapterCorrectness(BoolFields::class) + } } \ No newline at end of file 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 index 0bf6457b..35b958b5 100644 --- 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 @@ -9,8 +9,13 @@ import org.junit.Test */ class KotlinConcreteExampleTest { - @Test fun verifyTypeAdapterGenerated() { + @Test + fun verifyTypeAdapterGenerated() { Utils.verifyTypeAdapterGeneration(KotlinConcreteExample::class) } + @Test + fun verifyTypeAdapterCorrectness() { + Utils.verifyTypeAdapterCorrectness(KotlinConcreteExample::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 b311546d..0225d694 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 @@ -13,4 +13,8 @@ class KotlinSamplesTest { Utils.verifyTypeAdapterGeneration(KotlinSamples::class) } + @Test + fun verifyTypeAdapterCorrectness() { + Utils.verifyTypeAdapterCorrectness(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 index 5ebce367..d4c75cca 100644 --- 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 @@ -5,6 +5,8 @@ import com.google.gson.TypeAdapter import com.google.gson.reflect.TypeToken import com.vimeo.sample_kotlin.stag.generated.Stag import junit.framework.Assert +import junit.framework.Assert.assertEquals +import uk.co.jemos.podam.api.PodamFactoryImpl import kotlin.reflect.KClass /** @@ -50,5 +52,24 @@ class Utils { val typeAdapter = getTypeAdapter(clazz) Assert.assertNull("Type adapter should not have been generated by Stag", typeAdapter) } + + /** + * Verifies that the type adapter for [clazz] is correct. It does this by manufacturing an + * instance of the class, writing it to JSON, and then reading that object back out of JSON + * and comparing the two instances. + * + * @param clazz the [KClass] to use to get the [TypeAdapter]. + */ + fun verifyTypeAdapterCorrectness(clazz: KClass) { + val factory = PodamFactoryImpl() + + val obj: T = factory.manufacturePojo(clazz.java) + val typeAdapter: TypeAdapter? = getTypeAdapter(clazz) + + val json = typeAdapter?.toJson(obj) + + assertEquals(obj, typeAdapter?.fromJson(json)) + } + } } \ No newline at end of file diff --git a/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index e35c952f..8f2aedea 100644 --- a/stag-library-compiler/build.gradle +++ b/stag-library-compiler/build.gradle @@ -1,10 +1,11 @@ apply plugin: 'java' +apply plugin: 'kotlin' apply plugin: 'jacoco' apply plugin: 'maven-publish' compileJava { - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = "1.7" + targetCompatibility = "1.7" } jacoco { @@ -23,7 +24,9 @@ jacocoTestReport.dependsOn test dependencies { testCompile 'junit:junit:4.12' - testCompile 'com.google.testing.compile:compile-testing:0.8' + testCompile 'org.assertj:assertj-core:3.8.0' + testCompile 'com.google.testing.compile:compile-testing:0.12' + testCompile project(path: ':sample-java-model') // Forcibly add test resources to test classpath: https://code.google.com/p/android/issues/detail?id=64887 testRuntime files('build/resources/test') @@ -34,6 +37,8 @@ dependencies { compile 'com.squareup:javapoet:1.8.0' compile 'com.intellij:annotations:12.0@jar' compile 'com.google.auto.service:auto-service:1.0-rc3' + + compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" } test { 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 1cfa95d0..a099ddca 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 @@ -486,7 +486,7 @@ private TypeSpec getAdapterFactorySpec() { } @NotNull - private MethodSpec getSetOrThrowMethodSpec() { + private static MethodSpec getSetOrThrowMethodSpec() { return MethodSpec.methodBuilder("setOrThrow") .returns(TypeName.VOID) .addParameter(Gson.class, "gson") 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 46aa2acf..cb75eb3c 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 @@ -724,11 +724,11 @@ private static MethodSpec getWriteMethodSpec(@NotNull TypeName typeName, .addAnnotation(Override.class) .addException(IOException.class); - builder.addStatement("writer.beginObject()"); builder.beginControlFlow("if (object == null)"); - builder.addStatement("writer.endObject()"); + builder.addStatement("writer.nullValue()"); builder.addStatement("return"); builder.endControlFlow(); + builder.addStatement("writer.beginObject()"); for (Map.Entry element : memberVariables.entrySet()) { FieldAccessor fieldAccessor = element.getKey(); diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.java deleted file mode 100644 index 7afaa37b..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.vimeo.stag.processor; - -/* - * @(#)AbstractAnnotationProcessorTest.java 5 Jun 2009 - * - * Copyright © 2010 Andrew Phillips. - * - * ==================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ==================================================================== - */ - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -import javax.annotation.processing.Processor; -import javax.tools.Diagnostic; -import javax.tools.Diagnostic.Kind; -import javax.tools.DiagnosticCollector; -import javax.tools.JavaCompiler; -import javax.tools.JavaCompiler.CompilationTask; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -import static com.google.common.base.Throwables.propagate; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * A base test class for {@link Processor annotation processor} testing that - * attempts to compile source test cases that can be found on the classpath. - * - * Original source from: - * https://github.com/ngs-doo/dsl-json/blob/master/processor/src/test/java/com/dslplatform/json/AbstractAnnotationProcessorTest.java - * - * @author aphillips - * @since 5 Jun 2009 - */ -abstract class AbstractAnnotationProcessorTest { - private static final String SOURCE_FILE_SUFFIX = ".java"; - private static final JavaCompiler COMPILER = ToolProvider.getSystemJavaCompiler(); - - /** @return the processor instances that should be tested */ - protected abstract Collection getProcessors(); - - protected List> compileTestCase(String ... classNames) { - DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>(); - try (StandardJavaFileManager fileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null); - CleanableJavaFileManager cleanableJavaFileManager = new CleanableJavaFileManager(fileManager)) { - Collection files = classNamesToFiles(classNames); - Iterable javaFileObjects = fileManager.getJavaFileObjectsFromFiles(files); - /* - * Call the compiler with the "-proc:only" option. The "class names" - * option (which could, in principle, be used instead of compilation - * units for annotation processing) isn't useful in this case because - * that only gives access to the annotation declaration, not the - * members. - */ - CompilationTask task = COMPILER.getTask(null, cleanableJavaFileManager, diagnosticCollector, - Collections.singletonList("-proc:only"), null, javaFileObjects); - task.setProcessors(getProcessors()); - task.call(); - - } catch (IOException exception) { - exception.printStackTrace(System.err); - } - - return diagnosticCollector.getDiagnostics(); - } - - private Collection classNamesToFiles(String ... classNames) { - ArrayList files = new ArrayList<>(classNames.length); - for (String className : classNames) { - files.add(resourceToFile(className + SOURCE_FILE_SUFFIX)); - } - return files; - } - - private File resourceToFile(String resourceName) { - URL resource = getClass().getResource(resourceName); - assert resource.getProtocol().equals("file"); - try { - return new File(resource.toURI()); - } catch (URISyntaxException e) { - throw propagate(e); - } - } - - protected static void assertCompilationSuccessful(List> diagnostics) { - assert (diagnostics != null); - - for (Diagnostic diagnostic : diagnostics) { - System.err.println("Diagnostic: " + diagnostic); - assertFalse("Expected no errors", diagnostic.getKind().equals(Kind.ERROR)); - } - } - - protected static void assertCompilationReturned(Kind expectedDiagnosticKind, long expectedLineNumber, - List> diagnostics) { - assert ((expectedDiagnosticKind != null) && (diagnostics != null)); - boolean expectedDiagnosticFound = false; - - StringBuilder diagnosticsPrintout = new StringBuilder(); - for (Diagnostic diagnostic : diagnostics) { - diagnosticsPrintout.append(diagnostic.getKind()) - .append(" - ") - .append(getSourceIdent(diagnostic)) - .append(" - ") - .append(diagnostic.getMessage(Locale.ENGLISH)) - .append("\n"); - if (diagnostic.getKind().equals(expectedDiagnosticKind) - && (diagnostic.getLineNumber() == expectedLineNumber)) { - expectedDiagnosticFound = true; - break; - } - } - if (diagnosticsPrintout.length() == 0) { - diagnosticsPrintout.append("No diagnostic result"); - } - assertTrue("Expected a result of kind " + expectedDiagnosticKind - + " at line " + expectedLineNumber + "\nFound instead:\n" + diagnosticsPrintout, - expectedDiagnosticFound); - } - - private static String getSourceIdent(Diagnostic diagnostic) { - JavaFileObject source = diagnostic.getSource(); - if (source == null) { - return "unknown"; - } - String name = source.getName(); - int indexOf = name.lastIndexOf(File.separatorChar); - if (indexOf >= 0) { - name = name.substring(indexOf + 1); - } - long lineNumber = diagnostic.getLineNumber(); - long columnNumber = diagnostic.getColumnNumber(); - return name + ":" + lineNumber + ":" + columnNumber; - } -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt similarity index 71% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt index 03322def..9f254f40 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt @@ -21,33 +21,33 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor; +package com.vimeo.stag.processor -import com.google.testing.compile.CompilationRule; - -import org.junit.Before; -import org.junit.Rule; - -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; +import com.google.testing.compile.CompilationRule +import org.junit.Before +import org.junit.Rule +import javax.lang.model.util.Elements +import javax.lang.model.util.Types /** * Base unit test that sets up the utils class. */ -public class BaseUnitTest { +open class BaseUnitTest { + @JvmField @Rule - public final CompilationRule rule = new CompilationRule(); - protected Elements elements; - protected Types types; + val rule = CompilationRule() + protected lateinit var elements: Elements + protected lateinit var types: Types @Before - public void _setup() { - elements = rule.getElements(); - types = rule.getTypes(); + fun _setup() { + elements = rule.elements + types = rule.types - Utils.setup(elements, types); + Utils.elements = elements + Utils.types = types } } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.java deleted file mode 100644 index d2bbec4b..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * The MIT License (MIT) - *

- * Copyright (c) 2016 Vimeo - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.vimeo.stag.processor; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; - -import javax.tools.FileObject; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; - -/** - * {@link JavaFileManager} implementation which tracks created files and allows them to be - * systematically deleted. - */ -class CleanableJavaFileManager implements JavaFileManager { - - private final LinkedBlockingQueue writtenFiles = new LinkedBlockingQueue<>(); - private final JavaFileManager delegate; - - CleanableJavaFileManager(JavaFileManager delegate) { - this.delegate = delegate; - } - - void purge() throws IOException { - ArrayList toDelete = new ArrayList<>(); - writtenFiles.drainTo(toDelete); - for (FileObject file : toDelete) { - file.delete(); - } - } - - @Override - public ClassLoader getClassLoader(Location location) { - return delegate.getClassLoader(location); - } - - @Override - public Iterable list(Location location, String s, Set set, boolean b) throws IOException { - return delegate.list(location, s, set, b); - } - - @Override - public String inferBinaryName(Location location, JavaFileObject javaFileObject) { - return delegate.inferBinaryName(location, javaFileObject); - } - - @Override - public boolean isSameFile(FileObject fileObject, FileObject fileObject1) { - return delegate.isSameFile(fileObject, fileObject1); - } - - @Override - public boolean handleOption(String s, Iterator iterator) { - return delegate.handleOption(s, iterator); - } - - @Override - public boolean hasLocation(Location location) { - return delegate.hasLocation(location); - } - - @Override - public JavaFileObject getJavaFileForInput(Location location, String s, JavaFileObject.Kind kind) throws IOException { - return delegate.getJavaFileForInput(location, s, kind); - } - - @Override - public JavaFileObject getJavaFileForOutput(Location location, String s, JavaFileObject.Kind kind, FileObject fileObject) throws IOException { - JavaFileObject javaFileForOutput = delegate.getJavaFileForOutput(location, s, kind, fileObject); - writtenFiles.add(javaFileForOutput); - return javaFileForOutput; - } - - @Override - public FileObject getFileForInput(Location location, String s, String s1) throws IOException { - return delegate.getFileForInput(location, s, s1); - } - - @Override - public FileObject getFileForOutput(Location location, String s, String s1, FileObject fileObject) throws IOException { - FileObject fileForOutput = delegate.getFileForOutput(location, s, s1, fileObject); - writtenFiles.add(fileForOutput); - return fileForOutput; - } - - @Override - public void flush() throws IOException { - delegate.flush(); - } - - @Override - public void close() throws IOException { - delegate.close(); - purge(); - } - - @Override - public int isSupportedOption(String s) { - return delegate.isSupportedOption(s); - } -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.java deleted file mode 100644 index 11251b8f..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * The MIT License (MIT) - *

- * Copyright (c) 2016 Vimeo - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.vimeo.stag.processor; - -import com.vimeo.stag.processor.dummy.DummyClassWithConstructor; -import com.vimeo.stag.processor.dummy.DummyConcreteClass; -import com.vimeo.stag.processor.dummy.DummyGenericClass; -import com.vimeo.stag.processor.dummy.DummyInheritedClass; -import com.vimeo.stag.processor.utils.ElementUtils; -import com.vimeo.stag.processor.utils.TypeUtils; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import javax.lang.model.element.ExecutableElement; - -public class ElementUtilsUnitTest extends BaseUnitTest { - - @Before - public void setup() { - ElementUtils.initialize(elements); - TypeUtils.initialize(types); - } - - @Test - public void testConstructor() throws Exception { - Utils.testZeroArgumentConstructorFinalClass(ElementUtils.class); - } - - @Test - public void testGetTypeFromQualifiedName() throws Exception { - Assert.assertEquals(Utils.getTypeMirrorFromClass(String.class), - ElementUtils.getTypeFromQualifiedName(String.class.getName())); - Assert.assertEquals(Utils.getTypeMirrorFromClass(Object.class), - ElementUtils.getTypeFromQualifiedName(Object.class.getName())); - Assert.assertEquals(Utils.getTypeMirrorFromClass(ArrayList.class), - ElementUtils.getTypeFromQualifiedName(ArrayList.class.getName())); - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass.class), - ElementUtils.getTypeFromQualifiedName(DummyConcreteClass.class.getName())); - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyGenericClass.class), - ElementUtils.getTypeFromQualifiedName(DummyGenericClass.class.getName())); - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass.class), - ElementUtils.getTypeFromQualifiedName(DummyInheritedClass.class.getName())); - - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass.class), - ElementUtils.getTypeFromQualifiedName(DummyInheritedClass.class.getName())); - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyGenericClass.class), - ElementUtils.getTypeFromQualifiedName(DummyConcreteClass.class.getName())); - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass.class), - ElementUtils.getTypeFromQualifiedName(DummyGenericClass.class.getName())); - } - - @Test - public void testGetPackage() throws Exception { - Assert.assertEquals(String.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String.class))); - Assert.assertEquals(ArrayList.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList.class))); - Assert.assertEquals(Object.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Object.class))); - Assert.assertEquals(DummyGenericClass.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass.class))); - - Assert.assertEquals(DummyGenericClass.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyConcreteClass.class))); - Assert.assertEquals(DummyConcreteClass.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyInheritedClass.class))); - Assert.assertEquals(DummyInheritedClass.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass.class))); - - - Assert.assertNotEquals(Object.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList.class))); - Assert.assertNotEquals(List.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String.class))); - Assert.assertNotEquals(DummyInheritedClass.class.getPackage().getName(), - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Object.class))); - } - - @Test - public void testGetConstructor() throws Exception { - ExecutableElement executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String.class)); - Assert.assertEquals(executableElement.getEnclosingElement().toString(),Utils.getElementFromClass(String.class).toString()); - Assert.assertEquals(executableElement.getParameters().size(), 0); - - executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor.class)); - Assert.assertEquals(executableElement.getEnclosingElement().toString(),Utils.getElementFromClass(DummyClassWithConstructor.class).toString()); - Assert.assertEquals(executableElement.getParameters().size(), 1); - Assert.assertEquals(executableElement.getParameters().get(0).asType().toString(), Utils.getElementFromClass(String.class).toString()); - - executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyGenericClass.class)); - Assert.assertEquals(executableElement.getEnclosingElement().toString(), Utils.getElementFromClass(DummyGenericClass.class).toString()); - Assert.assertEquals(executableElement.getParameters().size(), 0); - - } - -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.kt new file mode 100644 index 00000000..e945029d --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.kt @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + *

+ * Copyright (c) 2016 Vimeo + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.vimeo.stag.processor + +import com.vimeo.stag.processor.dummy.DummyClassWithConstructor +import com.vimeo.stag.processor.dummy.DummyConcreteClass +import com.vimeo.stag.processor.dummy.DummyGenericClass +import com.vimeo.stag.processor.dummy.DummyInheritedClass +import com.vimeo.stag.processor.utils.ElementUtils +import com.vimeo.stag.processor.utils.TypeUtils +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals +import org.junit.Before +import org.junit.Test +import java.util.* + +class ElementUtilsUnitTest : BaseUnitTest() { + + @Before + fun setup() { + ElementUtils.initialize(elements) + TypeUtils.initialize(types) + } + + @Test + fun testConstructor() = Utils.testZeroArgumentConstructorFinalClass(ElementUtils::class.java) + + @Test + fun testGetTypeFromQualifiedName() { + testTypeMirrorCreationAndEquality(String::class.java) + testTypeMirrorCreationAndEquality(Any::class.java) + testTypeMirrorCreationAndEquality(ArrayList::class.java) + testTypeMirrorCreationAndEquality(DummyConcreteClass::class.java) + testTypeMirrorCreationAndEquality(DummyGenericClass::class.java) + testTypeMirrorCreationAndEquality(DummyInheritedClass::class.java) + + testTypeMirrorCreationAndInequality(DummyConcreteClass::class.java, DummyInheritedClass::class.java) + testTypeMirrorCreationAndInequality(DummyGenericClass::class.java, DummyConcreteClass::class.java) + testTypeMirrorCreationAndInequality(DummyInheritedClass::class.java, DummyGenericClass::class.java) + } + + private fun testTypeMirrorCreationAndEquality(clazz: Class) { + assertEquals(Utils.getTypeMirrorFromClass(clazz), ElementUtils.getTypeFromQualifiedName(clazz.name)) + } + + private fun testTypeMirrorCreationAndInequality(clazz: Class, otherClass: Class) { + assertNotEquals(Utils.getTypeMirrorFromClass(clazz), ElementUtils.getTypeFromQualifiedName(otherClass.name)) + } + + @Test + fun testGetPackage() { + testPackageEquality(String::class.java) + testPackageEquality(ArrayList::class.java) + testPackageEquality(Any::class.java) + testPackageEquality(DummyGenericClass::class.java) + + testPackageEquality(DummyGenericClass::class.java, DummyConcreteClass::class.java) + testPackageEquality(DummyConcreteClass::class.java, DummyInheritedClass::class.java) + testPackageEquality(DummyInheritedClass::class.java, DummyGenericClass::class.java) + + + testPackageInequality(Any::class.java, ArrayList::class.java) + testPackageInequality(List::class.java, String::class.java) + testPackageInequality(DummyInheritedClass::class.java, Any::class.java) + } + + private fun testPackageEquality(clazz: Class, otherClass: Class = clazz) { + assertEquals(clazz.`package`.name, ElementUtils.getPackage(Utils.getTypeMirrorFromClass(otherClass))) + } + + private fun testPackageInequality(clazz: Class, otherClass: Class) { + assertNotEquals(clazz.`package`.name, ElementUtils.getPackage(Utils.getTypeMirrorFromClass(otherClass))) + } + + @Test + fun testGetConstructor() { + var executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String::class.java))!! + assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(String::class.java).toString()) + assertEquals(executableElement.parameters.size.toLong(), 0) + + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor::class.java))!! + assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyClassWithConstructor::class.java).toString()) + assertEquals(executableElement.parameters.size.toLong(), 1) + assertEquals(executableElement.parameters[0].asType().toString(), Utils.getElementFromClass(String::class.java).toString()) + + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))!! + assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyGenericClass::class.java).toString()) + assertEquals(executableElement.parameters.size.toLong(), 0) + + } + +} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.java deleted file mode 100644 index ed536dd3..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * The MIT License (MIT) - *

- * Copyright (c) 2016 Vimeo - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.vimeo.stag.processor; - -import com.vimeo.stag.processor.utils.Preconditions; - -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -public class PreconditionsUnitTest { - - @Test - public void testFinalClass_isNotInstantiable() throws Exception { - Utils.testZeroArgumentConstructorFinalClass(Preconditions.class); - } - - @SuppressWarnings("ConstantConditions") - @Test(expected = NullPointerException.class) - public void checkNotNull_Null_throwsNullPointer() { - Object o = null; - Preconditions.checkNotNull(o); - } - - @Test - public void checkNotNull_NotNull() throws Exception { - Object o = new Object(); - Preconditions.checkNotNull(o); - } - - @Test - public void checkNotEmpty_NotEmpty() throws Exception { - List list = new ArrayList() {{ - add(new Object()); - }}; - - Preconditions.checkNotEmpty(list); - } - - @Test(expected = IllegalStateException.class) - public void checkNotEmpty_Empty_throwsException() { - List list = new ArrayList(); - Preconditions.checkNotEmpty(list); - } - - @Test - public void checkTrue_True() throws Exception { - Preconditions.checkTrue(true); - Preconditions.checkTrue(Boolean.TRUE); - } - - @Test(expected = IllegalStateException.class) - public void checkTrue_FalsePrimitive_throwsException() { - Preconditions.checkTrue(false); - } - - @Test(expected = IllegalStateException.class) - public void checkTrue_FalseObject_throwsException() { - Preconditions.checkTrue(Boolean.FALSE); - } - -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt similarity index 51% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt index 5ec84615..4df80443 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt @@ -21,76 +21,39 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor -import org.jetbrains.annotations.NotNull; +import com.vimeo.stag.processor.utils.Preconditions +import org.junit.Test -import java.util.Collection; -import java.util.Map; -import java.util.Set; +class PreconditionsUnitTest { -public class DummyMapClass implements Map { + @Test + fun testFinalClass_isNotInstantiable() = + Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) - @Override - public int size() { - return 0; - } + @Test(expected = NullPointerException::class) + fun checkNotNull_Null_throwsNullPointer() = Preconditions.checkNotNull(null) - @Override - public boolean isEmpty() { - return false; - } + @Test + fun checkNotNull_NotNull() = Preconditions.checkNotNull(Any()) - @Override - public boolean containsKey(Object o) { - return false; - } + @Test + fun checkNotEmpty_NotEmpty() = Preconditions.checkNotEmpty(listOf(Any())) - @Override - public boolean containsValue(Object o) { - return false; - } + @Test(expected = IllegalStateException::class) + fun checkNotEmpty_Empty_throwsException() = Preconditions.checkNotEmpty(listOf()) - @Override - public Object get(Object o) { - return null; + @Test + fun checkTrue_True() { + Preconditions.checkTrue(true) + Preconditions.checkTrue(java.lang.Boolean.TRUE) } - @Override - public Object put(Object o, Object o2) { - return null; - } + @Test(expected = IllegalStateException::class) + fun checkTrue_FalsePrimitive_throwsException() = Preconditions.checkTrue(false) - @Override - public Object remove(Object o) { - return null; - } - - @Override - public void putAll(@NotNull Map map) { - - } + @Test(expected = IllegalStateException::class) + fun checkTrue_FalseObject_throwsException() = Preconditions.checkTrue(java.lang.Boolean.FALSE) - @Override - public void clear() { - - } - - @NotNull - @Override - public Set keySet() { - return null; - } - - @NotNull - @Override - public Collection values() { - return null; - } - - @NotNull - @Override - public Set entrySet() { - return null; - } } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ProcessorTester.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ProcessorTester.kt new file mode 100644 index 00000000..ed8ec432 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ProcessorTester.kt @@ -0,0 +1,68 @@ +package com.vimeo.stag.processor + +import com.google.testing.compile.Compilation +import com.google.testing.compile.Compiler +import java.io.File +import javax.annotation.processing.Processor +import javax.tools.DiagnosticCollector +import javax.tools.ToolProvider +import kotlin.reflect.KClass + +/** + * A class that compiles [KClass] using the provided [processor] and emits the compilation result. + * + * Created by restainoa on 9/27/17. + */ +class ProcessorTester(private val processor: () -> Processor) { + + private val fileManager = ToolProvider.getSystemJavaCompiler().getStandardFileManager(DiagnosticCollector(), null, null) + private val classpathRoot = File(Thread.currentThread().contextClassLoader.getResource("").path) + private val projectRoot = classpathRoot.parentFile.parentFile.parentFile + private val javaRoot = File(File(File(projectRoot, "src"), "test"), "java") + + /** + * Compile the provided class(es) and return the [Compilation] result. + * + * @param clazz the class(es) to compile. + */ + fun compile(vararg clazz: KClass<*>): Compilation { + return Compiler.javac() + .withProcessors(processor()) + .compile(fileManager.getJavaFileObjects(*clazz.map { it.asResourcePath().asClassPathFile() }.toTypedArray())) + } + + /** + * Compile the provided class(es) and return the [Compilation] result. + * + * @param clazz the class(es) to compile, in the form of `package/ClassName.java` + */ + fun compileResource(vararg clazz: String): Compilation { + return Compiler.javac() + .withProcessors(processor()) + .compile(fileManager.getJavaFileObjects(*clazz.map { javaClass.getResource(it).toURI() }.map { File(it) }.toTypedArray())) + } + + /** + * Converts the [KClass] to a java resource path. + */ + private fun KClass<*>.asResourcePath() = "${this.java.name.replace('.', '/')}.java" + + /** + * Converts a [String] representing a resource path to a [File]. + */ + private fun String.asClassPathFile(): File { + val ind = this.indexOf('$') + + return if (ind < 0) { + File(javaRoot, this) + } else { + File(javaRoot, "${this.substring(0, ind)}.java") + } + } +} + +/** + * Return `true` if the status of the compilation is [Compilation.Status.SUCCESS], `false` + * otherwise. + */ +fun Compilation.isSuccessful() = this.status() == Compilation.Status.SUCCESS \ 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.kt similarity index 63% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt index 246c010f..712ec43a 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.kt @@ -21,31 +21,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor; +package com.vimeo.stag.processor -import org.junit.Test; +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test -import java.util.Collection; -import java.util.Collections; +class StagProcessorFunctionalTest { -import javax.annotation.processing.Processor; -import javax.tools.Diagnostic; - -public class StagProcessorFunctionalTest extends AbstractAnnotationProcessorTest { - - @Override - protected Collection getProcessors() { - StagProcessor processor = new StagProcessor(); - return Collections.singletonList(processor); - } + private val processorTester = ProcessorTester({ StagProcessor() }) /** * Ensure that final fields result in compile-time errors to prevent silent omission of fields * from generated type adapters. */ @Test - public void finalFieldsInAnnotatedClassReportsAsAnError() throws Exception { - assertCompilationReturned(Diagnostic.Kind.ERROR, 8, compileTestCase("bad/FinalFields")); + fun finalFieldsInAnnotatedClassReportsAsAnError() { + assertThat(processorTester.compileResource("testcase/FinalFields.java").isSuccessful()).isFalse() } /** @@ -53,8 +44,12 @@ public void finalFieldsInAnnotatedClassReportsAsAnError() throws Exception { * from generated type adapters. */ @Test - public void privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() throws Exception { - assertCompilationReturned(Diagnostic.Kind.ERROR, 8, compileTestCase("bad/PrivateFields")); + fun privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() { + assertThat(processorTester.compileResource("testcase/PrivateFields.java").isSuccessful()).isFalse() } + @Test + fun `User compiles successfully`() { + assertThat(processorTester.compileResource("testcase/User.java").isSuccessful()).isTrue() + } } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorIntegrationTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorIntegrationTest.kt new file mode 100644 index 00000000..d0e58321 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorIntegrationTest.kt @@ -0,0 +1,29 @@ +package com.vimeo.stag.processor + +import com.google.gson.Gson +import com.vimeo.sample_java_model.NullFields +import com.vimeo.sample_java_model.stag.generated.Stag +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +/** + * Integration tests for the compiler. + * + * Created by restainoa on 10/20/17. + */ +class StagProcessorIntegrationTest { + + @Test + fun `NullFields type adapter is correct for null values`() { + val typeAdapter = Stag.Factory().`getNullFields$TypeAdapter`(Gson()) + val nullFields = NullFields() + val json = typeAdapter.toJson(nullFields) + + // Assert that we are getting the JSON we expect + assertThat(json).isEqualTo("{}") + assertThat(typeAdapter.fromJson(json)).isEqualTo(nullFields) + + // Assert that a null value emits null JSON + assertThat(typeAdapter.toJson(null)).isEqualTo("null") + } +} \ No newline at end of file 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 deleted file mode 100644 index ee054ea4..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * The MIT License (MIT) - *

- * Copyright (c) 2016 Vimeo - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.vimeo.stag.processor; - -import com.vimeo.stag.processor.dummy.DummyAbstractClass; -import com.vimeo.stag.processor.dummy.DummyClassWithConstructor; -import com.vimeo.stag.processor.dummy.DummyConcreteClass; -import com.vimeo.stag.processor.dummy.DummyEnumClass; -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; -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Stack; -import java.util.Vector; - -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -/** - * Unit tests for the annotation processor. - * Run using: {@code ./gradlew :stag-library-compiler:test --continue} - */ -public class TypeUtilsUnitTest extends BaseUnitTest { - - @Before - public void setup() { - TypeUtils.initialize(types); - } - - @Test - public void testFinalClass_constructorFails() throws Exception { - Utils.testZeroArgumentConstructorFinalClass(TypeUtils.class); - } - - @Test - public void getInheritedType_isCorrect() throws Exception { - TypeMirror concreteType = - TypeUtils.getInheritedType(Utils.getElementFromClass(DummyInheritedClass.class)); - assertNotNull(concreteType); - - TypeMirror realConcreteType = - types.getDeclaredType(Utils.getElementFromClass(DummyGenericClass.class), - Utils.getTypeMirrorFromClass(String.class)); - - assertTrue(realConcreteType.toString().equals(concreteType.toString())); - - TypeMirror stringInheritedType = TypeUtils.getInheritedType(Utils.getElementFromClass(String.class)); - assertNull(stringInheritedType); - - TypeMirror enumType = TypeUtils.getInheritedType(Utils.getElementFromClass(DummyEnumClass.class)); - assertNull(enumType); - } - - /** - * This test is particularly susceptible to changes - * in the DummyGenericClass. Any fields - * added, removed, renamed, or changed, will probably - * break this test either explicitly, or implicitly. - * Any changes to that class need to be reflected here. - * - * @throws Exception thrown if the test fails. - */ - @Test - public void getConcreteMembers_isCorrect() throws Exception { - Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); - assertNotNull(genericElement); - - Map genericMembers = new HashMap<>(); - for (Element element : genericElement.getEnclosedElements()) { - if (element instanceof VariableElement) { - genericMembers.put(new DirectFieldAccessor((VariableElement) element), element.asType()); - } - } - - TypeMirror concreteType = - TypeUtils.getInheritedType(Utils.getElementFromClass(DummyInheritedClass.class)); - - assertNotNull(concreteType); - - TypeMirror genericType = Utils.getGenericVersionOfClass(DummyGenericClass.class); - - assertNotNull(genericType); - - 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().createGetterCode().contentEquals("testObject = ")) { - - assertTrue(entry.getValue().toString().equals(stringType.toString())); - - } else if (entry.getKey().createGetterCode().contentEquals("testList = ")) { - - assertTrue(entry.getValue() - .toString() - .equals(types.getDeclaredType(Utils.getElementFromClass(ArrayList.class), - stringType).toString())); - - } 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().createGetterCode().contentEquals("testSet = ")) { - - assertTrue(entry.getValue() - .toString() - .equals(types.getDeclaredType(Utils.getElementFromClass(HashSet.class), stringType) - .toString())); - } 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().createGetterCode().contentEquals("testListMap = ")) { - TypeMirror mapStringString = types.getDeclaredType(Utils.getElementFromClass(Map.class), stringType, stringType); - assertTrue(entry.getValue() - .toString() - .equals(types.getDeclaredType(Utils.getElementFromClass(ArrayList.class), mapStringString) - .toString())); - } - } - } - - @Test - public void isEnum_isCorrect() throws Exception { - assertTrue(TypeUtils.isEnum(Utils.getElementFromClass(DummyEnumClass.class))); - - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyAbstractClass.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyClassWithConstructor.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyConcreteClass.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyGenericClass.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyInheritedClass.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyMapClass.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(Object.class))); - assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(String.class))); - } - - @Test - public void areEqual_isCorrect() { - assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(Object.class), Utils.getTypeMirrorFromClass(Object.class))); - assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(String.class), Utils.getTypeMirrorFromClass(String.class))); - assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(List.class), Utils.getTypeMirrorFromClass(List.class))); - - assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(Object.class), Utils.getTypeMirrorFromClass(String.class))); - assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(String.class), Utils.getTypeMirrorFromClass(List.class))); - assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(List.class), Utils.getTypeMirrorFromClass(ArrayList.class))); - - assertTrue(TypeUtils.areEqual(Utils.getParameterizedClass(List.class, String.class), Utils.getParameterizedClass(List.class, String.class))); - assertFalse(TypeUtils.areEqual(Utils.getParameterizedClass(List.class, String.class), Utils.getParameterizedClass(List.class, Integer.class))); - } - - @Test - public void isParameterizedType_isCorrect() throws Exception { - - Map> testMap = new HashMap<>(); - assertTrue(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testMap))); - - List testList = new ArrayList<>(); - assertTrue(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testList))); - - String testString = "test"; - assertFalse(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testString))); - - Object testObject = new Object(); - assertFalse(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testObject))); - } - - @Test - public void getOuterClassType_isCorrect() throws Exception { - - // Test different objects - HashMap> testMap = new HashMap<>(); - TypeMirror mapMirror = Utils.getTypeMirrorFromObject(testMap); - assertNotNull(mapMirror); - assertTrue(HashMap.class.getName().equals(TypeUtils.getOuterClassType(mapMirror))); - - ArrayList testList = new ArrayList<>(); - TypeMirror listMirror = Utils.getTypeMirrorFromObject(testList); - assertNotNull(listMirror); - assertTrue(ArrayList.class.getName().equals(TypeUtils.getOuterClassType(listMirror))); - - String testString = "test"; - TypeMirror stringMirror = Utils.getTypeMirrorFromObject(testString); - assertNotNull(stringMirror); - assertTrue(String.class.getName().equals(TypeUtils.getOuterClassType(stringMirror))); - - Object testObject = new Object(); - TypeMirror objectMirror = Utils.getTypeMirrorFromObject(testObject); - assertNotNull(objectMirror); - assertTrue(Object.class.getName().equals(TypeUtils.getOuterClassType(objectMirror))); - - // Test primitives - assertTrue(int.class.getName() - .equals(TypeUtils.getOuterClassType(types.getPrimitiveType(TypeKind.INT)))); - } - - @Test - public void isConcreteType_Element_isCorrect() throws Exception { - - Element concreteElement = Utils.getElementFromClass(DummyConcreteClass.class); - assertNotNull(concreteElement); - for (Element element : concreteElement.getEnclosedElements()) { - if (element instanceof VariableElement) { - assertTrue(TypeUtils.isConcreteType(element)); - } - } - - Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); - assertNotNull(genericElement); - for (Element element : genericElement.getEnclosedElements()) { - if (element instanceof VariableElement) { - if ("testString".equals(element.getSimpleName().toString())) { - assertTrue(TypeUtils.isConcreteType(element)); - } else { - assertFalse(TypeUtils.isConcreteType(element)); - } - } - } - - } - - @Test - public void isConcreteType_TypeMirror_isCorrect() throws Exception { - - Element concreteElement = Utils.getElementFromClass(DummyConcreteClass.class); - assertNotNull(concreteElement); - for (Element element : concreteElement.getEnclosedElements()) { - if (element instanceof VariableElement) { - assertTrue(TypeUtils.isConcreteType(element.asType())); - } - } - - Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); - assertNotNull(genericElement); - for (Element element : genericElement.getEnclosedElements()) { - if (element instanceof VariableElement) { - if ("testString".equals(element.getSimpleName().toString())) { - assertTrue(TypeUtils.isConcreteType(element.asType())); - } else { - assertFalse(TypeUtils.isConcreteType(element.asType())); - } - } - } - } - - @Test - public void isAbstract_isCorrect() throws Exception { - Element abstractElement = Utils.getElementFromClass(DummyAbstractClass.class); - Assert.assertTrue(TypeUtils.isAbstract(abstractElement)); - - Element concreteElement = Utils.getElementFromClass(DummyConcreteClass.class); - Assert.assertFalse(TypeUtils.isAbstract(concreteElement)); - - Element genericElement = Utils.getElementFromClass(DummyGenericClass.class); - Assert.assertFalse(TypeUtils.isAbstract(genericElement)); - - Element enumElement = Utils.getElementFromClass(DummyEnumClass.class); - Assert.assertFalse(TypeUtils.isAbstract(enumElement)); - - Element inheritedElement = Utils.getElementFromClass(DummyInheritedClass.class); - Assert.assertFalse(TypeUtils.isAbstract(inheritedElement)); - - } - - @Test - public void isParameterizedType_Element_isCorrect() throws Exception { - Map> testMap = new HashMap<>(); - assertTrue(TypeUtils.isParameterizedType(Utils.getElementFromObject(testMap))); - - List testList = new ArrayList<>(); - assertTrue(TypeUtils.isParameterizedType(Utils.getElementFromObject(testList))); - - String testString = "test"; - assertFalse(TypeUtils.isParameterizedType(Utils.getElementFromObject(testString))); - - Object testObject = new Object(); - assertFalse(TypeUtils.isParameterizedType(Utils.getElementFromObject(testObject))); - } - - @Test - public void testIsSupportedPrimitive_supportsTypes() throws Exception { - - // Check supported primitives - Assert.assertTrue(TypeUtils.isSupportedPrimitive(long.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(int.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(boolean.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(float.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(double.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(byte.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(char.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedPrimitive(short.class.getName())); - - // Check unsupported primitives - Assert.assertFalse(TypeUtils.isSupportedPrimitive(void.class.getName())); - - // Check non-primitives - Assert.assertFalse(TypeUtils.isSupportedPrimitive(String.class.getName())); - Assert.assertFalse(TypeUtils.isSupportedPrimitive(Object.class.getName())); - } - - @Test - public void testIsSupportedCollection_supportsTypes() throws Exception { - // Check supported list types - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(List.class))); - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(ArrayList.class))); - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Collection.class))); - - // Check unsupported list types - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(LinkedList.class))); - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Vector.class))); - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Stack.class))); - - Assert.assertFalse(TypeUtils.isSupportedCollection(null)); - - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Object.class))); - - // Check array types - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.INT)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.BOOLEAN)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.CHAR)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(String.class)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(Object.class)))); - } - - @Test - public void testIsSupportedList_supportsTypes() throws Exception { - // Check supported types - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(List.class))); - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(ArrayList.class))); - Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Collection.class))); - - // Check unsupported list types - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(LinkedList.class))); - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Vector.class))); - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Stack.class))); - - - Assert.assertFalse(TypeUtils.isSupportedCollection(null)); - - Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Object.class))); - - // Check supported array types - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.INT)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.BOOLEAN)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.CHAR)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(String.class)))); - Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(Object.class)))); - - } - - @Test - public void testIsSupportedNative_supportsCorrectTypes() throws Exception { - // Check supported primitives - Assert.assertTrue(TypeUtils.isSupportedNative(long.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(int.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(boolean.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(float.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(double.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(String.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(byte.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(char.class.getName())); - Assert.assertTrue(TypeUtils.isSupportedNative(short.class.getName())); - - // Check unsupported primitives - Assert.assertFalse(TypeUtils.isSupportedNative(void.class.getName())); - - // Check non-primitives - Assert.assertFalse(TypeUtils.isSupportedNative(Object.class.getName())); - } - - @Test - public void testIsMap_supportsCorrectTypes() throws Exception { - // Check null - Assert.assertFalse(TypeUtils.isSupportedMap(null)); - - // Check supported types - Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(Map.class))); - Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(HashMap.class))); - Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(LinkedHashMap.class))); - - // Check type that implements map - Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(DummyMapClass.class))); - - // Check other types - Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(Object.class))); - Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(DummyConcreteClass.class))); - Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(String.class))); - } -} \ No newline at end of file diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt new file mode 100644 index 00000000..9c90101c --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt @@ -0,0 +1,399 @@ +/* + * The MIT License (MIT) + *

+ * Copyright (c) 2016 Vimeo + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.vimeo.stag.processor + +import com.vimeo.stag.processor.dummy.* +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 +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import java.util.* +import javax.lang.model.element.TypeElement +import javax.lang.model.element.VariableElement +import javax.lang.model.type.TypeKind +import javax.lang.model.type.TypeMirror + +/** + * Unit tests for the annotation processor. + * Run using: `./gradlew :stag-library-compiler:test --continue` + */ +class TypeUtilsUnitTest : BaseUnitTest() { + + @Before + fun setup() = TypeUtils.initialize(types) + + @Test + @Throws(Exception::class) + fun testFinalClass_constructorFails() = + Utils.testZeroArgumentConstructorFinalClass(TypeUtils::class.java) + + @Test + @Throws(Exception::class) + fun getInheritedType_isCorrect() { + val concreteType = TypeUtils.getInheritedType(Utils.getElementFromClass(DummyInheritedClass::class.java)) + assertNotNull(concreteType) + + val realConcreteType = types.getDeclaredType(Utils.getElementFromClass(DummyGenericClass::class.java), + Utils.getTypeMirrorFromClass(String::class.java)) + + assertTrue(realConcreteType.toString() == concreteType!!.toString()) + + val stringInheritedType = TypeUtils.getInheritedType(Utils.getElementFromClass(String::class.java)) + assertNull(stringInheritedType) + + val enumType = TypeUtils.getInheritedType(Utils.getElementFromClass(DummyEnumClass::class.java)) + assertNull(enumType) + } + + /** + * This test is particularly susceptible to changes + * in the DummyGenericClass. Any fields + * added, removed, renamed, or changed, will probably + * break this test either explicitly, or implicitly. + * Any changes to that class need to be reflected here. + * + * @throws Exception thrown if the test fails. + */ + @Test + fun getConcreteMembers_isCorrect() { + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + + val genericMembers = HashMap() + genericElement.enclosedElements + .filterIsInstance() + .forEach { genericMembers.put(DirectFieldAccessor(it), it.asType()) } + + val concreteType = TypeUtils.getInheritedType(Utils.getElementFromClass(DummyInheritedClass::class.java)) + + assertNotNull(concreteType) + + val genericType = Utils.getGenericVersionOfClass(DummyGenericClass::class.java) + + assertNotNull(genericType) + + val members = TypeUtils.getConcreteMembers(concreteType!!, types.asElement(genericType) as TypeElement, genericMembers) + + + val stringType = Utils.getTypeMirrorFromClass(String::class.java) + assertNotNull(stringType) + + for ((key, value) in members) { + val getterCode = key.createGetterCode() + when { + getterCode.contentEquals("testObject = ") -> + assertTrue(value.toString() == stringType.toString()) + getterCode.contentEquals("testList = ") -> + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(ArrayList::class.java), stringType).toString()) + getterCode.contentEquals("testMap = ") -> + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(HashMap::class.java), stringType, stringType).toString()) + getterCode.contentEquals("testSet = ") -> + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(HashSet::class.java), stringType).toString()) + getterCode.contentEquals("testArrayMap = ") -> { + val listString = types.getDeclaredType(Utils.getElementFromClass(List::class.java), stringType) + + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(HashMap::class.java), stringType, listString).toString()) + } + getterCode.contentEquals("testListMap = ") -> { + val mapStringString = types.getDeclaredType(Utils.getElementFromClass(Map::class.java), stringType, stringType) + + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(ArrayList::class.java), mapStringString).toString()) + } + } + } + } + + @Test + fun isEnum_isCorrect() { + assertTrue(TypeUtils.isEnum(Utils.getElementFromClass(DummyEnumClass::class.java))) + + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyAbstractClass::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyClassWithConstructor::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyConcreteClass::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyGenericClass::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyInheritedClass::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(DummyMapClass::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(Any::class.java))) + assertFalse(TypeUtils.isEnum(Utils.getElementFromClass(String::class.java))) + } + + @Test + fun areEqual_isCorrect() { + assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(Any::class.java), Utils.getTypeMirrorFromClass(Any::class.java))) + assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(String::class.java), Utils.getTypeMirrorFromClass(String::class.java))) + assertTrue(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(List::class.java), Utils.getTypeMirrorFromClass(List::class.java))) + + assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(Any::class.java), Utils.getTypeMirrorFromClass(String::class.java))) + assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(String::class.java), Utils.getTypeMirrorFromClass(List::class.java))) + assertFalse(TypeUtils.areEqual(Utils.getTypeMirrorFromClass(List::class.java), Utils.getTypeMirrorFromClass(ArrayList::class.java))) + + assertTrue(TypeUtils.areEqual(Utils.getParameterizedClass(List::class.java, String::class.java), Utils.getParameterizedClass(List::class.java, String::class.java))) + assertFalse(TypeUtils.areEqual(Utils.getParameterizedClass(List::class.java, String::class.java), Utils.getParameterizedClass(List::class.java, Int::class.javaObjectType))) + } + + @Test + fun isParameterizedType_isCorrect() { + + val testMap = HashMap>() + assertTrue(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testMap))) + + val testList = ArrayList() + assertTrue(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testList))) + + val testString = "test" + assertFalse(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testString))) + + val testObject = Any() + assertFalse(TypeUtils.isParameterizedType(Utils.getTypeMirrorFromObject(testObject))) + } + + @Test + fun getOuterClassType_isCorrect() { + + // Test different objects + val testMap = HashMap>() + val mapMirror = Utils.getTypeMirrorFromObject(testMap) + assertNotNull(mapMirror) + assertTrue(HashMap::class.java.name == TypeUtils.getOuterClassType(mapMirror)) + + val testList = ArrayList() + val listMirror = Utils.getTypeMirrorFromObject(testList) + assertNotNull(listMirror) + assertTrue(ArrayList::class.java.name == TypeUtils.getOuterClassType(listMirror)) + + val testString = "test" + val stringMirror = Utils.getTypeMirrorFromObject(testString) + assertNotNull(stringMirror) + assertTrue(String::class.java.name == TypeUtils.getOuterClassType(stringMirror)) + + val testObject = Any() + val objectMirror = Utils.getTypeMirrorFromObject(testObject) + assertNotNull(objectMirror) + assertTrue(Any::class.java.name == TypeUtils.getOuterClassType(objectMirror)) + + // Test primitives + assertTrue(Int::class.javaPrimitiveType!!.name == TypeUtils.getOuterClassType(types.getPrimitiveType(TypeKind.INT))) + } + + @Test + @Throws(Exception::class) + fun isConcreteType_Element_isCorrect() { + + val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) + assertNotNull(concreteElement) + concreteElement.enclosedElements + .filterIsInstance() + .forEach { assertTrue(TypeUtils.isConcreteType(it)) } + + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + genericElement.enclosedElements + .filterIsInstance() + .forEach { + if ("testString" == it.simpleName.toString()) { + assertTrue(TypeUtils.isConcreteType(it)) + } else { + assertFalse(TypeUtils.isConcreteType(it)) + } + } + + } + + @Test + @Throws(Exception::class) + fun isConcreteType_TypeMirror_isCorrect() { + + val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) + assertNotNull(concreteElement) + concreteElement.enclosedElements + .filterIsInstance() + .forEach { assertTrue(TypeUtils.isConcreteType(it.asType())) } + + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + genericElement.enclosedElements + .filterIsInstance() + .forEach { + if ("testString" == it.simpleName.toString()) { + assertTrue(TypeUtils.isConcreteType(it.asType())) + } else { + assertFalse(TypeUtils.isConcreteType(it.asType())) + } + } + } + + @Test + @Throws(Exception::class) + fun isAbstract_isCorrect() { + val abstractElement = Utils.getElementFromClass(DummyAbstractClass::class.java) + Assert.assertTrue(TypeUtils.isAbstract(abstractElement)) + + val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) + Assert.assertFalse(TypeUtils.isAbstract(concreteElement)) + + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + Assert.assertFalse(TypeUtils.isAbstract(genericElement)) + + val enumElement = Utils.getElementFromClass(DummyEnumClass::class.java) + Assert.assertFalse(TypeUtils.isAbstract(enumElement)) + + val inheritedElement = Utils.getElementFromClass(DummyInheritedClass::class.java) + Assert.assertFalse(TypeUtils.isAbstract(inheritedElement)) + + } + + @Test + @Throws(Exception::class) + fun isParameterizedType_Element_isCorrect() { + val testMap = HashMap>() + assertTrue(TypeUtils.isParameterizedType(Utils.getElementFromObject(testMap))) + + val testList = ArrayList() + assertTrue(TypeUtils.isParameterizedType(Utils.getElementFromObject(testList))) + + val testString = "test" + assertFalse(TypeUtils.isParameterizedType(Utils.getElementFromObject(testString))) + + val testObject = Any() + assertFalse(TypeUtils.isParameterizedType(Utils.getElementFromObject(testObject))) + } + + @Test + @Throws(Exception::class) + fun testIsSupportedPrimitive_supportsTypes() { + + // Check supported primitives + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Long::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Int::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Boolean::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Float::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Double::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Byte::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Char::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedPrimitive(Short::class.javaPrimitiveType!!.name)) + + // Check unsupported primitives + Assert.assertFalse(TypeUtils.isSupportedPrimitive(Void.TYPE.name)) + + // Check non-primitives + Assert.assertFalse(TypeUtils.isSupportedPrimitive(String::class.java.name)) + Assert.assertFalse(TypeUtils.isSupportedPrimitive(Any::class.java.name)) + } + + @Test + @Throws(Exception::class) + fun testIsSupportedCollection_supportsTypes() { + // Check supported list types + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(List::class.java))) + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(ArrayList::class.java))) + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Collection::class.java))) + + // Check unsupported list types + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(LinkedList::class.java))) + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Vector::class.java))) + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Stack::class.java))) + + Assert.assertFalse(TypeUtils.isSupportedCollection(null)) + + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Any::class.java))) + + // Check array types + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.INT)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.BOOLEAN)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.CHAR)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(String::class.java)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(Any::class.java)))) + } + + @Test + @Throws(Exception::class) + fun testIsSupportedList_supportsTypes() { + // Check supported types + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(List::class.java))) + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(ArrayList::class.java))) + Assert.assertTrue(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Collection::class.java))) + + // Check unsupported list types + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(LinkedList::class.java))) + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Vector::class.java))) + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Stack::class.java))) + + + Assert.assertFalse(TypeUtils.isSupportedCollection(null)) + + Assert.assertFalse(TypeUtils.isSupportedCollection(Utils.getTypeMirrorFromClass(Any::class.java))) + + // Check supported array types + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.INT)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.BOOLEAN)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(types.getPrimitiveType(TypeKind.CHAR)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(String::class.java)))) + Assert.assertTrue(TypeUtils.isSupportedCollection(types.getArrayType(Utils.getTypeMirrorFromClass(Any::class.java)))) + + } + + @Test + @Throws(Exception::class) + fun testIsSupportedNative_supportsCorrectTypes() { + // Check supported primitives + Assert.assertTrue(TypeUtils.isSupportedNative(Long::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Int::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Boolean::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Float::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Double::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(String::class.java.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Byte::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Char::class.javaPrimitiveType!!.name)) + Assert.assertTrue(TypeUtils.isSupportedNative(Short::class.javaPrimitiveType!!.name)) + + // Check unsupported primitives + Assert.assertFalse(TypeUtils.isSupportedNative(Void.TYPE.name)) + + // Check non-primitives + Assert.assertFalse(TypeUtils.isSupportedNative(Any::class.java.name)) + } + + @Test + @Throws(Exception::class) + fun testIsMap_supportsCorrectTypes() { + // Check null + Assert.assertFalse(TypeUtils.isSupportedMap(null)) + + // Check supported types + Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(Map::class.java))) + Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(HashMap::class.java))) + Assert.assertTrue(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(LinkedHashMap::class.java))) + + // Check type that implements map + Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(DummyMapClass::class.java))) + + // Check other types + Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(Any::class.java))) + Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java))) + Assert.assertFalse(TypeUtils.isSupportedMap(Utils.getTypeMirrorFromClass(String::class.java))) + } +} \ No newline at end of file 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 deleted file mode 100644 index b1be1839..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * The MIT License (MIT) - *

- * Copyright (c) 2016 Vimeo - *

- * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - *

- * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - *

- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.vimeo.stag.processor; - -import com.vimeo.stag.processor.dummy.DummyGenericClass; -import com.vimeo.stag.processor.utils.Preconditions; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.TypeParameterElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; - -import static org.junit.Assert.assertTrue; - -final class Utils { - - @Nullable private static Elements elements; - @Nullable private static Types types; - - private Utils() { - } - - @NotNull - private static Elements safeElements() { - Preconditions.checkNotNull(elements); - return elements; - } - - @NotNull - 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); - - Utils.elements = elements; - Utils.types = types; - } - - public static void testZeroArgumentConstructorFinalClass(Class clazz) throws Exception { - boolean exceptionThrown = false; - try { - Constructor constructor = clazz.getDeclaredConstructor(); - constructor.setAccessible(true); - constructor.newInstance(); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof UnsupportedOperationException) { - exceptionThrown = true; - } - } - assertTrue(exceptionThrown); - } - - /** - * Gets the parameterized class with the given parameters. - * - * @param clazz the class to parameterize. - * @param parameters the parameters to use. - * @return the declared type mirror with the correct type parameters. - */ - @NotNull - public static DeclaredType getParameterizedClass(@NotNull Class clazz, @NotNull Class... parameters) { - TypeElement rootType = safeElements().getTypeElement(clazz.getName()); - TypeMirror[] params = new TypeMirror[parameters.length]; - - for (int n = 0; n < parameters.length; n++) { - params[n] = safeElements().getTypeElement(parameters[n].getName()).asType(); - } - - return safeTypes().getDeclaredType(rootType, params); - } - - @Nullable - public static TypeElement getElementFromClass(@NotNull Class clazz) { - return safeElements().getTypeElement(clazz.getName()); - } - - @Nullable - public static TypeMirror getTypeMirrorFromClass(@NotNull Class clazz) { - TypeElement element = getElementFromClass(clazz); - return element != null ? element.asType() : null; - } - - @Nullable - public static TypeElement getElementFromObject(@NotNull Object object) { - return safeElements().getTypeElement(object.getClass().getName()); - } - - @Nullable - public static TypeMirror getTypeMirrorFromObject(@NotNull Object object) { - TypeElement element = getElementFromObject(object); - return element != null ? element.asType() : null; - } - - @NotNull - public static TypeMirror getGenericVersionOfClass(@NotNull Class clazz) { - List params = - 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); - } - -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.kt new file mode 100644 index 00000000..998c05fc --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.kt @@ -0,0 +1,100 @@ +/* + * The MIT License (MIT) + *

+ * Copyright (c) 2016 Vimeo + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.vimeo.stag.processor + +import com.vimeo.stag.processor.dummy.DummyGenericClass +import com.vimeo.stag.processor.utils.Preconditions +import org.junit.Assert.assertTrue +import java.lang.reflect.InvocationTargetException +import javax.lang.model.element.TypeElement +import javax.lang.model.type.DeclaredType +import javax.lang.model.type.TypeMirror +import javax.lang.model.util.Elements +import javax.lang.model.util.Types + +internal object Utils { + + internal lateinit var elements: Elements + internal lateinit var types: Types + + private fun safeTypes(): Types { + Preconditions.checkNotNull(types) + return types + } + + @Throws(Exception::class) + fun testZeroArgumentConstructorFinalClass(clazz: Class) { + var exceptionThrown = false + try { + val constructor = clazz.getDeclaredConstructor() + constructor.isAccessible = true + constructor.newInstance() + } catch (e: InvocationTargetException) { + if (e.cause is UnsupportedOperationException) { + exceptionThrown = true + } + } + + assertTrue(exceptionThrown) + } + + /** + * Gets the parameterized class with the given parameters. + * + * @param clazz the class to parameterize. + * @param parameters the parameters to use. + * @return the declared type mirror with the correct type parameters. + */ + fun getParameterizedClass(clazz: Class<*>, vararg parameters: Class<*>): DeclaredType { + val rootType = elements.getTypeElement(clazz.name) + val params = parameters.map { elements.getTypeElement(it.name).asType() }.toTypedArray() + + return safeTypes().getDeclaredType(rootType, *params) + } + + fun getElementFromClass(clazz: Class<*>): TypeElement = elements.getTypeElement(clazz.name) + + fun getTypeMirrorFromClass(clazz: Class<*>): TypeMirror { + val element = getElementFromClass(clazz) + return element.asType() + } + + fun getElementFromObject(`object`: Any): TypeElement = elements.getTypeElement(`object`.javaClass.name) + + fun getTypeMirrorFromObject(`object`: Any): TypeMirror { + val element = getElementFromObject(`object`) + return element.asType() + } + + fun getGenericVersionOfClass(clazz: Class<*>): TypeMirror { + val params = elements.getTypeElement(clazz.name).typeParameters + val genericTypes = arrayOfNulls(params.size) + for (n in genericTypes.indices) { + genericTypes[n] = params[n].asType() + } + return safeTypes().getDeclaredType(elements.getTypeElement(DummyGenericClass::class.java.name), + *genericTypes) + } + +} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.kt similarity index 89% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.kt index 88161554..5888dc25 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyAbstractClass.kt @@ -21,10 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor.dummy -public abstract class DummyAbstractClass { +abstract class DummyAbstractClass { - private DummyConcreteClass concreteClass; + private val concreteClass: DummyConcreteClass? = null } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.java deleted file mode 100644 index dda176ce..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.vimeo.stag.processor.dummy; - -/** - * Created by anshul.garg on 09/03/17. - */ - -public class DummyClassWithConstructor { - public String string; - - public DummyClassWithConstructor(String string) { - this.string = string; - } - - public DummyClassWithConstructor() { - } -} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.kt new file mode 100644 index 00000000..411fba59 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.kt @@ -0,0 +1,16 @@ +package com.vimeo.stag.processor.dummy + +/** + * A dummy class that also has a constructor. + * + * Created by anshul.garg on 09/03/17. + */ +class DummyClassWithConstructor { + var string: String? = null + + constructor(string: String) { + this.string = string + } + + constructor() {} +} diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.kt similarity index 77% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.kt index 0c0e624f..5e267f0f 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyConcreteClass.kt @@ -21,20 +21,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor.dummy -import java.util.List; -import java.util.Map; +class DummyConcreteClass { -public class DummyConcreteClass { + internal var testInt: Int = 0 - int testInt; + internal var testObject: String? = null - String testObject; + internal var testList: List? = null - List testList; + internal var testMap: Map? = null - Map testMap; - - DummyGenericClass> dummyInheritedClass; + internal var dummyInheritedClass: DummyGenericClass>? = null } \ No newline at end of file diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.kt similarity index 94% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.kt index 2c837132..9f71785c 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyEnumClass.kt @@ -21,9 +21,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor.dummy -public enum DummyEnumClass { +enum class DummyEnumClass { A, B, C diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.kt similarity index 71% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.kt index 632b9635..68d597e2 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyGenericClass.kt @@ -21,19 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor.dummy -import com.vimeo.stag.processor.TypeUtilsUnitTest; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import com.vimeo.stag.processor.TypeUtilsUnitTest +import java.util.* /** * Do not change this class without sure the - * {@link TypeUtilsUnitTest#getConcreteMembers_isCorrect()} + * [TypeUtilsUnitTest.getConcreteMembers_isCorrect] * test still works correctly. All members of * this class should be tested by that test, * and any generic ones here should be explicitly @@ -41,22 +36,22 @@ * resolved correctly. * * @param the type the the inheriting type - * should be of. - */ -public class DummyGenericClass { + * should be of. + */ +open class DummyGenericClass { - String testString; + internal var testString: String? = null - T testObject; + internal var testObject: T? = null - ArrayList testList; + internal var testList: ArrayList? = null - HashMap testMap; + internal var testMap: HashMap? = null - HashSet testSet; + internal var testSet: HashSet? = null - HashMap> testArrayMap; + internal var testArrayMap: HashMap>? = null - ArrayList> testListMap; + internal var testListMap: ArrayList>? = null } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.kt similarity index 91% rename from stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.java rename to stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.kt index 5c962afb..6934795c 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.java +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyInheritedClass.kt @@ -21,8 +21,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package com.vimeo.stag.processor.dummy; +package com.vimeo.stag.processor.dummy -public class DummyInheritedClass extends DummyGenericClass { - -} +class DummyInheritedClass : DummyGenericClass() diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.kt new file mode 100644 index 00000000..19ca4146 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.kt @@ -0,0 +1,54 @@ +/* + * The MIT License (MIT) + *

+ * Copyright (c) 2016 Vimeo + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.vimeo.stag.processor.dummy + + +class DummyMapClass : MutableMap { + override val size: Int + get() = 0 + + override fun containsKey(key: Any) = false + + override fun containsValue(value: Any) = false + + override fun get(key: Any): Any? = null + + override fun isEmpty() = true + + override val entries: MutableSet> + get() = mutableSetOf() + override val keys: MutableSet + get() = mutableSetOf() + override val values: MutableCollection + get() = mutableListOf() + + override fun clear() {} + + override fun put(key: Any, value: Any) = null + + override fun putAll(from: Map) {} + + override fun remove(key: Any) = null + +} \ No newline at end of file diff --git a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/FinalFields.java b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java similarity index 61% rename from stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/FinalFields.java rename to stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java index 8ae7bb80..6082d725 100644 --- a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/FinalFields.java +++ b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java @@ -1,4 +1,4 @@ -package com.vimeo.stag.processor; +package com.vimeo.stag.processor.testcase; import com.vimeo.stag.UseStag; @@ -7,13 +7,11 @@ public class FinalFields { final String finalString; - public FinalFields() - { + public FinalFields() { finalString = null; } - public FinalFields(String finalString) - { + public FinalFields(String finalString) { this.finalString = finalString; } diff --git a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/PrivateFields.java b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java similarity index 61% rename from stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/PrivateFields.java rename to stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java index 9ba1c7f8..64c57225 100644 --- a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/PrivateFields.java +++ b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java @@ -1,4 +1,4 @@ -package com.vimeo.stag.processor; +package com.vimeo.stag.processor.testcase; import com.vimeo.stag.UseStag; @@ -7,13 +7,11 @@ public class PrivateFields { private String privateString; - public PrivateFields() - { + public PrivateFields() { privateString = null; } - public PrivateFields(String privateString) - { + public PrivateFields(String privateString) { this.privateString = privateString; } diff --git a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/User.java b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/User.java new file mode 100644 index 00000000..9ef8fb2b --- /dev/null +++ b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/User.java @@ -0,0 +1,45 @@ +/* + * The MIT License (MIT) + *

+ * Copyright (c) 2016 Vimeo + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.vimeo.stag.processor.testcase; + +import com.google.gson.annotations.SerializedName; +import com.vimeo.stag.UseStag; + +/** + * Simple valid model. + */ +@UseStag +public class User { + + @SerializedName("name") + public String mName; + + @SerializedName("location") + public String mLocation; + + @Override + public String toString() { + return "name: " + mName + ", location: " + mLocation; + } +} \ No newline at end of file diff --git a/stag-library/build.gradle b/stag-library/build.gradle index 7f1e8d01..29aca55f 100644 --- a/stag-library/build.gradle +++ b/stag-library/build.gradle @@ -3,8 +3,8 @@ apply plugin: 'jacoco' apply plugin: 'maven-publish' compileJava { - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = "1.7" + targetCompatibility = "1.7" } jacoco { diff --git a/stag-library/src/main/java/com/vimeo/stag/KnownTypeAdapters.java b/stag-library/src/main/java/com/vimeo/stag/KnownTypeAdapters.java index e4924e75..4eabb3a6 100644 --- a/stag-library/src/main/java/com/vimeo/stag/KnownTypeAdapters.java +++ b/stag-library/src/main/java/com/vimeo/stag/KnownTypeAdapters.java @@ -419,13 +419,15 @@ public ArrayTypeAdapter(@NotNull TypeAdapter valueTypeAdapter, @Override public void write(JsonWriter writer, T[] value) throws IOException { - writer.beginArray(); - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { + writer.beginArray(); for (T item : value) { mValueTypeAdapter.write(writer, item); } + writer.endArray(); } - writer.endArray(); } @Override @@ -463,7 +465,9 @@ private PrimitiveIntegerArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable int[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (int item : value) { writer.value(item); @@ -496,7 +500,9 @@ private PrimitiveLongArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable long[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (long item : value) { writer.value(item); @@ -529,7 +535,9 @@ private PrimitiveDoubleArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable double[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (double item : value) { writer.value(item); @@ -562,7 +570,9 @@ private PrimitiveShortArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable short[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (short item : value) { writer.value(item); @@ -595,7 +605,9 @@ private PrimitiveFloatArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable float[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (float item : value) { writer.value(item); @@ -628,7 +640,9 @@ private PrimitiveBooleanArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable boolean[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (boolean item : value) { writer.value(item); @@ -661,7 +675,9 @@ private PrimitiveByteArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable byte[] value) throws IOException { - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { writer.beginArray(); for (byte item : value) { writer.value(item); @@ -696,7 +712,9 @@ private PrimitiveCharArrayAdapter() { } public static void write(@NotNull JsonWriter writer, @Nullable char[] value) throws IOException { - if (value != null) { + if (value == null) { + writer.nullValue(); + } else { String string = String.valueOf(value); STRING_NULL_SAFE_TYPE_ADAPTER.write(writer, string); } @@ -804,13 +822,15 @@ public ListTypeAdapter(@NotNull TypeAdapter valueTypeAdapter, @Override public void write(JsonWriter writer, T value) throws IOException { - writer.beginArray(); - if (null != value) { + if (value == null) { + writer.nullValue(); + } else { + writer.beginArray(); for (V item : value) { valueTypeAdapter.write(writer, item); } + writer.endArray(); } - writer.endArray(); } @Override @@ -856,7 +876,7 @@ public MapTypeAdapter(@NotNull TypeAdapter keyTypeAdapter, @Override public void write(JsonWriter writer, T value) throws IOException { - if (null == value) { + if (value == null) { writer.nullValue(); return; }