Skip to content

Commit

Permalink
Merge pull request #240 from LachlanMcKee/develop
Browse files Browse the repository at this point in the history
Update master to 3.7.2
  • Loading branch information
LachlanMcKee authored Nov 28, 2019
2 parents f518ef3 + 5ee3ee2 commit be569a9
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 35 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Change Log
===========

Version 3.7.2 *(2019-11-28)*
----------------------------

* Improvement: Made incremental annotation processing opt in. By default it will no longer be incremental
* This is to avoid any unexpected build failures.
* Refer to the README to learn how to make the processor incremental.

Version 3.7.1 *(2019-11-20)*
----------------------------

Expand Down
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,34 @@ return new GsonBuilder()
.create();
```

#### Incremental annotation processing

You must update your build.gradle (for each module) to opt into incremental annotation processing.

When enabled, all custom annotations (annotations which are either themselves annotated with either: `@AutoGsonAdapter`, `@GsonSubType`, `@AutoGsonAdapterFactory`) must be registered in the build.gradle (comma separated), otherwise they will be silently ignored.

Examples of this configuration are as follows:

```groovy
// Standard annotation processor
javaCompileOptions {
annotationProcessorOptions {
arguments = [
'gsonpath.incremental': 'true',
'gsonpath.additionalAnnotations': 'com.example.CustomAutoGsonAdapter,com.example.CustomGsonSubType'
]
}
}
// Kotlin annotation processor (kapt)
kapt {
arguments {
arg("gsonpath.incremental", "true")
arg("gsonpath.additionalAnnotations", "com.example.CustomAutoGsonAdapter,com.example.CustomGsonSubType")
}
}
```

## Proguard
To use proguard within your project, you must add the generated type adapter factory. Using the example above, this would be:

Expand All @@ -133,8 +161,8 @@ To use proguard within your project, you must add the generated type adapter fac
This library is available on Maven, you can add it to your project using the following gradle dependencies:

```gradle
compile 'net.lachlanmckee:gsonpath:3.7.1'
apt 'net.lachlanmckee:gsonpath-compiler:3.7.1'
compile 'net.lachlanmckee:gsonpath:3.7.2'
apt 'net.lachlanmckee:gsonpath-compiler:3.7.2'
compile 'net.lachlanmckee:gsonpath-kt:3.7.1' // an optional Kotlin library
compile 'net.lachlanmckee:gsonpath-kt:3.7.2' // an optional Kotlin library
```
2 changes: 1 addition & 1 deletion compiler/standard/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
POM_ARTIFACT_ID=gsonpath-compiler
POM_NAME=gsonpath-compiler
VERSION_NAME=3.7.1
VERSION_NAME=3.7.2
POM_PACKAGING=jar
44 changes: 34 additions & 10 deletions compiler/standard/src/main/java/gsonpath/GsonProcessor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,43 @@ open class GsonProcessor : AbstractProcessor() {
}

override fun getSupportedAnnotationTypes(): Set<String> {
val additonalAnnotations: Set<String> = processingEnv.options["gsonpath.additionalAnnotations"]
?.split(",")
?.toSet()
?: emptySet()

return additonalAnnotations.plus(setOf(
AutoGsonAdapterFactory::class.java.canonicalName,
AutoGsonAdapter::class.java.canonicalName,
GsonSubtype::class.java.canonicalName
))
return incrementalMetadata
?.let { (customAnnotations) ->
customAnnotations.plus(setOf(
AutoGsonAdapterFactory::class.java.canonicalName,
AutoGsonAdapter::class.java.canonicalName,
GsonSubtype::class.java.canonicalName
))
}
?: setOf("*")
}

override fun getSupportedSourceVersion(): SourceVersion {
return SourceVersion.latestSupported()
}

override fun getSupportedOptions(): Set<String> {
return if (incrementalMetadata != null) {
setOf("org.gradle.annotation.processing.aggregating")
} else {
emptySet()
}
}

private val incrementalMetadata: IncrementalMetadata? by lazy {
if ("true" != processingEnv.options[OPTION_INCREMENTAL]) {
null
} else {
processingEnv.options[OPTION_ADDITIONAL_ANNOTATIONS]
?.let { IncrementalMetadata(it.split(",").toSet()) }
?: IncrementalMetadata(emptySet())
}
}

private data class IncrementalMetadata(val customAnnotations: Set<String>)

private companion object {
private const val OPTION_INCREMENTAL = "gsonpath.incremental"
private const val OPTION_ADDITIONAL_ANNOTATIONS = "gsonpath.additionalAnnotations"
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
gsonpath.GsonProcessor,aggregating
gsonpath.GsonProcessor,dynamic
2 changes: 1 addition & 1 deletion compiler/testing/integration/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ buildscript {
dependencies {
compile project(":compiler:testing:base")
compile "com.google.truth:truth:0.34"
compile "com.google.testing.compile:compile-testing:0.11"
compile "com.google.testing.compile:compile-testing:0.18"
compile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ class SubTypeTest {

@Test
fun testIndirectlyAnnotatedSubType() =
assertGeneratedContent(TestCriteria("generator/gson_sub_type/indirectly_annotated",
absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"),
relativeSourceNames = listOf("IndirectlyAnnotatedSubType.java"),
relativeGeneratedNames = listOf("IndirectlyAnnotatedSubType_GsonTypeAdapter.java")
), "-Agsonpath.additionalAnnotations=generator.gson_sub_type.indirectly_annotated.IndirectSubType")
assertGeneratedContent(
TestCriteria("generator/gson_sub_type/indirectly_annotated",
absoluteSourceNames = listOf("generator/standard/TestGsonTypeFactory.java"),
relativeSourceNames = listOf("IndirectlyAnnotatedSubType.java"),
relativeGeneratedNames = listOf("IndirectlyAnnotatedSubType_GsonTypeAdapter.java")
),
"-Agsonpath.incremental=true",
"-Agsonpath.additionalAnnotations=generator.gson_sub_type.indirectly_annotated.IndirectSubType")

@Test
fun givenDuplicateKeys_whenProcessorExecuted_expectDuplicateKeysError() =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,122 @@
package gsonpath.generator.standard

import gsonpath.generator.GeneratorTester.assertGeneratedContent
import gsonpath.generator.TestCriteria
import com.google.common.truth.Truth.assertAbout
import com.google.testing.compile.*
import com.google.testing.compile.CompileTester.GeneratedPredicateClause
import com.google.testing.compile.CompileTester.SuccessfulCompilationClause
import gsonpath.GsonProcessor
import org.hamcrest.CoreMatchers
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import javax.tools.JavaFileObject
import javax.tools.StandardLocation

class CustomAutoGsonAdapterTest {
@JvmField
@Rule
val expectedException: ExpectedException = ExpectedException.none()

private fun standardGeneratorTester(relativePath: String): GeneratorTester {
return GeneratorTester(relativePath)
.absoluteInputFiles("generator/standard/TestGsonTypeFactory.java")
}

@Test
fun testCustomAutoGsonAdapterAnnotation() {
assertGeneratedContent(TestCriteria("generator/standard/custom_adapter_annotation",
fun testCustomAutoGsonAdapterAnnotationWithoutIncrementalProcessing() {
standardGeneratorTester("generator/standard/custom_adapter_annotation")
.relativeInputFiles("CustomAutoGsonAdapter.java", "TestCustomAutoGsonAdapterModel.java")
.compilesWithoutError { relativePath ->
generatesFiles("$relativePath/TestCustomAutoGsonAdapterModel_GsonTypeAdapter.java")
}
}

absoluteSourceNames = listOf(
"generator/standard/TestGsonTypeFactory.java"),
@Test
fun testCustomAutoGsonAdapterAnnotationWithIncrementalProcessingAndAdditionalAnnotations() {
standardGeneratorTester("generator/standard/custom_adapter_annotation")
.relativeInputFiles("CustomAutoGsonAdapter.java", "TestCustomAutoGsonAdapterModel.java")
.isIncremental(true)
.additionalAnnotations("generator.standard.custom_adapter_annotation.CustomAutoGsonAdapter")
.compilesWithoutError { relativePath ->
generatesFiles("$relativePath/TestCustomAutoGsonAdapterModel_GsonTypeAdapter.java")
}
}

relativeSourceNames = listOf(
"CustomAutoGsonAdapter.java",
"TestCustomAutoGsonAdapterModel.java"),
@Test
fun testCustomAutoGsonAdapterAnnotationWithIncrementalProcessingAndNoAdditionalAnnotations() {
expectedException.expect(AssertionError::class.java)
expectedException.expectMessage(CoreMatchers.containsString("expected to generate file: " +
"/generator/standard/custom_adapter_annotation/TestCustomAutoGsonAdapterModel_GsonTypeAdapter.java"))

relativeGeneratedNames = listOf(
"TestCustomAutoGsonAdapterModel_GsonTypeAdapter.java")
), "-Agsonpath.additionalAnnotations=generator.standard.custom_adapter_annotation.CustomAutoGsonAdapter")
standardGeneratorTester("generator/standard/custom_adapter_annotation")
.relativeInputFiles("CustomAutoGsonAdapter.java", "TestCustomAutoGsonAdapterModel.java")
.isIncremental(true)
.compilesWithoutError {
generatesFileNamed(StandardLocation.SOURCE_OUTPUT,
"generator.standard.custom_adapter_annotation",
"TestCustomAutoGsonAdapterModel_GsonTypeAdapter.java")
}
}
}

class GeneratorTester(private val relativePath: String) {
private val javaFileObjects = mutableListOf<JavaFileObject>()
private val additionalAnnotations = mutableListOf<String>()
private var incremental = false

fun relativeInputFiles(vararg files: String): GeneratorTester {
files.forEach { javaFileObjects.add(JavaFileObjects.forResource("$relativePath/$it")) }
return this
}

fun absoluteInputFiles(vararg files: String): GeneratorTester {
files.forEach { javaFileObjects.add(JavaFileObjects.forResource(it)) }
return this
}

fun isIncremental(incremental: Boolean): GeneratorTester {
this.incremental = incremental
return this
}

fun additionalAnnotations(vararg annotations: String): GeneratorTester {
annotations.forEach { additionalAnnotations.add(it) }
return this
}

private fun buildTester(): CompileTester {
val compileTesterFactory: ProcessedCompileTesterFactory = if (javaFileObjects.size == 1) {
assertAbout(JavaSourceSubjectFactory.javaSource()).that(javaFileObjects.first())

} else {
// Since we have multiple sources, we need to use a slightly different assert.
assertAbout(JavaSourcesSubjectFactory.javaSources()).that(javaFileObjects)
}
return compileTesterFactory
.builderTransformIf(incremental) {
withCompilerOptions("-Agsonpath.incremental=true")
}
.builderTransformIf(additionalAnnotations.size > 0) {
withCompilerOptions("-Agsonpath.additionalAnnotations=${additionalAnnotations.joinToString()}")
}
.processedWith(GsonProcessor())
}

fun compilesWithoutError(func: GeneratedPredicateClause<SuccessfulCompilationClause>.(String) -> Unit) {
func(buildTester().compilesWithoutError().and(), relativePath)
}
}

fun <T> GeneratedPredicateClause<T>.generatesFiles(vararg files: String): T {
val generatedSources = files.map { JavaFileObjects.forResource(it) }
return if (files.size == 1) {
generatesSources(generatedSources.first())

} else {
generatesSources(generatedSources.first(),
*generatedSources.subList(1, generatedSources.size).toTypedArray())
}
}

private inline fun <T> T.builderTransformIf(predicate: Boolean, f: T.() -> T): T =
if (predicate) f(this) else this
2 changes: 1 addition & 1 deletion library-kt/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
POM_ARTIFACT_ID=gsonpath-kt
POM_NAME=gsonpath-kt
VERSION_NAME=3.7.1
VERSION_NAME=3.7.2
POM_PACKAGING=jar
2 changes: 1 addition & 1 deletion library/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
POM_ARTIFACT_ID=gsonpath
POM_NAME=gsonpath
VERSION_NAME=3.7.1
VERSION_NAME=3.7.2
POM_PACKAGING=jar
1 change: 1 addition & 0 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ buildscript {

kapt {
arguments {
arg("gsonpath.incremental", "true")
arg("gsonpath.additionalAnnotations", "gsonpath.kotlin.CustomAnnotation,gsonpath.kotlin.TypeSubType")
}
}
Expand Down

0 comments on commit be569a9

Please sign in to comment.