From d68401759ae1a126feee93204a3991d1a0a8f29c Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Sat, 2 Sep 2017 11:02:03 -0400 Subject: [PATCH 01/19] Updating the PR template --- .github/PULL_REQUEST_TEMPLATE.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3b72e3fd..60046397 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,12 +1,8 @@ -#### Ticket -**Required for Vimeans only** -[TICKET_NUMBER](https://vimean.atlassian.net/browse/TICKET_NUMBER) +#### Issue +(If applicable) -#### 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. From 61495570205a7dc0b7311b1072a1bd4173cc5429 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Sat, 2 Sep 2017 11:03:30 -0400 Subject: [PATCH 02/19] Adding issue line --- .github/PULL_REQUEST_TEMPLATE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 60046397..496471a1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,6 @@ #### Issue (If applicable) +- https://github.com/vimeo/stag-java/issues/NUMBER #### Summary A brief but thorough description of the changes. From 3730fc302d445ccfe9b64b9705bce75bae873952 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 5 Sep 2017 13:59:58 -0400 Subject: [PATCH 03/19] Converting compiler unit tests to kaitlin --- sample-kotlin-model/build.gradle | 2 +- stag-library-compiler/build.gradle | 3 + .../AbstractAnnotationProcessorTest.java | 158 ------- .../AbstractAnnotationProcessorTest.kt | 240 ++++++++++ .../{BaseUnitTest.java => BaseUnitTest.kt} | 29 +- .../processor/CleanableJavaFileManager.java | 126 ----- .../processor/CleanableJavaFileManager.kt | 103 ++++ .../stag/processor/ElementUtilsUnitTest.java | 122 ----- .../stag/processor/ElementUtilsUnitTest.kt | 121 +++++ .../stag/processor/PreconditionsUnitTest.java | 84 ---- .../stag/processor/PreconditionsUnitTest.kt | 82 ++++ ...st.java => StagProcessorFunctionalTest.kt} | 31 +- .../stag/processor/TypeUtilsUnitTest.java | 443 ------------------ .../vimeo/stag/processor/TypeUtilsUnitTest.kt | 424 +++++++++++++++++ .../java/com/vimeo/stag/processor/Utils.java | 140 ------ .../java/com/vimeo/stag/processor/Utils.kt | 108 +++++ ...stractClass.java => DummyAbstractClass.kt} | 6 +- .../dummy/DummyClassWithConstructor.java | 16 - .../dummy/DummyClassWithConstructor.kt | 16 + ...ncreteClass.java => DummyConcreteClass.kt} | 17 +- ...{DummyEnumClass.java => DummyEnumClass.kt} | 4 +- ...GenericClass.java => DummyGenericClass.kt} | 33 +- ...ritedClass.java => DummyInheritedClass.kt} | 6 +- .../stag/processor/dummy/DummyMapClass.java | 96 ---- .../stag/processor/dummy/DummyMapClass.kt | 54 +++ 25 files changed, 1208 insertions(+), 1256 deletions(-) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/{BaseUnitTest.java => BaseUnitTest.kt} (71%) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.kt delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/{StagProcessorFunctionalTest.java => StagProcessorFunctionalTest.kt} (63%) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.kt rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/{DummyAbstractClass.java => DummyAbstractClass.kt} (89%) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyClassWithConstructor.kt rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/{DummyConcreteClass.java => DummyConcreteClass.kt} (77%) rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/{DummyEnumClass.java => DummyEnumClass.kt} (94%) rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/{DummyGenericClass.java => DummyGenericClass.kt} (71%) rename stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/{DummyInheritedClass.java => DummyInheritedClass.kt} (91%) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.kt diff --git a/sample-kotlin-model/build.gradle b/sample-kotlin-model/build.gradle index 8d060c52..ee6861f1 100644 --- a/sample-kotlin-model/build.gradle +++ b/sample-kotlin-model/build.gradle @@ -60,7 +60,7 @@ dependencies { compile project(':stag-library') kapt project(':stag-library-compiler') - compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + testCompile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" } diff --git a/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index e35c952f..89d9d27a 100644 --- a/stag-library-compiler/build.gradle +++ b/stag-library-compiler/build.gradle @@ -34,6 +34,9 @@ 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" + testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" } test { 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/AbstractAnnotationProcessorTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt new file mode 100644 index 00000000..af6c4936 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt @@ -0,0 +1,240 @@ +/* + * Adapted from: 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. + * ==================================================================== + */ +package com.vimeo.stag.processor + +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import java.io.File +import java.io.IOException +import java.util.* +import javax.annotation.processing.Processor +import javax.tools.* +import javax.tools.Diagnostic.Kind + +/** + * Adapted from [https://raw.githubusercontent.com/ngs-doo/dsl-json/master/processor/src/test/java/com/dslplatform/json/AbstractAnnotationProcessorTest.java] + * + * Taken from https://github.com/anthonycr/Mezzanine/blob/66349b65e73ce58235353542aaeaefb3adc30b59/mezzanine-compiler/src/test/java/com/anthonycr/mezzanine/AbstractAnnotationProcessorTest.kt + * + * A base test class for [annotation processor][Processor] testing that + * attempts to compile source test cases that can be found on the classpath. + * + * @author aphillips + * @since 5 Jun 2009 + */ +abstract class AbstractAnnotationProcessorTest { + + /** + * @return the processor instances that should be tested + */ + protected abstract fun getProcessors(): Collection + + /** + * Attempts to compile the given compilation units using the Java Compiler + * API. + * + * The compilation units and all their dependencies are expected to be on + * the classpath. + * + * @param compilationUnits the classes to compile + * @return the [diagnostics][Diagnostic] returned by the compilation, + * as demonstrated in the documentation for [JavaCompiler] + * @see .compileTestCase + */ + protected fun compileTestCase(vararg compilationUnits: Class<*>) = + compileTestCase(Arrays.asList("-Adsljson.showdsl=true"), *compilationUnits) + + /** + * Attempts to compile the given compilation units using the Java Compiler + * API. + * + * The compilation units and all their dependencies are expected to be on + * the classpath. + * + * @param compileArguments compile arguments to pass into annotation processing + * @param compilationUnits the classes to compile + * @return the [diagnostics][Diagnostic] returned by the compilation, + * as demonstrated in the documentation for [JavaCompiler] + * @see .compileTestCase + */ + protected fun compileTestCase(compileArguments: List, + vararg compilationUnits: Class<*>): List> { + val compilationUnitPaths = compilationUnits.map { toResourcePath(it) }.toTypedArray() + + return compileTestCase(compilationUnitPaths, compileArguments) + } + + /** + * Attempts to compile the given compilation units using the Java Compiler API. + * + * The compilation units and all their dependencies are expected to be on the classpath. + * + * @param compilationUnitPaths the paths of the source files to compile, as would be expected + * by [ClassLoader.getResource] + * @return the [diagnostics][Diagnostic] returned by the compilation, as demonstrated in the + * documentation for [JavaCompiler] + * @see .compileTestCase + */ + protected fun compileTestCase(compilationUnitPaths: Array, + arguments: List): List> { + val compilationUnits: Collection + + try { + compilationUnits = findClasspathFiles(compilationUnitPaths) + } catch (exception: IOException) { + throw IllegalArgumentException( + "Unable to resolve compilation units ${Arrays.toString(compilationUnitPaths)} due to: ${exception.message}", + exception + ) + } + + val diagnosticCollector = DiagnosticCollector() + val fileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null) + + val compileArgs = ArrayList() + compileArgs.add("-proc:only") + compileArgs.addAll(arguments) + /* + * 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 + * only annotations on the classes being compiled are accessible. + * + * Information about the classes being compiled (such as what they are annotated + * with) is *not* available via the RoundEnvironment. However, if these classes + * are annotations, they certainly need to be validated. + */ + val task = COMPILER.getTask(null, fileManager, diagnosticCollector, + compileArgs, null, + fileManager.getJavaFileObjectsFromFiles(compilationUnits)) + task.setProcessors(getProcessors()) + task.call() + + try { + fileManager.close() + } catch (ignore: IOException) { + } + + val diagnostics = diagnosticCollector.diagnostics + if (diagnostics.size > 0 && diagnostics[0].kind == Kind.WARNING + && diagnostics[0].getMessage(Locale.ENGLISH).startsWith("Supported source version 'RELEASE_6' from annotation processor 'com.dslplatform.json.CompiledJsonProcessor' less than -source")) { + return diagnostics.subList(1, diagnostics.size) + } + + return diagnostics + } + + companion object { + private val SOURCE_FILE_SUFFIX = ".java" + private val COMPILER = ToolProvider.getSystemJavaCompiler() + + private fun toResourcePath(clazz: Class<*>) = clazz.name.replace('.', '/') + SOURCE_FILE_SUFFIX + + @JvmStatic + @Throws(IOException::class) + private fun findClasspathFiles(filenames: Array): Collection { + val classpathFiles = ArrayList(filenames.size) + + val cl = Thread.currentThread().contextClassLoader + val classpathRoot = File(cl.getResource("")!!.path) + val projectRoot = classpathRoot.parentFile.parentFile.parentFile + val javaRoot = File(File(File(projectRoot, "src"), "test"), "java") + + for (filename in filenames) { + val ind = filename.indexOf('$') + if (ind < 0) { + classpathFiles.add(File(javaRoot, filename)) + } else { + classpathFiles.add(File(javaRoot, filename.substring(0, ind) + ".java")) + } + } + + return classpathFiles + } + + /** + * Asserts that the compilation produced no errors, i.e. no diagnostics of type + * [Kind.ERROR]. + * + * @param diagnostics the result of the compilation + * @see .assertCompilationReturned + * @see .assertCompilationReturned + */ + @JvmStatic + protected fun assertCompilationSuccessful(diagnostics: List>) { + diagnostics.forEach { assertFalse(it.getMessage(Locale.ENGLISH), it.kind == Kind.ERROR) } + } + + /** + * Asserts that the compilation produced results of the following + * [Kinds][Kind] at the given line numbers, where the *n*th kind + * is expected at the *n*th line number. + * + * Does not check that these is the *only* diagnostic kinds returned! + * + * @param expectedDiagnosticKinds the kinds of diagnostic expected + * @param expectedLineNumbers the line numbers at which the diagnostics are expected + * @param diagnostics the result of the compilation + * @see .assertCompilationSuccessful + * @see .assertCompilationReturned + */ + @JvmStatic + protected fun assertCompilationReturned(expectedDiagnosticKinds: Array, + expectedLineNumbers: LongArray, + diagnostics: List>) { + assert(expectedDiagnosticKinds.size == expectedLineNumbers.size) + + for (i in expectedDiagnosticKinds.indices) { + assertCompilationReturned(expectedDiagnosticKinds[i], expectedLineNumbers[i], diagnostics, "") + } + } + + /** + * Asserts that the compilation produced a result of the following + * [Kind] at the given line number. + * + * Does not check that this is the *only* diagnostic kind returned! + * + * @param expectedDiagnosticKind the kind of diagnostic expected + * @param expectedLineNumber the line number at which the diagnostic is expected + * @param diagnostics the result of the compilation + * @param contains diagnostics results contains the message + * @see .assertCompilationSuccessful + * @see .assertCompilationReturned + */ + @JvmStatic + protected fun assertCompilationReturned(expectedDiagnosticKind: Kind, expectedLineNumber: Long, + diagnostics: List>, + contains: String): Diagnostic<*> { + + val detected = diagnostics.firstOrNull { it.kind == expectedDiagnosticKind && it.lineNumber == expectedLineNumber } + + val nonNullDetected = requireNotNull(detected) { + "Expected a result of kind $expectedDiagnosticKind at line $expectedLineNumber" + } + + assertTrue(nonNullDetected.getMessage(Locale.ENGLISH).contains(contains)) + + return nonNullDetected + } + } + +} \ No newline at end of file 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..0481fb35 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,34 @@ * 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 com.google.testing.compile.CompilationRule -import org.junit.Before; -import org.junit.Rule; +import org.junit.Before +import org.junit.Rule -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; +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 { @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/CleanableJavaFileManager.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt new file mode 100644 index 00000000..4571285c --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt @@ -0,0 +1,103 @@ +/* + * 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.* +import java.util.concurrent.LinkedBlockingQueue +import javax.tools.FileObject +import javax.tools.JavaFileManager +import javax.tools.JavaFileObject + +/** + * [JavaFileManager] implementation which tracks created files and allows them to be + * systematically deleted. + */ +internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : JavaFileManager { + + private val writtenFiles = LinkedBlockingQueue() + + @Throws(IOException::class) + fun purge() { + val toDelete = ArrayList() + writtenFiles.drainTo(toDelete) + for (file in toDelete) { + file.delete() + } + } + + override fun getClassLoader(location: JavaFileManager.Location) = + delegate.getClassLoader(location) + + @Throws(IOException::class) + override fun list(location: JavaFileManager.Location, s: String, set: Set, b: Boolean) = + delegate.list(location, s, set, b) + + override fun inferBinaryName(location: JavaFileManager.Location, javaFileObject: JavaFileObject) = + delegate.inferBinaryName(location, javaFileObject) + + override fun isSameFile(fileObject: FileObject, fileObject1: FileObject) = + delegate.isSameFile(fileObject, fileObject1) + + override fun handleOption(s: String, iterator: Iterator) = + delegate.handleOption(s, iterator) + + override fun hasLocation(location: JavaFileManager.Location) = + delegate.hasLocation(location) + + @Throws(IOException::class) + override fun getJavaFileForInput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind) = + delegate.getJavaFileForInput(location, s, kind) + + @Throws(IOException::class) + override fun getJavaFileForOutput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind, fileObject: FileObject): JavaFileObject { + val javaFileForOutput = delegate.getJavaFileForOutput(location, s, kind, fileObject) + writtenFiles.add(javaFileForOutput) + return javaFileForOutput + } + + @Throws(IOException::class) + override fun getFileForInput(location: JavaFileManager.Location, s: String, s1: String) = + delegate.getFileForInput(location, s, s1) + + @Throws(IOException::class) + override fun getFileForOutput(location: JavaFileManager.Location, s: String, s1: String, fileObject: FileObject): FileObject { + val fileForOutput = delegate.getFileForOutput(location, s, s1, fileObject) + writtenFiles.add(fileForOutput) + return fileForOutput + } + + @Throws(IOException::class) + override fun flush() { + delegate.flush() + } + + @Throws(IOException::class) + override fun close() { + delegate.close() + purge() + } + + override fun isSupportedOption(s: String) = 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..7fa51ab1 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/ElementUtilsUnitTest.kt @@ -0,0 +1,121 @@ +/* + * 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.* + +class ElementUtilsUnitTest : BaseUnitTest() { + + @Before + fun setup() { + ElementUtils.initialize(elements) + TypeUtils.initialize(types) + } + + @Test + @Throws(Exception::class) + fun testConstructor() { + Utils.testZeroArgumentConstructorFinalClass(ElementUtils::class.java) + } + + @Test + @Throws(Exception::class) + fun testGetTypeFromQualifiedName() { + Assert.assertEquals(Utils.getTypeMirrorFromClass(String::class.java), + ElementUtils.getTypeFromQualifiedName(String::class.java.name)) + Assert.assertEquals(Utils.getTypeMirrorFromClass(Any::class.java), + ElementUtils.getTypeFromQualifiedName(Any::class.java.name)) + Assert.assertEquals(Utils.getTypeMirrorFromClass(ArrayList::class.java), + ElementUtils.getTypeFromQualifiedName(ArrayList::class.java.name)) + Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyConcreteClass::class.java.name)) + Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyGenericClass::class.java.name)) + Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyInheritedClass::class.java.name)) + + Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyInheritedClass::class.java.name)) + Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyConcreteClass::class.java.name)) + Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java), + ElementUtils.getTypeFromQualifiedName(DummyGenericClass::class.java.name)) + } + + @Test + @Throws(Exception::class) + fun testGetPackage() { + Assert.assertEquals(String::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java)!!)) + Assert.assertEquals(ArrayList::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java)!!)) + Assert.assertEquals(Any::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java)!!)) + Assert.assertEquals(DummyGenericClass::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)!!)) + + Assert.assertEquals(DummyGenericClass::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java)!!)) + Assert.assertEquals(DummyConcreteClass::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java)!!)) + Assert.assertEquals(DummyInheritedClass::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)!!)) + + + Assert.assertNotEquals(Any::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java)!!)) + Assert.assertNotEquals(List::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java)!!)) + Assert.assertNotEquals(DummyInheritedClass::class.java.`package`.name, + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java)!!)) + } + + @Test + @Throws(Exception::class) + fun testGetConstructor() { + var executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String::class.java)) + Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(String::class.java)!!.toString()) + Assert.assertEquals(executableElement.parameters.size.toLong(), 0) + + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor::class.java)) + Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(DummyClassWithConstructor::class.java)!!.toString()) + Assert.assertEquals(executableElement.parameters.size.toLong(), 1) + Assert.assertEquals(executableElement.parameters[0].asType().toString(), Utils.getElementFromClass(String::class.java)!!.toString()) + + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)) + Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(DummyGenericClass::class.java)!!.toString()) + Assert.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/PreconditionsUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt new file mode 100644 index 00000000..d1154b17 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt @@ -0,0 +1,82 @@ +/* + * 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.* + +class PreconditionsUnitTest { + + @Test + @Throws(Exception::class) + fun testFinalClass_isNotInstantiable() { + Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) + } + + @Test(expected = NullPointerException::class) + fun checkNotNull_Null_throwsNullPointer() { + val o: Any? = null + Preconditions.checkNotNull(o) + } + + @Test + @Throws(Exception::class) + fun checkNotNull_NotNull() { + val o = Any() + Preconditions.checkNotNull(o) + } + + @Test + @Throws(Exception::class) + fun checkNotEmpty_NotEmpty() { + val list = listOf(Any()) + + Preconditions.checkNotEmpty(list) + } + + @Test(expected = IllegalStateException::class) + fun checkNotEmpty_Empty_throwsException() { + val list = ArrayList() + Preconditions.checkNotEmpty(list) + } + + @Test + @Throws(Exception::class) + fun checkTrue_True() { + Preconditions.checkTrue(true) + Preconditions.checkTrue(java.lang.Boolean.TRUE) + } + + @Test(expected = IllegalStateException::class) + fun checkTrue_FalsePrimitive_throwsException() { + Preconditions.checkTrue(false) + } + + @Test(expected = IllegalStateException::class) + fun checkTrue_FalseObject_throwsException() { + Preconditions.checkTrue(java.lang.Boolean.FALSE) + } + +} 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..6be40dbc 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,24 @@ * 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.junit.Test +import javax.tools.Diagnostic -import java.util.Collection; -import java.util.Collections; +class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { -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); - } + override fun getProcessors() = listOf(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() { + val output = compileTestCase(FinalFields::class.java) + + assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) } /** @@ -53,8 +46,10 @@ 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() { + val output = compileTestCase(PrivateFields::class.java) + + assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) } } 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..34f93aa4 --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt @@ -0,0 +1,424 @@ +/* + * 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 + @Throws(Exception::class) + fun getConcreteMembers_isCorrect() { + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + + val genericMembers = HashMap() + for (element in genericElement!!.enclosedElements) { + if (element is VariableElement) { + genericMembers.put(DirectFieldAccessor(element), element.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) { + if (key.createGetterCode().contentEquals("testObject = ")) { + + assertTrue(value.toString() == stringType!!.toString()) + + } else if (key.createGetterCode().contentEquals("testList = ")) { + + assertTrue(value + .toString() == types.getDeclaredType(Utils.getElementFromClass(ArrayList::class.java), + stringType).toString()) + + } else if (key.createGetterCode().contentEquals("testMap = ")) { + + assertTrue(value + .toString() == types.getDeclaredType(Utils.getElementFromClass(HashMap::class.java), stringType, + stringType).toString()) + + } else if (key.createGetterCode().contentEquals("testSet = ")) { + + assertTrue(value + .toString() == types.getDeclaredType(Utils.getElementFromClass(HashSet::class.java), stringType) + .toString()) + } else if (key.createGetterCode().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()) + } else if (key.createGetterCode().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 + @Throws(Exception::class) + 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.java))) + } + + @Test + @Throws(Exception::class) + 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 + @Throws(Exception::class) + 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) + for (element in concreteElement!!.enclosedElements) { + if (element is VariableElement) { + assertTrue(TypeUtils.isConcreteType(element)) + } + } + + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + for (element in genericElement!!.enclosedElements) { + if (element is VariableElement) { + if ("testString" == element.getSimpleName().toString()) { + assertTrue(TypeUtils.isConcreteType(element)) + } else { + assertFalse(TypeUtils.isConcreteType(element)) + } + } + } + + } + + @Test + @Throws(Exception::class) + fun isConcreteType_TypeMirror_isCorrect() { + + val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) + assertNotNull(concreteElement) + for (element in concreteElement!!.enclosedElements) { + if (element is VariableElement) { + assertTrue(TypeUtils.isConcreteType(element.asType())) + } + } + + val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) + assertNotNull(genericElement) + for (element in genericElement!!.enclosedElements) { + if (element is VariableElement) { + if ("testString" == element.getSimpleName().toString()) { + assertTrue(TypeUtils.isConcreteType(element.asType())) + } else { + assertFalse(TypeUtils.isConcreteType(element.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..caaf448a --- /dev/null +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/Utils.kt @@ -0,0 +1,108 @@ +/* + * 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 = arrayOfNulls(parameters.size) + + for (n in parameters.indices) { + params[n] = elements.getTypeElement(parameters[n].name).asType() + } + + return safeTypes().getDeclaredType(rootType, *params) + } + + fun getElementFromClass(clazz: Class<*>): TypeElement? { + return elements.getTypeElement(clazz.name) + } + + fun getTypeMirrorFromClass(clazz: Class<*>): TypeMirror? { + val element = getElementFromClass(clazz) + return element?.asType() + } + + fun getElementFromObject(`object`: Any): TypeElement? { + return 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.java b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java deleted file mode 100644 index 5ec84615..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/dummy/DummyMapClass.java +++ /dev/null @@ -1,96 +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.dummy; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; - -public class DummyMapClass implements Map { - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public boolean containsKey(Object o) { - return false; - } - - @Override - public boolean containsValue(Object o) { - return false; - } - - @Override - public Object get(Object o) { - return null; - } - - @Override - public Object put(Object o, Object o2) { - return null; - } - - @Override - public Object remove(Object o) { - return null; - } - - @Override - public void putAll(@NotNull Map map) { - - } - - @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/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 From 6c64ff0c27fc8f3501b7d5dc072de60ba16e3a73 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 5 Sep 2017 17:42:00 -0400 Subject: [PATCH 04/19] Making code more Kotlin idiomatic --- .../processor/CleanableJavaFileManager.kt | 2 +- .../stag/processor/ElementUtilsUnitTest.kt | 34 ++--- .../stag/processor/PreconditionsUnitTest.kt | 4 - .../vimeo/stag/processor/TypeUtilsUnitTest.kt | 130 ++++++++---------- .../java/com/vimeo/stag/processor/Utils.kt | 16 +-- 5 files changed, 78 insertions(+), 108 deletions(-) diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt index 4571285c..df9ef1a2 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt @@ -39,7 +39,7 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : private val writtenFiles = LinkedBlockingQueue() @Throws(IOException::class) - fun purge() { + private fun purge() { val toDelete = ArrayList() writtenFiles.drainTo(toDelete) for (file in toDelete) { 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 index 7fa51ab1..7d2bc6fa 100644 --- 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 @@ -76,44 +76,44 @@ class ElementUtilsUnitTest : BaseUnitTest() { @Throws(Exception::class) fun testGetPackage() { Assert.assertEquals(String::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java))) Assert.assertEquals(ArrayList::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java))) Assert.assertEquals(Any::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java))) Assert.assertEquals(DummyGenericClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))) Assert.assertEquals(DummyGenericClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java))) Assert.assertEquals(DummyConcreteClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java))) Assert.assertEquals(DummyInheritedClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))) Assert.assertNotEquals(Any::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java))) Assert.assertNotEquals(List::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java))) Assert.assertNotEquals(DummyInheritedClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java)!!)) + ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java))) } @Test @Throws(Exception::class) fun testGetConstructor() { - var executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String::class.java)) - Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(String::class.java)!!.toString()) + var executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String::class.java))!! + Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(String::class.java).toString()) Assert.assertEquals(executableElement.parameters.size.toLong(), 0) - executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor::class.java)) - Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(DummyClassWithConstructor::class.java)!!.toString()) + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor::class.java))!! + Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyClassWithConstructor::class.java).toString()) Assert.assertEquals(executableElement.parameters.size.toLong(), 1) - Assert.assertEquals(executableElement.parameters[0].asType().toString(), Utils.getElementFromClass(String::class.java)!!.toString()) + Assert.assertEquals(executableElement.parameters[0].asType().toString(), Utils.getElementFromClass(String::class.java).toString()) - executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java)) - Assert.assertEquals(executableElement!!.enclosingElement.toString(), Utils.getElementFromClass(DummyGenericClass::class.java)!!.toString()) + executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))!! + Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyGenericClass::class.java).toString()) Assert.assertEquals(executableElement.parameters.size.toLong(), 0) } diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt index d1154b17..f3f2d345 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt @@ -30,7 +30,6 @@ import java.util.* class PreconditionsUnitTest { @Test - @Throws(Exception::class) fun testFinalClass_isNotInstantiable() { Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) } @@ -42,14 +41,12 @@ class PreconditionsUnitTest { } @Test - @Throws(Exception::class) fun checkNotNull_NotNull() { val o = Any() Preconditions.checkNotNull(o) } @Test - @Throws(Exception::class) fun checkNotEmpty_NotEmpty() { val list = listOf(Any()) @@ -63,7 +60,6 @@ class PreconditionsUnitTest { } @Test - @Throws(Exception::class) fun checkTrue_True() { Preconditions.checkTrue(true) Preconditions.checkTrue(java.lang.Boolean.TRUE) 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 index 34f93aa4..19d1d923 100644 --- 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 @@ -82,17 +82,14 @@ class TypeUtilsUnitTest : BaseUnitTest() { * @throws Exception thrown if the test fails. */ @Test - @Throws(Exception::class) fun getConcreteMembers_isCorrect() { val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) assertNotNull(genericElement) val genericMembers = HashMap() - for (element in genericElement!!.enclosedElements) { - if (element is VariableElement) { - genericMembers.put(DirectFieldAccessor(element), element.asType()) - } - } + genericElement.enclosedElements + .filterIsInstance() + .forEach { genericMembers.put(DirectFieldAccessor(it), it.asType()) } val concreteType = TypeUtils.getInheritedType(Utils.getElementFromClass(DummyInheritedClass::class.java)) @@ -109,44 +106,31 @@ class TypeUtilsUnitTest : BaseUnitTest() { assertNotNull(stringType) for ((key, value) in members) { - if (key.createGetterCode().contentEquals("testObject = ")) { - - assertTrue(value.toString() == stringType!!.toString()) - - } else if (key.createGetterCode().contentEquals("testList = ")) { - - assertTrue(value - .toString() == types.getDeclaredType(Utils.getElementFromClass(ArrayList::class.java), - stringType).toString()) - - } else if (key.createGetterCode().contentEquals("testMap = ")) { - - assertTrue(value - .toString() == types.getDeclaredType(Utils.getElementFromClass(HashMap::class.java), stringType, - stringType).toString()) - - } else if (key.createGetterCode().contentEquals("testSet = ")) { - - assertTrue(value - .toString() == types.getDeclaredType(Utils.getElementFromClass(HashSet::class.java), stringType) - .toString()) - } else if (key.createGetterCode().contentEquals("testArrayMap = ")) { - val listString = types.getDeclaredType(Utils.getElementFromClass(List::class.java), stringType) + 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(HashMap::class.java), stringType, listString) - .toString()) - } else if (key.createGetterCode().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()) + assertTrue(value.toString() == types.getDeclaredType(Utils.getElementFromClass(ArrayList::class.java), mapStringString).toString()) + } } } } @Test - @Throws(Exception::class) fun isEnum_isCorrect() { assertTrue(TypeUtils.isEnum(Utils.getElementFromClass(DummyEnumClass::class.java))) @@ -162,20 +146,19 @@ class TypeUtilsUnitTest : BaseUnitTest() { @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)!!)) + 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)!!)) + 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.java))) } @Test - @Throws(Exception::class) fun isParameterizedType_isCorrect() { val testMap = HashMap>() @@ -192,29 +175,28 @@ class TypeUtilsUnitTest : BaseUnitTest() { } @Test - @Throws(Exception::class) fun getOuterClassType_isCorrect() { // Test different objects val testMap = HashMap>() val mapMirror = Utils.getTypeMirrorFromObject(testMap) assertNotNull(mapMirror) - assertTrue(HashMap::class.java.name == TypeUtils.getOuterClassType(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!!)) + 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!!)) + 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!!)) + assertTrue(Any::class.java.name == TypeUtils.getOuterClassType(objectMirror)) // Test primitives assertTrue(Int::class.javaPrimitiveType!!.name == TypeUtils.getOuterClassType(types.getPrimitiveType(TypeKind.INT))) @@ -226,23 +208,21 @@ class TypeUtilsUnitTest : BaseUnitTest() { val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) assertNotNull(concreteElement) - for (element in concreteElement!!.enclosedElements) { - if (element is VariableElement) { - assertTrue(TypeUtils.isConcreteType(element)) - } - } + concreteElement.enclosedElements + .filterIsInstance() + .forEach { assertTrue(TypeUtils.isConcreteType(it)) } val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) assertNotNull(genericElement) - for (element in genericElement!!.enclosedElements) { - if (element is VariableElement) { - if ("testString" == element.getSimpleName().toString()) { - assertTrue(TypeUtils.isConcreteType(element)) - } else { - assertFalse(TypeUtils.isConcreteType(element)) + genericElement.enclosedElements + .filterIsInstance() + .forEach { + if ("testString" == it.simpleName.toString()) { + assertTrue(TypeUtils.isConcreteType(it)) + } else { + assertFalse(TypeUtils.isConcreteType(it)) + } } - } - } } @@ -252,23 +232,21 @@ class TypeUtilsUnitTest : BaseUnitTest() { val concreteElement = Utils.getElementFromClass(DummyConcreteClass::class.java) assertNotNull(concreteElement) - for (element in concreteElement!!.enclosedElements) { - if (element is VariableElement) { - assertTrue(TypeUtils.isConcreteType(element.asType())) - } - } + concreteElement.enclosedElements + .filterIsInstance() + .forEach { assertTrue(TypeUtils.isConcreteType(it.asType())) } val genericElement = Utils.getElementFromClass(DummyGenericClass::class.java) assertNotNull(genericElement) - for (element in genericElement!!.enclosedElements) { - if (element is VariableElement) { - if ("testString" == element.getSimpleName().toString()) { - assertTrue(TypeUtils.isConcreteType(element.asType())) - } else { - assertFalse(TypeUtils.isConcreteType(element.asType())) + genericElement.enclosedElements + .filterIsInstance() + .forEach { + if ("testString" == it.simpleName.toString()) { + assertTrue(TypeUtils.isConcreteType(it.asType())) + } else { + assertFalse(TypeUtils.isConcreteType(it.asType())) + } } - } - } } @Test 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 index caaf448a..1799d737 100644 --- 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 @@ -77,22 +77,18 @@ internal object Utils { return safeTypes().getDeclaredType(rootType, *params) } - fun getElementFromClass(clazz: Class<*>): TypeElement? { - return elements.getTypeElement(clazz.name) - } + fun getElementFromClass(clazz: Class<*>): TypeElement = elements.getTypeElement(clazz.name) - fun getTypeMirrorFromClass(clazz: Class<*>): TypeMirror? { + fun getTypeMirrorFromClass(clazz: Class<*>): TypeMirror { val element = getElementFromClass(clazz) - return element?.asType() + return element.asType() } - fun getElementFromObject(`object`: Any): TypeElement? { - return elements.getTypeElement(`object`.javaClass.name) - } + fun getElementFromObject(`object`: Any): TypeElement = elements.getTypeElement(`object`.javaClass.name) - fun getTypeMirrorFromObject(`object`: Any): TypeMirror? { + fun getTypeMirrorFromObject(`object`: Any): TypeMirror { val element = getElementFromObject(`object`) - return element?.asType() + return element.asType() } fun getGenericVersionOfClass(clazz: Class<*>): TypeMirror { From 0d5f7a0e84512a02fb5f420fac75865a1f9ef826 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 5 Sep 2017 17:44:47 -0400 Subject: [PATCH 05/19] reverting mistaken compilation change --- sample-kotlin-model/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-kotlin-model/build.gradle b/sample-kotlin-model/build.gradle index ee6861f1..8d060c52 100644 --- a/sample-kotlin-model/build.gradle +++ b/sample-kotlin-model/build.gradle @@ -60,7 +60,7 @@ dependencies { compile project(':stag-library') kapt project(':stag-library-compiler') - testCompile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" } From 8a36518494f25c0c2d9791bbcd775f5bbe3d3d71 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 6 Sep 2017 10:26:08 -0400 Subject: [PATCH 06/19] Cleaning up and fixing all the tests --- build.gradle | 2 +- stag-library-compiler/build.gradle | 6 +- .../AbstractAnnotationProcessorTest.kt | 73 ++++++++++++++----- .../com/vimeo/stag/processor/BaseUnitTest.kt | 4 +- .../processor/CleanableJavaFileManager.kt | 6 +- .../processor/StagProcessorFunctionalTest.kt | 4 +- .../java/com/vimeo/stag/processor/Utils.kt | 6 +- stag-library/build.gradle | 4 +- 8 files changed, 68 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index 4c695899..df6a35ff 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.2-3' + ext.kotlin_version = '1.1.4-3' ext.jacoco_version = '0.7.9' // See http://www.eclemma.org/jacoco/ // android dependencies diff --git a/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index 89d9d27a..cad9c7b3 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 { @@ -36,7 +37,6 @@ dependencies { compile 'com.google.auto.service:auto-service:1.0-rc3' compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" } test { diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt index af6c4936..af47067a 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt @@ -24,10 +24,13 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import java.io.File import java.io.IOException +import java.net.URISyntaxException import java.util.* import javax.annotation.processing.Processor import javax.tools.* import javax.tools.Diagnostic.Kind +import kotlin.collections.ArrayList + /** * Adapted from [https://raw.githubusercontent.com/ngs-doo/dsl-json/master/processor/src/test/java/com/dslplatform/json/AbstractAnnotationProcessorTest.java] @@ -62,6 +65,10 @@ abstract class AbstractAnnotationProcessorTest { protected fun compileTestCase(vararg compilationUnits: Class<*>) = compileTestCase(Arrays.asList("-Adsljson.showdsl=true"), *compilationUnits) + protected fun compileTestCase(vararg compilationUnitResources: String): List> { + return compileTestCase(classNamesToFiles(*compilationUnitResources), listOf()) + } + /** * Attempts to compile the given compilation units using the Java Compiler * API. @@ -79,7 +86,19 @@ abstract class AbstractAnnotationProcessorTest { vararg compilationUnits: Class<*>): List> { val compilationUnitPaths = compilationUnits.map { toResourcePath(it) }.toTypedArray() - return compileTestCase(compilationUnitPaths, compileArguments) + return compileTestCase(compileArguments, *compilationUnitPaths) + } + + protected fun compileTestCase(compileArguments: List, + vararg compilationUnitPaths: String): List> { + try { + return compileTestCase(findClasspathFiles(compilationUnitPaths), compileArguments) + } catch (exception: IOException) { + throw IllegalArgumentException( + "Unable to resolve compilation units ${Arrays.toString(compilationUnitPaths)} due to: ${exception.message}", + exception + ) + } } /** @@ -93,21 +112,12 @@ abstract class AbstractAnnotationProcessorTest { * documentation for [JavaCompiler] * @see .compileTestCase */ - protected fun compileTestCase(compilationUnitPaths: Array, - arguments: List): List> { - val compilationUnits: Collection - - try { - compilationUnits = findClasspathFiles(compilationUnitPaths) - } catch (exception: IOException) { - throw IllegalArgumentException( - "Unable to resolve compilation units ${Arrays.toString(compilationUnitPaths)} due to: ${exception.message}", - exception - ) - } - + private fun compileTestCase(compilationUnits: Collection, + arguments: List): List> { val diagnosticCollector = DiagnosticCollector() - val fileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null) + + val javaFileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null) + val cleanableFileManager = CleanableJavaFileManager(javaFileManager) val compileArgs = ArrayList() compileArgs.add("-proc:only") @@ -122,14 +132,14 @@ abstract class AbstractAnnotationProcessorTest { * with) is *not* available via the RoundEnvironment. However, if these classes * are annotations, they certainly need to be validated. */ - val task = COMPILER.getTask(null, fileManager, diagnosticCollector, + val task = COMPILER.getTask(null, cleanableFileManager, diagnosticCollector, compileArgs, null, - fileManager.getJavaFileObjectsFromFiles(compilationUnits)) + javaFileManager.getJavaFileObjectsFromFiles(compilationUnits)) task.setProcessors(getProcessors()) task.call() try { - fileManager.close() + cleanableFileManager.close() } catch (ignore: IOException) { } @@ -146,11 +156,36 @@ abstract class AbstractAnnotationProcessorTest { private val SOURCE_FILE_SUFFIX = ".java" private val COMPILER = ToolProvider.getSystemJavaCompiler() + @JvmStatic private fun toResourcePath(clazz: Class<*>) = clazz.name.replace('.', '/') + SOURCE_FILE_SUFFIX + @JvmStatic + private fun classNamesToFiles(vararg classNames: String): Collection { + val files = ArrayList(classNames.size) + for (className in classNames) { + files.add(resourceToFile(className + SOURCE_FILE_SUFFIX)) + } + +// return classNames.map { resourceToFile(it + SOURCE_FILE_SUFFIX) } + + return files + } + + @JvmStatic + private fun resourceToFile(resourceName: String): File { + val resource = this::class.java.getResource(resourceName) + assert(resource.protocol == "file") + try { + return File(resource.toURI()) + } catch (e: URISyntaxException) { + throw e + } + + } + @JvmStatic @Throws(IOException::class) - private fun findClasspathFiles(filenames: Array): Collection { + private fun findClasspathFiles(filenames: Array): Collection { val classpathFiles = ArrayList(filenames.size) val cl = Thread.currentThread().contextClassLoader diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt index 0481fb35..df4607a5 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt @@ -24,10 +24,8 @@ 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 @@ -36,8 +34,10 @@ import javax.lang.model.util.Types */ open class BaseUnitTest { + @JvmField @Rule val rule = CompilationRule() + protected lateinit var elements: Elements protected lateinit var types: Types diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt index df9ef1a2..04765643 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt @@ -67,11 +67,11 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : delegate.hasLocation(location) @Throws(IOException::class) - override fun getJavaFileForInput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind) = + override fun getJavaFileForInput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind): JavaFileObject = delegate.getJavaFileForInput(location, s, kind) @Throws(IOException::class) - override fun getJavaFileForOutput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind, fileObject: FileObject): JavaFileObject { + override fun getJavaFileForOutput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind, fileObject: FileObject?): JavaFileObject { val javaFileForOutput = delegate.getJavaFileForOutput(location, s, kind, fileObject) writtenFiles.add(javaFileForOutput) return javaFileForOutput @@ -82,7 +82,7 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : delegate.getFileForInput(location, s, s1) @Throws(IOException::class) - override fun getFileForOutput(location: JavaFileManager.Location, s: String, s1: String, fileObject: FileObject): FileObject { + override fun getFileForOutput(location: JavaFileManager.Location, s: String, s1: String, fileObject: FileObject?): FileObject { val fileForOutput = delegate.getFileForOutput(location, s, s1, fileObject) writtenFiles.add(fileForOutput) return fileForOutput diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt index 6be40dbc..980c06c1 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt @@ -36,7 +36,7 @@ class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { */ @Test fun finalFieldsInAnnotatedClassReportsAsAnError() { - val output = compileTestCase(FinalFields::class.java) + val output = compileTestCase("bad/FinalFields") assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) } @@ -47,7 +47,7 @@ class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { */ @Test fun privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() { - val output = compileTestCase(PrivateFields::class.java) + val output = compileTestCase("bad/PrivateFields") assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) } 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 index 1799d737..998c05fc 100644 --- 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 @@ -68,11 +68,7 @@ internal object Utils { */ fun getParameterizedClass(clazz: Class<*>, vararg parameters: Class<*>): DeclaredType { val rootType = elements.getTypeElement(clazz.name) - val params = arrayOfNulls(parameters.size) - - for (n in parameters.indices) { - params[n] = elements.getTypeElement(parameters[n].name).asType() - } + val params = parameters.map { elements.getTypeElement(it.name).asType() }.toTypedArray() return safeTypes().getDeclaredType(rootType, *params) } 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 { From 7f9a102a1f7b648f3fbd259af20fa07f9bb6c4b5 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 6 Sep 2017 10:38:52 -0400 Subject: [PATCH 07/19] Fixing unit test --- .../src/test/java/com/vimeo/stag/processor/TypeUtilsUnitTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 19d1d923..eb54e602 100644 --- 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 @@ -155,7 +155,7 @@ class TypeUtilsUnitTest : BaseUnitTest() { 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.java))) + assertFalse(TypeUtils.areEqual(Utils.getParameterizedClass(List::class.java, String::class.java), Utils.getParameterizedClass(List::class.java, Int::class.javaObjectType))) } @Test From aff9cd1949a34d72272c26a2cb87c2e8fbfda3f7 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Wed, 6 Sep 2017 11:13:49 -0400 Subject: [PATCH 08/19] Cleaning up kotlin code --- .../processor/generators/StagGenerator.java | 2 +- .../AbstractAnnotationProcessorTest.kt | 31 ++++++------------- .../processor/CleanableJavaFileManager.kt | 12 +++---- .../stag/processor/ElementUtilsUnitTest.kt | 4 +-- .../stag/processor/PreconditionsUnitTest.kt | 13 +++----- .../vimeo/stag/processor/TypeUtilsUnitTest.kt | 9 ++---- 6 files changed, 24 insertions(+), 47 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/StagGenerator.java index 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/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt index af47067a..99f9aa37 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt @@ -65,9 +65,8 @@ abstract class AbstractAnnotationProcessorTest { protected fun compileTestCase(vararg compilationUnits: Class<*>) = compileTestCase(Arrays.asList("-Adsljson.showdsl=true"), *compilationUnits) - protected fun compileTestCase(vararg compilationUnitResources: String): List> { - return compileTestCase(classNamesToFiles(*compilationUnitResources), listOf()) - } + protected fun compileTestCase(vararg compilationUnitResources: String): List> = + compileTestCase(classNamesToFiles(*compilationUnitResources), listOf()) /** * Attempts to compile the given compilation units using the Java Compiler @@ -91,8 +90,8 @@ abstract class AbstractAnnotationProcessorTest { protected fun compileTestCase(compileArguments: List, vararg compilationUnitPaths: String): List> { - try { - return compileTestCase(findClasspathFiles(compilationUnitPaths), compileArguments) + return try { + compileTestCase(findClasspathFiles(compilationUnitPaths), compileArguments) } catch (exception: IOException) { throw IllegalArgumentException( "Unable to resolve compilation units ${Arrays.toString(compilationUnitPaths)} due to: ${exception.message}", @@ -153,30 +152,21 @@ abstract class AbstractAnnotationProcessorTest { } companion object { - private val SOURCE_FILE_SUFFIX = ".java" + private const val SOURCE_FILE_SUFFIX = ".java" private val COMPILER = ToolProvider.getSystemJavaCompiler() @JvmStatic private fun toResourcePath(clazz: Class<*>) = clazz.name.replace('.', '/') + SOURCE_FILE_SUFFIX @JvmStatic - private fun classNamesToFiles(vararg classNames: String): Collection { - val files = ArrayList(classNames.size) - for (className in classNames) { - files.add(resourceToFile(className + SOURCE_FILE_SUFFIX)) - } - -// return classNames.map { resourceToFile(it + SOURCE_FILE_SUFFIX) } - - return files - } + private fun classNamesToFiles(vararg classNames: String): Collection = classNames.map { resourceToFile(it + SOURCE_FILE_SUFFIX) } @JvmStatic private fun resourceToFile(resourceName: String): File { val resource = this::class.java.getResource(resourceName) assert(resource.protocol == "file") - try { - return File(resource.toURI()) + return try { + File(resource.toURI()) } catch (e: URISyntaxException) { throw e } @@ -214,9 +204,8 @@ abstract class AbstractAnnotationProcessorTest { * @see .assertCompilationReturned */ @JvmStatic - protected fun assertCompilationSuccessful(diagnostics: List>) { - diagnostics.forEach { assertFalse(it.getMessage(Locale.ENGLISH), it.kind == Kind.ERROR) } - } + protected fun assertCompilationSuccessful(diagnostics: List>) = + diagnostics.forEach { assertFalse(it.getMessage(Locale.ENGLISH), it.kind == Kind.ERROR) } /** * Asserts that the compilation produced results of the following diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt index 04765643..4ac998ee 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt @@ -47,14 +47,14 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : } } - override fun getClassLoader(location: JavaFileManager.Location) = + override fun getClassLoader(location: JavaFileManager.Location): ClassLoader = delegate.getClassLoader(location) @Throws(IOException::class) - override fun list(location: JavaFileManager.Location, s: String, set: Set, b: Boolean) = + override fun list(location: JavaFileManager.Location, s: String, set: Set, b: Boolean): MutableIterable = delegate.list(location, s, set, b) - override fun inferBinaryName(location: JavaFileManager.Location, javaFileObject: JavaFileObject) = + override fun inferBinaryName(location: JavaFileManager.Location, javaFileObject: JavaFileObject): String = delegate.inferBinaryName(location, javaFileObject) override fun isSameFile(fileObject: FileObject, fileObject1: FileObject) = @@ -78,7 +78,7 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : } @Throws(IOException::class) - override fun getFileForInput(location: JavaFileManager.Location, s: String, s1: String) = + override fun getFileForInput(location: JavaFileManager.Location, s: String, s1: String): FileObject = delegate.getFileForInput(location, s, s1) @Throws(IOException::class) @@ -89,9 +89,7 @@ internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : } @Throws(IOException::class) - override fun flush() { - delegate.flush() - } + override fun flush() = delegate.flush() @Throws(IOException::class) override fun close() { 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 index 7d2bc6fa..8efde179 100644 --- 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 @@ -44,9 +44,7 @@ class ElementUtilsUnitTest : BaseUnitTest() { @Test @Throws(Exception::class) - fun testConstructor() { - Utils.testZeroArgumentConstructorFinalClass(ElementUtils::class.java) - } + fun testConstructor() = Utils.testZeroArgumentConstructorFinalClass(ElementUtils::class.java) @Test @Throws(Exception::class) diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt index f3f2d345..5fc580dd 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt @@ -30,9 +30,8 @@ import java.util.* class PreconditionsUnitTest { @Test - fun testFinalClass_isNotInstantiable() { - Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) - } + fun testFinalClass_isNotInstantiable() = + Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) @Test(expected = NullPointerException::class) fun checkNotNull_Null_throwsNullPointer() { @@ -66,13 +65,9 @@ class PreconditionsUnitTest { } @Test(expected = IllegalStateException::class) - fun checkTrue_FalsePrimitive_throwsException() { - Preconditions.checkTrue(false) - } + fun checkTrue_FalsePrimitive_throwsException() = Preconditions.checkTrue(false) @Test(expected = IllegalStateException::class) - fun checkTrue_FalseObject_throwsException() { - Preconditions.checkTrue(java.lang.Boolean.FALSE) - } + fun checkTrue_FalseObject_throwsException() = Preconditions.checkTrue(java.lang.Boolean.FALSE) } 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 index eb54e602..9c90101c 100644 --- 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 @@ -44,15 +44,12 @@ import javax.lang.model.type.TypeMirror class TypeUtilsUnitTest : BaseUnitTest() { @Before - fun setup() { - TypeUtils.initialize(types) - } + fun setup() = TypeUtils.initialize(types) @Test @Throws(Exception::class) - fun testFinalClass_constructorFails() { - Utils.testZeroArgumentConstructorFinalClass(TypeUtils::class.java) - } + fun testFinalClass_constructorFails() = + Utils.testZeroArgumentConstructorFinalClass(TypeUtils::class.java) @Test @Throws(Exception::class) From a7a241492f26b289dc02b8726e001b1cf49bfe12 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 15 Sep 2017 14:00:10 -0400 Subject: [PATCH 09/19] Cleaning up tests --- .../AbstractAnnotationProcessorTest.kt | 12 +-- .../com/vimeo/stag/processor/BaseUnitTest.kt | 1 - .../stag/processor/ElementUtilsUnitTest.kt | 102 +++++++++--------- .../stag/processor/PreconditionsUnitTest.kt | 22 +--- 4 files changed, 57 insertions(+), 80 deletions(-) diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt index 99f9aa37..dcd204fa 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt @@ -24,6 +24,7 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import java.io.File import java.io.IOException +import java.lang.IllegalArgumentException import java.net.URISyntaxException import java.util.* import javax.annotation.processing.Processor @@ -31,7 +32,6 @@ import javax.tools.* import javax.tools.Diagnostic.Kind import kotlin.collections.ArrayList - /** * Adapted from [https://raw.githubusercontent.com/ngs-doo/dsl-json/master/processor/src/test/java/com/dslplatform/json/AbstractAnnotationProcessorTest.java] * @@ -105,7 +105,7 @@ abstract class AbstractAnnotationProcessorTest { * * The compilation units and all their dependencies are expected to be on the classpath. * - * @param compilationUnitPaths the paths of the source files to compile, as would be expected + * @param compilationUnits the paths of the source files to compile, as would be expected * by [ClassLoader.getResource] * @return the [diagnostics][Diagnostic] returned by the compilation, as demonstrated in the * documentation for [JavaCompiler] @@ -118,9 +118,7 @@ abstract class AbstractAnnotationProcessorTest { val javaFileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null) val cleanableFileManager = CleanableJavaFileManager(javaFileManager) - val compileArgs = ArrayList() - compileArgs.add("-proc:only") - compileArgs.addAll(arguments) + val compileArgs = listOf("-proc:only") + arguments /* * Call the compiler with the "-proc:only" option. The "class names" * option (which could, in principle, be used instead of compilation @@ -143,7 +141,7 @@ abstract class AbstractAnnotationProcessorTest { } val diagnostics = diagnosticCollector.diagnostics - if (diagnostics.size > 0 && diagnostics[0].kind == Kind.WARNING + if (diagnostics.isNotEmpty() && diagnostics[0].kind == Kind.WARNING && diagnostics[0].getMessage(Locale.ENGLISH).startsWith("Supported source version 'RELEASE_6' from annotation processor 'com.dslplatform.json.CompiledJsonProcessor' less than -source")) { return diagnostics.subList(1, diagnostics.size) } @@ -179,7 +177,7 @@ abstract class AbstractAnnotationProcessorTest { val classpathFiles = ArrayList(filenames.size) val cl = Thread.currentThread().contextClassLoader - val classpathRoot = File(cl.getResource("")!!.path) + val classpathRoot = File(cl.getResource("").path) val projectRoot = classpathRoot.parentFile.parentFile.parentFile val javaRoot = File(File(File(projectRoot, "src"), "test"), "java") diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt index df4607a5..9f254f40 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/BaseUnitTest.kt @@ -41,7 +41,6 @@ open class BaseUnitTest { protected lateinit var elements: Elements protected lateinit var types: Types - @Before fun _setup() { elements = rule.elements 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 index 8efde179..e945029d 100644 --- 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 @@ -29,7 +29,8 @@ 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.Assert.assertEquals +import org.junit.Assert.assertNotEquals import org.junit.Before import org.junit.Test import java.util.* @@ -43,76 +44,69 @@ class ElementUtilsUnitTest : BaseUnitTest() { } @Test - @Throws(Exception::class) fun testConstructor() = Utils.testZeroArgumentConstructorFinalClass(ElementUtils::class.java) @Test - @Throws(Exception::class) fun testGetTypeFromQualifiedName() { - Assert.assertEquals(Utils.getTypeMirrorFromClass(String::class.java), - ElementUtils.getTypeFromQualifiedName(String::class.java.name)) - Assert.assertEquals(Utils.getTypeMirrorFromClass(Any::class.java), - ElementUtils.getTypeFromQualifiedName(Any::class.java.name)) - Assert.assertEquals(Utils.getTypeMirrorFromClass(ArrayList::class.java), - ElementUtils.getTypeFromQualifiedName(ArrayList::class.java.name)) - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyConcreteClass::class.java.name)) - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyGenericClass::class.java.name)) - Assert.assertEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyInheritedClass::class.java.name)) - - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyInheritedClass::class.java.name)) - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyConcreteClass::class.java.name)) - Assert.assertNotEquals(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java), - ElementUtils.getTypeFromQualifiedName(DummyGenericClass::class.java.name)) + 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 - @Throws(Exception::class) fun testGetPackage() { - Assert.assertEquals(String::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java))) - Assert.assertEquals(ArrayList::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java))) - Assert.assertEquals(Any::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java))) - Assert.assertEquals(DummyGenericClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))) - - Assert.assertEquals(DummyGenericClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyConcreteClass::class.java))) - Assert.assertEquals(DummyConcreteClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyInheritedClass::class.java))) - Assert.assertEquals(DummyInheritedClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(DummyGenericClass::class.java))) - - - Assert.assertNotEquals(Any::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(ArrayList::class.java))) - Assert.assertNotEquals(List::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(String::class.java))) - Assert.assertNotEquals(DummyInheritedClass::class.java.`package`.name, - ElementUtils.getPackage(Utils.getTypeMirrorFromClass(Any::class.java))) + 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 - @Throws(Exception::class) fun testGetConstructor() { var executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(String::class.java))!! - Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(String::class.java).toString()) - Assert.assertEquals(executableElement.parameters.size.toLong(), 0) + assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(String::class.java).toString()) + assertEquals(executableElement.parameters.size.toLong(), 0) executableElement = ElementUtils.getFirstConstructor(Utils.getTypeMirrorFromClass(DummyClassWithConstructor::class.java))!! - Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyClassWithConstructor::class.java).toString()) - Assert.assertEquals(executableElement.parameters.size.toLong(), 1) - Assert.assertEquals(executableElement.parameters[0].asType().toString(), Utils.getElementFromClass(String::class.java).toString()) + 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))!! - Assert.assertEquals(executableElement.enclosingElement.toString(), Utils.getElementFromClass(DummyGenericClass::class.java).toString()) - Assert.assertEquals(executableElement.parameters.size.toLong(), 0) + 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.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt index 5fc580dd..4df80443 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/PreconditionsUnitTest.kt @@ -25,7 +25,6 @@ package com.vimeo.stag.processor import com.vimeo.stag.processor.utils.Preconditions import org.junit.Test -import java.util.* class PreconditionsUnitTest { @@ -34,29 +33,16 @@ class PreconditionsUnitTest { Utils.testZeroArgumentConstructorFinalClass(Preconditions::class.java) @Test(expected = NullPointerException::class) - fun checkNotNull_Null_throwsNullPointer() { - val o: Any? = null - Preconditions.checkNotNull(o) - } + fun checkNotNull_Null_throwsNullPointer() = Preconditions.checkNotNull(null) @Test - fun checkNotNull_NotNull() { - val o = Any() - Preconditions.checkNotNull(o) - } + fun checkNotNull_NotNull() = Preconditions.checkNotNull(Any()) @Test - fun checkNotEmpty_NotEmpty() { - val list = listOf(Any()) - - Preconditions.checkNotEmpty(list) - } + fun checkNotEmpty_NotEmpty() = Preconditions.checkNotEmpty(listOf(Any())) @Test(expected = IllegalStateException::class) - fun checkNotEmpty_Empty_throwsException() { - val list = ArrayList() - Preconditions.checkNotEmpty(list) - } + fun checkNotEmpty_Empty_throwsException() = Preconditions.checkNotEmpty(listOf()) @Test fun checkTrue_True() { From 5d18327903e19113d5d460fce2b8003bb4ca2c92 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 29 Sep 2017 11:48:45 -0400 Subject: [PATCH 10/19] Updating kaitlin version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 63c2b8c1..c37cddd2 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 From b15f1c2065bc382f8b26cf8d6440b15b713cf736 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 29 Sep 2017 13:16:31 -0400 Subject: [PATCH 11/19] Removing abstract test in favor of simpler implementation using google/compile-testing --- stag-library-compiler/build.gradle | 3 +- .../AbstractAnnotationProcessorTest.kt | 262 ------------------ .../processor/CleanableJavaFileManager.kt | 101 ------- .../vimeo/stag/processor/ProcessorTester.kt | 68 +++++ .../processor/StagProcessorFunctionalTest.kt | 14 +- .../bad => testcase}/FinalFields.java | 8 +- .../bad => testcase}/PrivateFields.java | 8 +- 7 files changed, 81 insertions(+), 383 deletions(-) delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt delete mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/ProcessorTester.kt rename stag-library-compiler/src/test/resources/{com/vimeo/stag/processor/bad => testcase}/FinalFields.java (61%) rename stag-library-compiler/src/test/resources/{com/vimeo/stag/processor/bad => testcase}/PrivateFields.java (62%) diff --git a/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index cad9c7b3..55bc0e09 100644 --- a/stag-library-compiler/build.gradle +++ b/stag-library-compiler/build.gradle @@ -24,7 +24,8 @@ 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' // Forcibly add test resources to test classpath: https://code.google.com/p/android/issues/detail?id=64887 testRuntime files('build/resources/test') diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt deleted file mode 100644 index dcd204fa..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/AbstractAnnotationProcessorTest.kt +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Adapted from: 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. - * ==================================================================== - */ -package com.vimeo.stag.processor - -import org.junit.Assert.assertFalse -import org.junit.Assert.assertTrue -import java.io.File -import java.io.IOException -import java.lang.IllegalArgumentException -import java.net.URISyntaxException -import java.util.* -import javax.annotation.processing.Processor -import javax.tools.* -import javax.tools.Diagnostic.Kind -import kotlin.collections.ArrayList - -/** - * Adapted from [https://raw.githubusercontent.com/ngs-doo/dsl-json/master/processor/src/test/java/com/dslplatform/json/AbstractAnnotationProcessorTest.java] - * - * Taken from https://github.com/anthonycr/Mezzanine/blob/66349b65e73ce58235353542aaeaefb3adc30b59/mezzanine-compiler/src/test/java/com/anthonycr/mezzanine/AbstractAnnotationProcessorTest.kt - * - * A base test class for [annotation processor][Processor] testing that - * attempts to compile source test cases that can be found on the classpath. - * - * @author aphillips - * @since 5 Jun 2009 - */ -abstract class AbstractAnnotationProcessorTest { - - /** - * @return the processor instances that should be tested - */ - protected abstract fun getProcessors(): Collection - - /** - * Attempts to compile the given compilation units using the Java Compiler - * API. - * - * The compilation units and all their dependencies are expected to be on - * the classpath. - * - * @param compilationUnits the classes to compile - * @return the [diagnostics][Diagnostic] returned by the compilation, - * as demonstrated in the documentation for [JavaCompiler] - * @see .compileTestCase - */ - protected fun compileTestCase(vararg compilationUnits: Class<*>) = - compileTestCase(Arrays.asList("-Adsljson.showdsl=true"), *compilationUnits) - - protected fun compileTestCase(vararg compilationUnitResources: String): List> = - compileTestCase(classNamesToFiles(*compilationUnitResources), listOf()) - - /** - * Attempts to compile the given compilation units using the Java Compiler - * API. - * - * The compilation units and all their dependencies are expected to be on - * the classpath. - * - * @param compileArguments compile arguments to pass into annotation processing - * @param compilationUnits the classes to compile - * @return the [diagnostics][Diagnostic] returned by the compilation, - * as demonstrated in the documentation for [JavaCompiler] - * @see .compileTestCase - */ - protected fun compileTestCase(compileArguments: List, - vararg compilationUnits: Class<*>): List> { - val compilationUnitPaths = compilationUnits.map { toResourcePath(it) }.toTypedArray() - - return compileTestCase(compileArguments, *compilationUnitPaths) - } - - protected fun compileTestCase(compileArguments: List, - vararg compilationUnitPaths: String): List> { - return try { - compileTestCase(findClasspathFiles(compilationUnitPaths), compileArguments) - } catch (exception: IOException) { - throw IllegalArgumentException( - "Unable to resolve compilation units ${Arrays.toString(compilationUnitPaths)} due to: ${exception.message}", - exception - ) - } - } - - /** - * Attempts to compile the given compilation units using the Java Compiler API. - * - * The compilation units and all their dependencies are expected to be on the classpath. - * - * @param compilationUnits the paths of the source files to compile, as would be expected - * by [ClassLoader.getResource] - * @return the [diagnostics][Diagnostic] returned by the compilation, as demonstrated in the - * documentation for [JavaCompiler] - * @see .compileTestCase - */ - private fun compileTestCase(compilationUnits: Collection, - arguments: List): List> { - val diagnosticCollector = DiagnosticCollector() - - val javaFileManager = COMPILER.getStandardFileManager(diagnosticCollector, null, null) - val cleanableFileManager = CleanableJavaFileManager(javaFileManager) - - val compileArgs = listOf("-proc:only") + arguments - /* - * 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 - * only annotations on the classes being compiled are accessible. - * - * Information about the classes being compiled (such as what they are annotated - * with) is *not* available via the RoundEnvironment. However, if these classes - * are annotations, they certainly need to be validated. - */ - val task = COMPILER.getTask(null, cleanableFileManager, diagnosticCollector, - compileArgs, null, - javaFileManager.getJavaFileObjectsFromFiles(compilationUnits)) - task.setProcessors(getProcessors()) - task.call() - - try { - cleanableFileManager.close() - } catch (ignore: IOException) { - } - - val diagnostics = diagnosticCollector.diagnostics - if (diagnostics.isNotEmpty() && diagnostics[0].kind == Kind.WARNING - && diagnostics[0].getMessage(Locale.ENGLISH).startsWith("Supported source version 'RELEASE_6' from annotation processor 'com.dslplatform.json.CompiledJsonProcessor' less than -source")) { - return diagnostics.subList(1, diagnostics.size) - } - - return diagnostics - } - - companion object { - private const val SOURCE_FILE_SUFFIX = ".java" - private val COMPILER = ToolProvider.getSystemJavaCompiler() - - @JvmStatic - private fun toResourcePath(clazz: Class<*>) = clazz.name.replace('.', '/') + SOURCE_FILE_SUFFIX - - @JvmStatic - private fun classNamesToFiles(vararg classNames: String): Collection = classNames.map { resourceToFile(it + SOURCE_FILE_SUFFIX) } - - @JvmStatic - private fun resourceToFile(resourceName: String): File { - val resource = this::class.java.getResource(resourceName) - assert(resource.protocol == "file") - return try { - File(resource.toURI()) - } catch (e: URISyntaxException) { - throw e - } - - } - - @JvmStatic - @Throws(IOException::class) - private fun findClasspathFiles(filenames: Array): Collection { - val classpathFiles = ArrayList(filenames.size) - - val cl = Thread.currentThread().contextClassLoader - val classpathRoot = File(cl.getResource("").path) - val projectRoot = classpathRoot.parentFile.parentFile.parentFile - val javaRoot = File(File(File(projectRoot, "src"), "test"), "java") - - for (filename in filenames) { - val ind = filename.indexOf('$') - if (ind < 0) { - classpathFiles.add(File(javaRoot, filename)) - } else { - classpathFiles.add(File(javaRoot, filename.substring(0, ind) + ".java")) - } - } - - return classpathFiles - } - - /** - * Asserts that the compilation produced no errors, i.e. no diagnostics of type - * [Kind.ERROR]. - * - * @param diagnostics the result of the compilation - * @see .assertCompilationReturned - * @see .assertCompilationReturned - */ - @JvmStatic - protected fun assertCompilationSuccessful(diagnostics: List>) = - diagnostics.forEach { assertFalse(it.getMessage(Locale.ENGLISH), it.kind == Kind.ERROR) } - - /** - * Asserts that the compilation produced results of the following - * [Kinds][Kind] at the given line numbers, where the *n*th kind - * is expected at the *n*th line number. - * - * Does not check that these is the *only* diagnostic kinds returned! - * - * @param expectedDiagnosticKinds the kinds of diagnostic expected - * @param expectedLineNumbers the line numbers at which the diagnostics are expected - * @param diagnostics the result of the compilation - * @see .assertCompilationSuccessful - * @see .assertCompilationReturned - */ - @JvmStatic - protected fun assertCompilationReturned(expectedDiagnosticKinds: Array, - expectedLineNumbers: LongArray, - diagnostics: List>) { - assert(expectedDiagnosticKinds.size == expectedLineNumbers.size) - - for (i in expectedDiagnosticKinds.indices) { - assertCompilationReturned(expectedDiagnosticKinds[i], expectedLineNumbers[i], diagnostics, "") - } - } - - /** - * Asserts that the compilation produced a result of the following - * [Kind] at the given line number. - * - * Does not check that this is the *only* diagnostic kind returned! - * - * @param expectedDiagnosticKind the kind of diagnostic expected - * @param expectedLineNumber the line number at which the diagnostic is expected - * @param diagnostics the result of the compilation - * @param contains diagnostics results contains the message - * @see .assertCompilationSuccessful - * @see .assertCompilationReturned - */ - @JvmStatic - protected fun assertCompilationReturned(expectedDiagnosticKind: Kind, expectedLineNumber: Long, - diagnostics: List>, - contains: String): Diagnostic<*> { - - val detected = diagnostics.firstOrNull { it.kind == expectedDiagnosticKind && it.lineNumber == expectedLineNumber } - - val nonNullDetected = requireNotNull(detected) { - "Expected a result of kind $expectedDiagnosticKind at line $expectedLineNumber" - } - - assertTrue(nonNullDetected.getMessage(Locale.ENGLISH).contains(contains)) - - return nonNullDetected - } - } - -} \ No newline at end of file diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt deleted file mode 100644 index 4ac998ee..00000000 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/CleanableJavaFileManager.kt +++ /dev/null @@ -1,101 +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.* -import java.util.concurrent.LinkedBlockingQueue -import javax.tools.FileObject -import javax.tools.JavaFileManager -import javax.tools.JavaFileObject - -/** - * [JavaFileManager] implementation which tracks created files and allows them to be - * systematically deleted. - */ -internal class CleanableJavaFileManager(private val delegate: JavaFileManager) : JavaFileManager { - - private val writtenFiles = LinkedBlockingQueue() - - @Throws(IOException::class) - private fun purge() { - val toDelete = ArrayList() - writtenFiles.drainTo(toDelete) - for (file in toDelete) { - file.delete() - } - } - - override fun getClassLoader(location: JavaFileManager.Location): ClassLoader = - delegate.getClassLoader(location) - - @Throws(IOException::class) - override fun list(location: JavaFileManager.Location, s: String, set: Set, b: Boolean): MutableIterable = - delegate.list(location, s, set, b) - - override fun inferBinaryName(location: JavaFileManager.Location, javaFileObject: JavaFileObject): String = - delegate.inferBinaryName(location, javaFileObject) - - override fun isSameFile(fileObject: FileObject, fileObject1: FileObject) = - delegate.isSameFile(fileObject, fileObject1) - - override fun handleOption(s: String, iterator: Iterator) = - delegate.handleOption(s, iterator) - - override fun hasLocation(location: JavaFileManager.Location) = - delegate.hasLocation(location) - - @Throws(IOException::class) - override fun getJavaFileForInput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind): JavaFileObject = - delegate.getJavaFileForInput(location, s, kind) - - @Throws(IOException::class) - override fun getJavaFileForOutput(location: JavaFileManager.Location, s: String, kind: JavaFileObject.Kind, fileObject: FileObject?): JavaFileObject { - val javaFileForOutput = delegate.getJavaFileForOutput(location, s, kind, fileObject) - writtenFiles.add(javaFileForOutput) - return javaFileForOutput - } - - @Throws(IOException::class) - override fun getFileForInput(location: JavaFileManager.Location, s: String, s1: String): FileObject = - delegate.getFileForInput(location, s, s1) - - @Throws(IOException::class) - override fun getFileForOutput(location: JavaFileManager.Location, s: String, s1: String, fileObject: FileObject?): FileObject { - val fileForOutput = delegate.getFileForOutput(location, s, s1, fileObject) - writtenFiles.add(fileForOutput) - return fileForOutput - } - - @Throws(IOException::class) - override fun flush() = delegate.flush() - - @Throws(IOException::class) - override fun close() { - delegate.close() - purge() - } - - override fun isSupportedOption(s: String) = delegate.isSupportedOption(s) -} 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..ce72a9d4 --- /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 compile(vararg clazz: String): Compilation { + return Compiler.javac() + .withProcessors(processor()) + .compile(fileManager.getJavaFileObjects(*clazz.map { it.asClassPathFile() }.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.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt index 980c06c1..2d798a14 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt @@ -23,12 +23,12 @@ */ package com.vimeo.stag.processor +import org.assertj.core.api.Assertions.assertThat import org.junit.Test -import javax.tools.Diagnostic -class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { +class StagProcessorFunctionalTest { - override fun getProcessors() = listOf(StagProcessor()) + private val processorTester = ProcessorTester({ StagProcessor() }) /** * Ensure that final fields result in compile-time errors to prevent silent omission of fields @@ -36,9 +36,7 @@ class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { */ @Test fun finalFieldsInAnnotatedClassReportsAsAnError() { - val output = compileTestCase("bad/FinalFields") - - assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) + assertThat(processorTester.compile("testcase/FinalFields.java").isSuccessful()).isFalse() } /** @@ -47,9 +45,7 @@ class StagProcessorFunctionalTest : AbstractAnnotationProcessorTest() { */ @Test fun privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() { - val output = compileTestCase("bad/PrivateFields") - - assertCompilationReturned(arrayOf(Diagnostic.Kind.ERROR), longArrayOf(8), output) + assertThat(processorTester.compile("testcase/FinalFields.java").isSuccessful()).isFalse() } } diff --git a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/FinalFields.java b/stag-library-compiler/src/test/resources/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/testcase/FinalFields.java index 8ae7bb80..b08e5618 100644 --- a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/FinalFields.java +++ b/stag-library-compiler/src/test/resources/testcase/FinalFields.java @@ -1,4 +1,4 @@ -package com.vimeo.stag.processor; +package 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/testcase/PrivateFields.java similarity index 62% rename from stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/PrivateFields.java rename to stag-library-compiler/src/test/resources/testcase/PrivateFields.java index 9ba1c7f8..082aa2b9 100644 --- a/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/bad/PrivateFields.java +++ b/stag-library-compiler/src/test/resources/testcase/PrivateFields.java @@ -1,4 +1,4 @@ -package com.vimeo.stag.processor; +package 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; } From 2cd694e31346617558547addae152c630188d9de Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 29 Sep 2017 13:59:51 -0400 Subject: [PATCH 12/19] Fixing tests --- .../vimeo/stag/processor/ProcessorTester.kt | 4 +- .../processor/StagProcessorFunctionalTest.kt | 8 +++- .../stag/processor}/testcase/FinalFields.java | 2 +- .../processor}/testcase/PrivateFields.java | 2 +- .../vimeo/stag/processor/testcase/User.java | 45 +++++++++++++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) rename stag-library-compiler/src/test/resources/{ => com/vimeo/stag/processor}/testcase/FinalFields.java (85%) rename stag-library-compiler/src/test/resources/{ => com/vimeo/stag/processor}/testcase/PrivateFields.java (86%) create mode 100644 stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/User.java 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 index ce72a9d4..ed8ec432 100644 --- 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 @@ -36,10 +36,10 @@ class ProcessorTester(private val processor: () -> Processor) { * * @param clazz the class(es) to compile, in the form of `package/ClassName.java` */ - fun compile(vararg clazz: String): Compilation { + fun compileResource(vararg clazz: String): Compilation { return Compiler.javac() .withProcessors(processor()) - .compile(fileManager.getJavaFileObjects(*clazz.map { it.asClassPathFile() }.toTypedArray())) + .compile(fileManager.getJavaFileObjects(*clazz.map { javaClass.getResource(it).toURI() }.map { File(it) }.toTypedArray())) } /** diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt index 2d798a14..5e11f798 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt @@ -36,7 +36,7 @@ class StagProcessorFunctionalTest { */ @Test fun finalFieldsInAnnotatedClassReportsAsAnError() { - assertThat(processorTester.compile("testcase/FinalFields.java").isSuccessful()).isFalse() + assertThat(processorTester.compileResource("testcase/FinalFields.java").isSuccessful()).isFalse() } /** @@ -45,7 +45,11 @@ class StagProcessorFunctionalTest { */ @Test fun privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() { - assertThat(processorTester.compile("testcase/FinalFields.java").isSuccessful()).isFalse() + assertThat(processorTester.compileResource("testcase/FinalFields.java").isSuccessful()).isFalse() } + @Test + fun `User compiles successfully`() { + assertThat(processorTester.compileResource("testcase/User.java").isSuccessful()).isTrue() + } } diff --git a/stag-library-compiler/src/test/resources/testcase/FinalFields.java b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java similarity index 85% rename from stag-library-compiler/src/test/resources/testcase/FinalFields.java rename to stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java index b08e5618..6082d725 100644 --- a/stag-library-compiler/src/test/resources/testcase/FinalFields.java +++ b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/FinalFields.java @@ -1,4 +1,4 @@ -package testcase; +package com.vimeo.stag.processor.testcase; import com.vimeo.stag.UseStag; diff --git a/stag-library-compiler/src/test/resources/testcase/PrivateFields.java b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java similarity index 86% rename from stag-library-compiler/src/test/resources/testcase/PrivateFields.java rename to stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java index 082aa2b9..64c57225 100644 --- a/stag-library-compiler/src/test/resources/testcase/PrivateFields.java +++ b/stag-library-compiler/src/test/resources/com/vimeo/stag/processor/testcase/PrivateFields.java @@ -1,4 +1,4 @@ -package testcase; +package com.vimeo.stag.processor.testcase; import com.vimeo.stag.UseStag; 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 From fa99af6c1085f7a6e80e19811f0c514d06f37a91 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 2 Oct 2017 10:36:31 -0400 Subject: [PATCH 13/19] Emitting a null value for null objects rather than --- .../vimeo/stag/processor/generators/TypeAdapterGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java b/stag-library-compiler/src/main/java/com/vimeo/stag/processor/generators/TypeAdapterGenerator.java index 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(); From 57bbd2f1c7576afd8f1bdd0d2011b9197536dc41 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 2 Oct 2017 10:37:04 -0400 Subject: [PATCH 14/19] Ensure that knowntypeadatpers also handle null case --- .../com/vimeo/stag/KnownTypeAdapters.java | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) 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; } From 27cb2a6960fa3231a01e192ed2055131770aaa26 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Mon, 2 Oct 2017 14:24:37 -0400 Subject: [PATCH 15/19] Testing type adapters created in kotlin module --- sample-kotlin-model/build.gradle | 1 + .../vimeo/dummy/sample_kotlin/BoolFields.kt | 13 ++++-------- .../sample_kotlin/KotlinConcreteExample.kt | 18 ++++++++++++++++ .../sample_kotlin/KotlinGenericExample.kt | 15 +++++++++++++ .../dummy/sample_kotlin/KotlinSamples.kt | 21 +++++++------------ .../dummy/sample_kotlin/BoolFieldsTest.kt | 6 +++++- .../KotlinConcreteExampleTest.kt | 7 ++++++- .../dummy/sample_kotlin/KotlinSamplesTest.kt | 4 ++++ .../com/vimeo/dummy/sample_kotlin/Utils.kt | 21 +++++++++++++++++++ 9 files changed, 81 insertions(+), 25 deletions(-) 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..d818f381 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,10 @@ 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( + var stringField: String? = null, + var nonNullStringField: String = "default", + var intField: Int? = null, + var longField: Long = 1, + @SerializedName("boolean_field") var booleanField: Boolean? = null +) \ 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 From 585880685ebd489a04e9b176405258a0fda147ea Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 20 Oct 2017 14:21:46 -0400 Subject: [PATCH 16/19] Fixing test --- .../com/vimeo/stag/processor/StagProcessorFunctionalTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt index 5e11f798..712ec43a 100644 --- a/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt +++ b/stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorFunctionalTest.kt @@ -45,7 +45,7 @@ class StagProcessorFunctionalTest { */ @Test fun privateFieldsNoSettersOrGettersInAnnotatedClassReportsAsAnError() { - assertThat(processorTester.compileResource("testcase/FinalFields.java").isSuccessful()).isFalse() + assertThat(processorTester.compileResource("testcase/PrivateFields.java").isSuccessful()).isFalse() } @Test From 65a3c595f5d4734ab03fc90d0ab8e8e345b9f750 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 20 Oct 2017 15:18:53 -0400 Subject: [PATCH 17/19] Adding test case for null value writing --- .../vimeo/sample_java_model/NullFields.java | 36 +++++++++++++++++++ stag-library-compiler/build.gradle | 1 + .../processor/StagProcessorIntegrationTest.kt | 29 +++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 sample-java-model/src/main/java/com/vimeo/sample_java_model/NullFields.java create mode 100644 stag-library-compiler/src/test/java/com/vimeo/stag/processor/StagProcessorIntegrationTest.kt 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/stag-library-compiler/build.gradle b/stag-library-compiler/build.gradle index 55bc0e09..8f2aedea 100644 --- a/stag-library-compiler/build.gradle +++ b/stag-library-compiler/build.gradle @@ -26,6 +26,7 @@ dependencies { testCompile 'junit:junit:4.12' 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') 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 From ffea2aa595b4bb951e69419741aae37721281579 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 24 Oct 2017 12:02:23 -0400 Subject: [PATCH 18/19] Cleaning up sample --- .../com/vimeo/dummy/sample_kotlin/KotlinSamples.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) 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 d818f381..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 @@ -10,9 +10,10 @@ import com.vimeo.stag.UseStag */ @UseStag data 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 + @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 From 2064d6507d9e468ecc7dc4a0bb9fd08ff6152fb1 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Tue, 24 Oct 2017 13:09:02 -0400 Subject: [PATCH 19/19] Bumping version to 2.4.0 --- CHANGELOG.md | 6 ++++++ README.md | 4 ++-- build.gradle | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) 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 c37cddd2..95914842 100644 --- a/build.gradle +++ b/build.gradle @@ -40,5 +40,5 @@ allprojects { subprojects { group = 'com.vimeo.stag' - version = '2.3.3' + version = '2.4.0' }