Revert "Optimization for storing enums in databases."

This reverts commit ae093dec7bfdc578cf0d7cd2ee6c8563ddd4f5ed.

Reason for revert: Causes undesired type converters to be used in query parameters. b/173130710

Bug: 173130710
Change-Id: I7ad29cb08bcd15c1b67b09bbba6fd746888c8b99
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
index db41d40..8ba6067 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XType.kt
@@ -134,11 +134,6 @@
     fun isType(): Boolean
 
     /**
-     * Returns true if this represented by an [Enum].
-     */
-    fun isEnum(): Boolean
-
-    /**
      * Returns `true` if this is the same raw type as [other]
      */
     fun isTypeOf(other: KClass<*>): Boolean
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
index dc9a6be..de5dc66 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacType.kt
@@ -25,7 +25,6 @@
 import androidx.room.compiler.processing.safeTypeName
 import com.google.auto.common.MoreTypes
 import com.squareup.javapoet.TypeName
-import javax.lang.model.element.ElementKind
 import javax.lang.model.type.TypeKind
 import javax.lang.model.type.TypeMirror
 import kotlin.reflect.KClass
@@ -139,7 +138,4 @@
         private val BOXED_LONG = TypeName.LONG.box()
         private val BOXED_BYTE = TypeName.BYTE.box()
     }
-
-    override fun isEnum() = typeMirror.kind == TypeKind.DECLARED &&
-        MoreTypes.asElement(typeMirror).kind == ElementKind.ENUM
 }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
index 5329363..aad772f 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspType.kt
@@ -20,7 +20,6 @@
 import androidx.room.compiler.processing.XNullability
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
-import com.google.devtools.ksp.symbol.ClassKind
 import androidx.room.compiler.processing.tryBox
 import androidx.room.compiler.processing.tryUnbox
 import com.google.devtools.ksp.symbol.KSClassDeclaration
@@ -152,8 +151,4 @@
     override fun toString(): String {
         return ksType.toString()
     }
-
-    override fun isEnum(): Boolean {
-        return (ksType.declaration as? KSClassDeclaration)?.classKind == ClassKind.ENUM_CLASS
-    }
 }
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
index 19ac355..36a3e12 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeArgumentType.kt
@@ -17,9 +17,9 @@
 package androidx.room.compiler.processing.ksp
 
 import androidx.room.compiler.processing.XType
+import com.squareup.javapoet.TypeName
 import com.google.devtools.ksp.symbol.KSTypeArgument
 import com.google.devtools.ksp.symbol.KSTypeParameter
-import com.squareup.javapoet.TypeName
 
 /**
  * The typeName for type arguments requires the type parameter, hence we have a special type
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index f4cf3a5..d79a71c 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -16,16 +16,16 @@
 
 package androidx.room.solver
 
+import androidx.room.ext.CommonTypeNames
+import androidx.room.ext.GuavaBaseTypeNames
+import androidx.room.ext.isEntityElement
+import androidx.room.parser.ParsedQuery
+import androidx.room.parser.SQLTypeAffinity
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.asDeclaredType
 import androidx.room.compiler.processing.isArray
 import androidx.room.compiler.processing.isDeclared
-import androidx.room.ext.CommonTypeNames
-import androidx.room.ext.GuavaBaseTypeNames
-import androidx.room.ext.isEntityElement
 import androidx.room.ext.isNotByte
-import androidx.room.parser.ParsedQuery
-import androidx.room.parser.SQLTypeAffinity
 import androidx.room.processor.Context
 import androidx.room.processor.EntityProcessor
 import androidx.room.processor.FieldProcessor
@@ -86,7 +86,6 @@
 import androidx.room.solver.types.CompositeAdapter
 import androidx.room.solver.types.CompositeTypeConverter
 import androidx.room.solver.types.CursorValueReader
-import androidx.room.solver.types.EnumColumnTypeAdapter
 import androidx.room.solver.types.NoOpConverter
 import androidx.room.solver.types.PrimitiveBooleanToIntConverter
 import androidx.room.solver.types.PrimitiveColumnTypeAdapter
@@ -219,26 +218,13 @@
         if (adapter != null) {
             return adapter
         }
-
-        fun findTypeConverterAdapter(): ColumnTypeAdapter? {
-            val targetTypes = targetTypeMirrorsFor(affinity)
-            val binder = findTypeConverter(input, targetTypes) ?: return null
-            // columnAdapter should not be null but we are receiving errors on crash in `first()` so
-            // this safeguard allows us to dispatch the real problem to the user (e.g. why we couldn't
-            // find the right adapter)
-            val columnAdapter = getAllColumnAdapters(binder.to).firstOrNull() ?: return null
-            return CompositeAdapter(input, columnAdapter, binder, null)
-        }
-
-        val adapterByTypeConverter = findTypeConverterAdapter()
-        if (adapterByTypeConverter != null) {
-            return adapterByTypeConverter
-        }
-        val enumAdapter = createEnumTypeAdapter(input)
-        if (enumAdapter != null) {
-            return enumAdapter
-        }
-        return null
+        val targetTypes = targetTypeMirrorsFor(affinity)
+        val binder = findTypeConverter(input, targetTypes) ?: return null
+        // columnAdapter should not be null but we are receiving errors on crash in `first()` so
+        // this safeguard allows us to dispatch the real problem to the user (e.g. why we couldn't
+        // find the right adapter)
+        val columnAdapter = getAllColumnAdapters(binder.to).firstOrNull() ?: return null
+        return CompositeAdapter(input, columnAdapter, binder, null)
     }
 
     /**
@@ -265,28 +251,13 @@
             // two way is better
             return adapter
         }
-
-        fun findTypeConverterAdapter(): ColumnTypeAdapter? {
-            val targetTypes = targetTypeMirrorsFor(affinity)
-            val converter = findTypeConverter(targetTypes, output) ?: return null
-            return CompositeAdapter(
-                output,
-                getAllColumnAdapters(converter.from).first(), null, converter
-            )
-        }
-
         // we could not find a two way version, search for anything
-        val typeConverterAdapter = findTypeConverterAdapter()
-        if (typeConverterAdapter != null) {
-            return typeConverterAdapter
-        }
-
-        val enumAdapter = createEnumTypeAdapter(output)
-        if (enumAdapter != null) {
-            return enumAdapter
-        }
-
-        return null
+        val targetTypes = targetTypeMirrorsFor(affinity)
+        val converter = findTypeConverter(targetTypes, output) ?: return null
+        return CompositeAdapter(
+            output,
+            getAllColumnAdapters(converter.from).first(), null, converter
+        )
     }
 
     /**
@@ -322,34 +293,15 @@
         if (adapter != null) {
             return adapter
         }
-
-        fun findTypeConverterAdapter(): ColumnTypeAdapter? {
-            val targetTypes = targetTypeMirrorsFor(affinity)
-            val intoStatement = findTypeConverter(out, targetTypes) ?: return null
-            // ok found a converter, try the reverse now
-            val fromCursor = reverse(intoStatement) ?: findTypeConverter(intoStatement.to, out)
-                ?: return null
-            return CompositeAdapter(
-                out, getAllColumnAdapters(intoStatement.to).first(), intoStatement, fromCursor
-            )
-        }
-
-        val adapterByTypeConverter = findTypeConverterAdapter()
-        if (adapterByTypeConverter != null) {
-            return adapterByTypeConverter
-        }
-        val enumAdapter = createEnumTypeAdapter(out)
-        if (enumAdapter != null) {
-            return enumAdapter
-        }
-        return null
-    }
-
-    private fun createEnumTypeAdapter(type: XType): ColumnTypeAdapter? {
-        if (type.isEnum()) {
-            return EnumColumnTypeAdapter(type)
-        }
-        return null
+        val targetTypes = targetTypeMirrorsFor(affinity)
+        val intoStatement = findTypeConverter(out, targetTypes) ?: return null
+        // ok found a converter, try the reverse now
+        val fromCursor = reverse(intoStatement) ?: findTypeConverter(intoStatement.to, out)
+            ?: return null
+        return CompositeAdapter(
+            out, getAllColumnAdapters(intoStatement.to).first(), intoStatement,
+            fromCursor
+        )
     }
 
     private fun findDirectAdapterFor(
@@ -561,17 +513,17 @@
         if (typeMirror.isType() &&
             context.COMMON_TYPES.COLLECTION.rawType.isAssignableFrom(typeMirror)
         ) {
-            val collectionBinder = findStatementValueBinder(typeMirror, null)
-            if (collectionBinder != null) {
-                // user has a converter for the collection itself
-                return BasicQueryParameterAdapter(collectionBinder)
-            }
-
             val declared = typeMirror.asDeclaredType()
             val binder = findStatementValueBinder(
                 declared.typeArguments.first().extendsBoundOrSelf(), null
-            ) ?: return null
-            return CollectionQueryParameterAdapter(binder)
+            )
+            if (binder != null) {
+                return CollectionQueryParameterAdapter(binder)
+            } else {
+                // maybe user wants to convert this collection themselves. look for a match
+                val collectionBinder = findStatementValueBinder(typeMirror, null) ?: return null
+                return BasicQueryParameterAdapter(collectionBinder)
+            }
         } else if (typeMirror.isArray() && typeMirror.componentType.isNotByte()) {
             val component = typeMirror.componentType
             val binder = findStatementValueBinder(component, null) ?: return null
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/types/EnumColumnTypeAdapter.kt b/room/compiler/src/main/kotlin/androidx/room/solver/types/EnumColumnTypeAdapter.kt
deleted file mode 100644
index 1194b1d..0000000
--- a/room/compiler/src/main/kotlin/androidx/room/solver/types/EnumColumnTypeAdapter.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * 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 androidx.room.solver.types
-
-import androidx.room.compiler.processing.XType
-import androidx.room.ext.L
-import androidx.room.ext.T
-import androidx.room.parser.SQLTypeAffinity.TEXT
-import androidx.room.solver.CodeGenScope
-
-/**
- * Uses enum string representation.
- */
-class EnumColumnTypeAdapter(out: XType) :
-    ColumnTypeAdapter(out, TEXT) {
-    private val enumTypeName = out.typeName
-    override fun readFromCursor(
-        outVarName: String,
-        cursorVarName: String,
-        indexVarName: String,
-        scope: CodeGenScope
-    ) {
-        scope.builder()
-            .addStatement(
-                "$L = $T.valueOf($L.getString($L))", outVarName, enumTypeName,
-                cursorVarName,
-                indexVarName
-            )
-    }
-
-    override fun bindToStmt(
-        stmtName: String,
-        indexVarName: String,
-        valueVarName: String,
-        scope: CodeGenScope
-    ) {
-        scope.builder().apply {
-            beginControlFlow("if ($L == null)", valueVarName)
-                .addStatement("$L.bindNull($L)", stmtName, indexVarName)
-            nextControlFlow("else")
-                .addStatement("$L.bindString($L, $L.name())", stmtName, indexVarName, valueVarName)
-            endControlFlow()
-        }
-    }
-}
\ No newline at end of file
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
index 1f1d6cb..085b391 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
@@ -50,24 +50,6 @@
     }
 
     @Test
-    fun testUnusedEnumCompilesWithoutError() {
-        singleDao(
-            """
-                @Dao abstract class MyDao {
-                    @Query("SELECT uid FROM User")
-                    abstract int[] getIds();
-                    enum Fruit {
-                        APPLE,
-                        BANANA,
-                        STRAWBERRY
-                    }
-                }
-                """
-        ) { _, _ ->
-        }.compilesWithoutError()
-    }
-
-    @Test
     fun testNonAbstract() {
         singleDao("@Dao public class MyDao {}") { _, _ -> }
             .failsToCompile()
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 3d437fc..e520c12 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -20,8 +20,6 @@
 import androidx.paging.DataSource
 import androidx.paging.PagingSource
 import androidx.room.Entity
-import androidx.room.compiler.processing.XProcessingEnv
-import androidx.room.compiler.processing.asDeclaredType
 import androidx.room.ext.GuavaUtilConcurrentTypeNames
 import androidx.room.ext.L
 import androidx.room.ext.LifecyclesTypeNames
@@ -32,6 +30,8 @@
 import androidx.room.ext.RxJava3TypeNames
 import androidx.room.ext.T
 import androidx.room.parser.SQLTypeAffinity
+import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.asDeclaredType
 import androidx.room.processor.Context
 import androidx.room.processor.ProcessorErrors
 import androidx.room.solver.binderprovider.DataSourceFactoryQueryResultBinderProvider
@@ -44,7 +44,6 @@
 import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
 import androidx.room.solver.shortcut.binderprovider.RxCallableInsertMethodBinderProvider
 import androidx.room.solver.types.CompositeAdapter
-import androidx.room.solver.types.EnumColumnTypeAdapter
 import androidx.room.solver.types.TypeConverter
 import androidx.room.testing.TestInvocation
 import androidx.room.testing.TestProcessor
@@ -104,30 +103,6 @@
     }
 
     @Test
-    fun testJavaLangEnumCompilesWithoutError() {
-        simpleRun(
-            JavaFileObjects.forSourceString(
-                "foo.bar.Fruit",
-                """ package foo.bar;
-                import androidx.room.*;
-                enum Fruit {
-                    APPLE,
-                    BANANA,
-                    STRAWBERRY}
-                """.trimMargin()
-            )
-        ) { invocation ->
-            val store = TypeAdapterStore.create(Context(invocation.processingEnv))
-            val enum = invocation
-                .processingEnv
-                .requireType("foo.bar.Fruit")
-            val adapter = store.findColumnTypeAdapter(enum, null)
-            assertThat(adapter, notNullValue())
-            assertThat(adapter, instanceOf(EnumColumnTypeAdapter::class.java))
-        }.compilesWithoutError()
-    }
-
-    @Test
     fun testVia1TypeAdapter() {
         singleRun { invocation ->
             val store = TypeAdapterStore.create(Context(invocation.processingEnv))
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/EnumColumnTypeAdapterTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/EnumColumnTypeAdapterTest.java
deleted file mode 100644
index 4c0df94..0000000
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/EnumColumnTypeAdapterTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * 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 androidx.room.integration.testapp.test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
-import android.content.Context;
-
-import androidx.room.Dao;
-import androidx.room.Database;
-import androidx.room.Entity;
-import androidx.room.PrimaryKey;
-import androidx.room.Query;
-import androidx.room.Room;
-import androidx.room.RoomDatabase;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class EnumColumnTypeAdapterTest {
-
-    private EnumColumnTypeAdapterDatabase mDb;
-
-    @Entity
-    public static class EntityWithEnum {
-        @PrimaryKey
-        public Long id;
-        public Fruit fruit;
-    }
-
-    public enum Fruit {
-        BANANA,
-        STRAWBERRY,
-        WILDBERRY
-    }
-
-    @Dao
-    public interface SampleDao {
-        @Query("INSERT INTO EntityWithEnum (id, fruit) VALUES (:id, :fruit)")
-        long insert(long id, Fruit fruit);
-
-        @Query("SELECT * FROM EntityWithEnum WHERE id = :id")
-        EntityWithEnum getValueWithId(long id);
-    }
-
-    @Database(entities = {EntityWithEnum.class}, version = 1, exportSchema = false)
-    public abstract static class EnumColumnTypeAdapterDatabase extends RoomDatabase {
-        public abstract EnumColumnTypeAdapterTest.SampleDao dao();
-    }
-
-    @Before
-    public void initDb() {
-        Context context = ApplicationProvider.getApplicationContext();
-        mDb = Room.inMemoryDatabaseBuilder(
-                context,
-                EnumColumnTypeAdapterDatabase.class)
-                .build();
-    }
-
-    @Test
-    public void readAndWriteEnumToDatabase() {
-        final long id1 = mDb.dao().insert(1, Fruit.BANANA);
-        final long id2 = mDb.dao().insert(2, Fruit.STRAWBERRY);
-
-        assertThat(mDb.dao().getValueWithId(1).fruit, is(equalTo(Fruit.BANANA)));
-        assertThat(mDb.dao().getValueWithId(2).fruit, is(equalTo(Fruit.STRAWBERRY)));
-    }
-}