Home | History | Annotate | Download | only in processor
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.room.processor
     18 
     19 import androidx.room.log.RLog
     20 import androidx.room.preconditions.Checks
     21 import androidx.room.processor.cache.Cache
     22 import androidx.room.solver.TypeAdapterStore
     23 import androidx.room.verifier.DatabaseVerifier
     24 import java.io.File
     25 import java.util.LinkedHashSet
     26 import javax.annotation.processing.ProcessingEnvironment
     27 import javax.lang.model.element.Element
     28 import javax.lang.model.type.TypeMirror
     29 
     30 class Context private constructor(
     31         val processingEnv: ProcessingEnvironment,
     32         val logger: RLog,
     33         private val typeConverters: CustomConverterProcessor.ProcessResult,
     34         private val inheritedAdapterStore: TypeAdapterStore?,
     35         val cache: Cache) {
     36     val checker: Checks = Checks(logger)
     37     val COMMON_TYPES: Context.CommonTypes = Context.CommonTypes(processingEnv)
     38 
     39     val typeAdapterStore by lazy {
     40         if (inheritedAdapterStore != null) {
     41             TypeAdapterStore.copy(this, inheritedAdapterStore)
     42         } else {
     43             TypeAdapterStore.create(this, typeConverters.converters)
     44         }
     45     }
     46 
     47     // set when database and its entities are processed.
     48     var databaseVerifier: DatabaseVerifier? = null
     49 
     50     companion object {
     51         val ARG_OPTIONS by lazy {
     52             ProcessorOptions.values().map { it.argName }
     53         }
     54     }
     55 
     56     constructor(processingEnv: ProcessingEnvironment) : this(
     57             processingEnv = processingEnv,
     58             logger = RLog(RLog.ProcessingEnvMessager(processingEnv), emptySet(), null),
     59             typeConverters = CustomConverterProcessor.ProcessResult.EMPTY,
     60             inheritedAdapterStore = null,
     61             cache = Cache(null, LinkedHashSet(), emptySet()))
     62 
     63     class CommonTypes(val processingEnv: ProcessingEnvironment) {
     64         val STRING: TypeMirror by lazy {
     65             processingEnv.elementUtils.getTypeElement("java.lang.String").asType()
     66         }
     67     }
     68 
     69     val schemaOutFolder by lazy {
     70         val arg = processingEnv.options[ProcessorOptions.OPTION_SCHEMA_FOLDER.argName]
     71         if (arg?.isNotEmpty() ?: false) {
     72             File(arg)
     73         } else {
     74             null
     75         }
     76     }
     77 
     78     fun <T> collectLogs(handler: (Context) -> T): Pair<T, RLog.CollectingMessager> {
     79         val collector = RLog.CollectingMessager()
     80         val subContext = Context(processingEnv = processingEnv,
     81                 logger = RLog(collector, logger.suppressedWarnings, logger.defaultElement),
     82                 typeConverters = this.typeConverters,
     83                 inheritedAdapterStore = typeAdapterStore,
     84                 cache = cache)
     85         subContext.databaseVerifier = databaseVerifier
     86         val result = handler(subContext)
     87         return Pair(result, collector)
     88     }
     89 
     90     fun fork(element: Element): Context {
     91         val suppressedWarnings = SuppressWarningProcessor.getSuppressedWarnings(element)
     92         val processConvertersResult = CustomConverterProcessor.findConverters(this, element)
     93         val canReUseAdapterStore = processConvertersResult.classes.isEmpty()
     94         // order here is important since the sub context should give priority to new converters.
     95         val subTypeConverters = if (canReUseAdapterStore) {
     96             this.typeConverters
     97         } else {
     98             processConvertersResult + this.typeConverters
     99         }
    100         val subSuppressedWarnings = suppressedWarnings + logger.suppressedWarnings
    101         val subCache = Cache(cache, subTypeConverters.classes, subSuppressedWarnings)
    102         val subContext = Context(
    103                 processingEnv = processingEnv,
    104                 logger = RLog(logger.messager, subSuppressedWarnings, element),
    105                 typeConverters = subTypeConverters,
    106                 inheritedAdapterStore = if (canReUseAdapterStore) typeAdapterStore else null,
    107                 cache = subCache)
    108         subContext.databaseVerifier = databaseVerifier
    109         return subContext
    110     }
    111 
    112     enum class ProcessorOptions(val argName: String) {
    113         OPTION_SCHEMA_FOLDER("room.schemaLocation")
    114     }
    115 }
    116