Skip to content

Commit 01742aa

Browse files
committed
KT-12303 Pass only relevant annotations to annotation processors
1 parent ed34ec0 commit 01742aa

File tree

17 files changed

+327
-4
lines changed

17 files changed

+327
-4
lines changed

libraries/tools/kotlin-annotation-processing/src/main/kotlin/org/jetbrains/kotlin/annotation/AnnotationProcessorWrapper.kt

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,25 @@ import javax.lang.model.element.TypeElement
2626
import javax.tools.Diagnostic
2727
import kotlin.properties.Delegates
2828

29-
public class AnnotationProcessorStub : AbstractProcessor() {
29+
class AnnotationProcessorStub : AbstractProcessor() {
3030
override fun process(annotations: Set<TypeElement>?, roundEnv: RoundEnvironment?) = true
3131
}
3232

33-
public abstract class AnnotationProcessorWrapper(
33+
abstract class AnnotationProcessorWrapper(
3434
private val processorFqName: String,
3535
private val taskQualifier: String
3636
) : Processor {
3737

3838
private companion object {
3939
val KAPT_ANNOTATION_OPTION = "kapt.annotations"
4040
val KAPT_KOTLIN_GENERATED_OPTION = "kapt.kotlin.generated"
41+
42+
/*
43+
* If no Java sources are provided, javac finishes without running Annotation Processing.
44+
* This is not what we want, so we generate a special class for this case
45+
* with a field annotated with KAPT_SPECIAL_ANNOTATION (see AnnotationProcessingManager.generateJavaHackFile).
46+
*/
47+
val KAPT_SPECIAL_ANNOTATION = "__gen.KotlinAptAnnotation"
4148
}
4249

4350
private val processor: Processor by lazy {
@@ -56,6 +63,8 @@ public abstract class AnnotationProcessorWrapper(
5663

5764
private var roundCounter = 0
5865

66+
private var handledAnnotationTypes: Set<String> = emptySet()
67+
5968
override fun getCompletions(
6069
element: Element?,
6170
annotation: AnnotationMirror?,
@@ -83,11 +92,13 @@ public abstract class AnnotationProcessorWrapper(
8392
}
8493

8594
processor.init(processingEnv)
95+
96+
handledAnnotationTypes = this.supportedAnnotationTypes
8697
}
8798

8899
override fun getSupportedAnnotationTypes(): MutableSet<String> {
89100
val supportedAnnotations = processor.supportedAnnotationTypes.toMutableSet()
90-
supportedAnnotations.add("__gen.KotlinAptAnnotation")
101+
supportedAnnotations.add(KAPT_SPECIAL_ANNOTATION)
91102
return supportedAnnotations
92103
}
93104

@@ -106,7 +117,10 @@ public abstract class AnnotationProcessorWrapper(
106117

107118
if (roundCounter == 1) {
108119
for (annotationFqName in kotlinAnnotationsProvider.annotatedKotlinElements.keys) {
109-
if (annotationFqName in existingFqNames) continue
120+
if (annotationFqName in existingFqNames
121+
|| annotationFqName == KAPT_SPECIAL_ANNOTATION
122+
|| annotationFqName !in handledAnnotationTypes // Filter out irrelevant annotations) continue
123+
) continue
110124
existingFqNames.add(annotationFqName)
111125
processingEnv.elementUtils.getTypeElement(annotationFqName)?.let { wrappedAnnotations += it }
112126
}

libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ fun getSomething() = 10
175175
}
176176
}
177177

178+
@Test
179+
fun testAndroidIcepickProject() {
180+
val project = Project("AndroidIcepickProject", gradleVersion)
181+
val options = defaultBuildOptions().copy(incremental = false)
182+
183+
project.build("assembleDebug", options = options) {
184+
assertSuccessful()
185+
}
186+
}
187+
178188
@Test
179189
fun testAndroidExtensions() {
180190
val project = Project("AndroidExtensionsProject", gradleVersion)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
apply plugin: 'com.android.application'
2+
apply plugin: 'kotlin-android'
3+
apply plugin: 'android-sdk-manager'
4+
5+
dependencies {
6+
compile "frankiesardo:icepick:3.2.0"
7+
kapt "frankiesardo:icepick-processor:3.2.0"
8+
9+
compile 'org.parceler:parceler-api:1.1.5'
10+
kapt 'org.parceler:parceler:1.1.5'
11+
12+
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
13+
}
14+
15+
android {
16+
compileSdkVersion 23
17+
buildToolsVersion "23.0.1"
18+
19+
defaultConfig {
20+
applicationId "com.example.icepick.kotlin"
21+
minSdkVersion 14
22+
targetSdkVersion 23
23+
versionCode 1
24+
versionName "1.0"
25+
}
26+
27+
lintOptions {
28+
abortOnError false
29+
}
30+
sourceSets {
31+
main.java.srcDirs += 'src/main/kotlin'
32+
}
33+
}
34+
35+
repositories {
36+
mavenCentral()
37+
maven {
38+
url "https://clojars.org/repo/"
39+
}
40+
mavenLocal()
41+
}
42+
43+
kapt {
44+
generateStubs = true
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.github.frankiesardo.icepick"
4+
android:versionCode="1"
5+
android:versionName="1.0">
6+
7+
<application
8+
android:allowBackup="true"
9+
android:label="@string/app_name"
10+
android:theme="@android:style/Theme.Holo.Light">
11+
<activity
12+
android:name=".MainActivity"
13+
android:label="@string/app_name">
14+
<intent-filter>
15+
<action android:name="android.intent.action.MAIN"/>
16+
17+
<category android:name="android.intent.category.LAUNCHER"/>
18+
</intent-filter>
19+
</activity>
20+
</application>
21+
22+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.github.frankiesardo.icepick
2+
3+
import android.content.Context
4+
import android.os.Parcelable
5+
import android.util.AttributeSet
6+
import com.sample.icepick.lib.BaseCustomView
7+
import icepick.State
8+
9+
class CustomView : BaseCustomView {
10+
@JvmField @State
11+
var textColor: Int? = null
12+
13+
constructor(context: Context) : super(context)
14+
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
15+
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
16+
17+
fun setTextColorWithAnotherMethod(color: Int) {
18+
this.textColor = color
19+
setTextColor(textColor!!)
20+
}
21+
22+
override fun onRestoreInstanceState(state: Parcelable) {
23+
super.onRestoreInstanceState(state)
24+
if (textColor != null) {
25+
setTextColorWithAnotherMethod(textColor!!)
26+
}
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.github.frankiesardo.icepick
2+
3+
import org.parceler.Parcel
4+
5+
@Parcel
6+
class Example {
7+
lateinit var name: String
8+
9+
@JvmField
10+
var age: Int = 0
11+
12+
constructor() { /*Required empty bean constructor*/
13+
}
14+
15+
constructor(age: Int, name: String) {
16+
this.age = age
17+
this.name = name
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.github.frankiesardo.icepick
2+
3+
import android.os.Bundle
4+
import android.os.Parcelable
5+
6+
import org.parceler.Parcels
7+
8+
import icepick.Bundler
9+
10+
class ExampleBundler : Bundler<Any> {
11+
override fun put(s: String, example: Any, bundle: Bundle) {
12+
bundle.putParcelable(s, Parcels.wrap(example))
13+
}
14+
15+
override fun get(s: String, bundle: Bundle): Any {
16+
return Parcels.unwrap<Any>(bundle.getParcelable<Parcelable>(s))
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.github.frankiesardo.icepick
2+
3+
import android.graphics.Color
4+
import android.os.Bundle
5+
import android.view.Menu
6+
import android.view.MenuItem
7+
import com.sample.icepick.lib.BaseActivity
8+
import icepick.State
9+
10+
class MainActivity : BaseActivity() {
11+
@JvmField @State(MyBundler::class)
12+
var message: String? = null
13+
14+
lateinit var customView: CustomView
15+
16+
override fun onCreate(savedInstanceState: Bundle?) {
17+
super.onCreate(savedInstanceState)
18+
setContentView(R.layout.activity_main)
19+
customView = findViewById(R.id.custom_view) as CustomView
20+
updateText()
21+
}
22+
23+
private fun updateText() {
24+
val defaultText = if (message == null || baseMessage == null) {
25+
"Use the menu to add some state"
26+
} else {
27+
baseMessage + message
28+
}
29+
customView.text = defaultText
30+
}
31+
32+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
33+
menuInflater.inflate(R.menu.main, menu)
34+
return super.onPrepareOptionsMenu(menu)
35+
}
36+
37+
override fun onMenuItemSelected(featureId: Int, item: MenuItem): Boolean {
38+
if (item.itemId == R.id.action_add_state) {
39+
customView.setBackgroundColorWithAnotherMethod(Color.BLUE)
40+
customView.setTextColorWithAnotherMethod(Color.WHITE)
41+
42+
baseMessage = "This state will be automagically "
43+
message = "saved and restored"
44+
updateText()
45+
return true
46+
}
47+
return super.onMenuItemSelected(featureId, item)
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.github.frankiesardo.icepick
2+
3+
import android.os.Bundle
4+
5+
import icepick.Bundler
6+
7+
class MyBundler : Bundler<String> {
8+
override fun put(key: String, value: String?, bundle: Bundle) {
9+
if (value != null) {
10+
bundle.putString(key, value + "*")
11+
}
12+
}
13+
14+
override fun get(key: String, bundle: Bundle): String? {
15+
return bundle.getString(key)
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.sample.icepick.lib
2+
3+
import android.app.Activity
4+
import android.os.Bundle
5+
import android.os.Parcelable
6+
import icepick.Icepick
7+
import icepick.State
8+
import android.util.Log
9+
10+
open class BaseActivity : Activity() {
11+
@JvmField @State
12+
var baseMessage: String? = null
13+
14+
override fun onCreate(savedInstanceState: Bundle?) {
15+
super.onCreate(savedInstanceState)
16+
Icepick.restoreInstanceState(this, savedInstanceState)
17+
}
18+
19+
override fun onSaveInstanceState(outState: Bundle) {
20+
super.onSaveInstanceState(outState)
21+
Icepick.saveInstanceState(this, outState)
22+
}
23+
}
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.sample.icepick.lib
2+
3+
import android.content.Context
4+
import android.os.Parcelable
5+
import android.util.AttributeSet
6+
import android.widget.TextView
7+
8+
import icepick.Icepick
9+
import icepick.State
10+
11+
open class BaseCustomView : TextView {
12+
@JvmField @State
13+
var backgroundColor: Int? = null
14+
15+
constructor(context: Context) : super(context)
16+
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
17+
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
18+
19+
fun setBackgroundColorWithAnotherMethod(color: Int) {
20+
this.backgroundColor = color
21+
setBackgroundColor(color)
22+
}
23+
24+
override fun onSaveInstanceState(): Parcelable {
25+
return Icepick.saveInstanceState(this, super.onSaveInstanceState())
26+
}
27+
28+
override fun onRestoreInstanceState(state: Parcelable) {
29+
super.onRestoreInstanceState(Icepick.restoreInstanceState(this, state))
30+
if (backgroundColor != null) {
31+
setBackgroundColorWithAnotherMethod(backgroundColor!!)
32+
}
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:layout_width="match_parent"
3+
android:layout_height="match_parent"
4+
android:orientation="vertical">
5+
6+
<com.github.frankiesardo.icepick.CustomView
7+
android:layout_width="match_parent"
8+
android:layout_height="wrap_content"
9+
android:gravity="center_vertical"
10+
android:id="@+id/custom_view"/>
11+
12+
</LinearLayout>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<menu xmlns:android="http://schemas.android.com/apk/res/android">
2+
<item
3+
android:id="@+id/action_add_state"
4+
android:title="@string/action_add_state"
5+
android:orderInCategory="100"
6+
android:showAsAction="never" />
7+
</menu>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="app_name">Icepick</string>
4+
<string name="action_add_state">Add some state</string>
5+
</resources>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
buildscript {
2+
ext.kotlin_version = '0.1-SNAPSHOT' //'1.0.3'
3+
repositories {
4+
mavenCentral()
5+
mavenLocal()
6+
jcenter()
7+
}
8+
dependencies {
9+
classpath "com.android.tools.build:gradle:$androidToolsVersion"
10+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11+
classpath "com.jakewharton.sdkmanager:gradle-plugin:0.12.+"
12+
}
13+
}
14+
15+
task wrapper(type: Wrapper) {
16+
gradleVersion = '2.12'
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.gradle.jvmargs=-ea -XX:MaxPermSize=512m
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include 'app'

0 commit comments

Comments
 (0)