Skip to content

Commit 9be4b0a

Browse files
committed
Fix infinite recursive loop in Kotlin generics
Fixes #9
1 parent a98ac3a commit 9be4b0a

File tree

2 files changed

+56
-10
lines changed

2 files changed

+56
-10
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
@file:Suppress("unused")
2+
3+
package com.evernote.android.state.test
4+
5+
import com.evernote.android.state.State
6+
import java.io.Serializable
7+
import java.util.*
8+
9+
/**
10+
* Copyright 2017 Evernote Corporation. All rights reserved.
11+
*
12+
* Created by rwondratschek on 3/1/17.
13+
*/
14+
class MyComparator : Comparator<MyComparable>, Serializable {
15+
override fun compare(o1: MyComparable, o2: MyComparable): Int = 0
16+
}
17+
18+
class MyComparable : Comparable<MyComparable>, Serializable {
19+
override fun compareTo(other: MyComparable): Int = 0
20+
}
21+
22+
interface MyInterface<T : MyInterface<T>> {
23+
fun doSomething(other: T)
24+
}
25+
26+
class MyInterfaceImpl : MyInterface<MyInterfaceImpl>, Serializable {
27+
override fun doSomething(other: MyInterfaceImpl) {}
28+
}
29+
30+
interface MySerializableInterface<T : MySerializableInterface<T>> : Serializable {
31+
fun doSomething(other: T)
32+
}
33+
34+
class MySerializableImpl : MySerializableInterface<MySerializableImpl> {
35+
override fun doSomething(other: MySerializableImpl) {}
36+
}
37+
38+
class TestKotlinComparable {
39+
40+
@State
41+
var comparator: MyComparator? = null
42+
43+
@State
44+
var comparable: MyComparable? = null
45+
46+
@State
47+
var myInterface: MyInterfaceImpl? = null
48+
49+
@State
50+
var mySerializableInterface: MySerializableImpl? = null
51+
}

processor/src/main/java/com/evernote/android/state/StateProcessor.java

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
/**
6666
* @author rwondratschek
6767
*/
68-
@SuppressWarnings("unused")
6968
@AutoService(Processor.class)
7069
public class StateProcessor extends AbstractProcessor {
7170

@@ -116,9 +115,6 @@ public int compare(Element o1, Element o2) {
116115
private static final String OBJECT_CLASS_NAME = Object.class.getName();
117116
private static final String PARCELABLE_CLASS_NAME = Parcelable.class.getName();
118117
private static final String SERIALIZABLE_CLASS_NAME = Serializable.class.getName();
119-
private static final String ARRAY_LIST_CLASS_NAME = ArrayList.class.getName();
120-
private static final String SPARSE_ARRAY_CLASS_NAME = SparseArray.class.getName();
121-
private static final String ENUM_CLASS_NAME = Enum.class.getName();
122118

123119
private static final Set<String> IGNORED_TYPE_DECLARATIONS = Collections.unmodifiableSet(new HashSet<String>() {{
124120
add(Bundle.class.getName());
@@ -731,7 +727,7 @@ private TypeMirror getInsertedType(TypeMirror fieldType, boolean checkIgnoredTyp
731727
}
732728

733729
TypeElement classElement = mElementUtils.getTypeElement(fieldType.toString());
734-
if (classElement == null) {
730+
if (classElement == null || OBJECT_CLASS_NAME.equals(classElement.toString())) {
735731
return null;
736732
}
737733

@@ -749,11 +745,10 @@ private TypeMirror getInsertedType(TypeMirror fieldType, boolean checkIgnoredTyp
749745
if (SERIALIZABLE_CLASS_NAME.equals(superTypeString)) {
750746
return fieldType;
751747
}
752-
if (superTypeString.startsWith(ENUM_CLASS_NAME)) {
753-
// Necessary for Kotlin enums, otherwise this ends in an endless loop, e.g. java.lang.Enum<com.world.MyEnum>
754-
return fieldType;
755-
}
756-
TypeMirror result = getInsertedType(superType, checkIgnoredTypes);
748+
}
749+
750+
for (TypeMirror superType : typeMirrors) {
751+
TypeMirror result = getInsertedType(eraseGenericIfNecessary(superType), checkIgnoredTypes);
757752
if (result != null) {
758753
// always return the passed in type and not any super type
759754
return fieldType;

0 commit comments

Comments
 (0)