Merge "Add a new API to configure XProcessingEnv behavior" into androidx-main
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
index 43f7efa..50847b3 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticJavacProcessor.kt
@@ -23,9 +23,17 @@
 @Suppress("VisibleForTests")
 @ExperimentalProcessingApi
 class SyntheticJavacProcessor private constructor(
-    private val impl: SyntheticProcessorImpl
-) : JavacBasicAnnotationProcessor(), SyntheticProcessor by impl {
-    constructor(handlers: List<(XTestInvocation) -> Unit>) : this(SyntheticProcessorImpl(handlers))
+    config: XProcessingEnvConfig,
+    private val impl: SyntheticProcessorImpl,
+) : JavacBasicAnnotationProcessor(
+    configureEnv = {
+        config
+    }
+), SyntheticProcessor by impl {
+    constructor(
+        config: XProcessingEnvConfig,
+        handlers: List<(XTestInvocation) -> Unit>,
+    ) : this(config, SyntheticProcessorImpl(handlers))
 
     override fun processingSteps(): Iterable<XProcessingStep> = impl.processingSteps()
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
index e9c0231..6ae8034 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/SyntheticKspProcessor.kt
@@ -22,13 +22,17 @@
 @ExperimentalProcessingApi
 class SyntheticKspProcessor private constructor(
     symbolProcessorEnvironment: SymbolProcessorEnvironment,
-    private val impl: SyntheticProcessorImpl
-) : KspBasicAnnotationProcessor(symbolProcessorEnvironment), SyntheticProcessor by impl {
+    config: XProcessingEnvConfig,
+    private val impl: SyntheticProcessorImpl,
+) : KspBasicAnnotationProcessor(symbolProcessorEnvironment, config),
+    SyntheticProcessor by impl {
     constructor(
         symbolProcessorEnvironment: SymbolProcessorEnvironment,
-        handlers: List<(XTestInvocation) -> Unit>
+        config: XProcessingEnvConfig,
+        handlers: List<(XTestInvocation) -> Unit>,
     ) : this(
         symbolProcessorEnvironment,
+        config,
         SyntheticProcessorImpl(handlers)
     )
 
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/XProcessingEnvironmentTestConfigProvider.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/XProcessingEnvironmentTestConfigProvider.kt
new file mode 100644
index 0000000..fa0b02c
--- /dev/null
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/XProcessingEnvironmentTestConfigProvider.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 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.compiler.processing
+
+import java.util.ServiceLoader
+
+/**
+ * This interface can be implemented by XProcessingTesting clients to provide a default
+ * configuration for all runProcessingTest calls.
+ *
+ * XProcessingTesting will find the implementation via a [ServiceLoader]. To register your
+ * implementation, add the following file
+ * `androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider` into
+ * `resources/META-INF/services/` folder (test source path). The contents of the file should have
+ * the fully qualified name of your implementation class.
+ */
+interface XProcessingEnvironmentTestConfigProvider {
+    fun configure(options: Map<String, String>): XProcessingEnvConfig
+
+    companion object {
+        private val instance: XProcessingEnvironmentTestConfigProvider? by lazy {
+            val implementations = ServiceLoader.load(
+                XProcessingEnvironmentTestConfigProvider::class.java
+            ).toList()
+            if (implementations.size >= 2) {
+                error(
+                    "Multiple XProcessingEnvironmentTestConfigProvider implementations " +
+                        "were found: $implementations. There can be only 1 or 0."
+                )
+            }
+            implementations.firstOrNull()
+        }
+
+        internal fun createConfig(options: Map<String, String>): XProcessingEnvConfig {
+            return instance?.configure(options) ?: XProcessingEnvConfig.DEFAULT
+        }
+    }
+}
\ No newline at end of file
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
index d89909f..d3e3a9f6 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/ProcessorTestExt.kt
@@ -17,8 +17,10 @@
 package androidx.room.compiler.processing.util
 
 import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import androidx.room.compiler.processing.XProcessingStep
 import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider
 import androidx.room.compiler.processing.util.compiler.TestCompilationArguments
 import androidx.room.compiler.processing.util.compiler.compile
 import androidx.room.compiler.processing.util.runner.CompilationTestRunner
@@ -35,6 +37,10 @@
 import java.util.jar.JarOutputStream
 import javax.annotation.processing.Processor
 
+private fun defaultTestConfig(
+    options: Map<String, String>
+) = XProcessingEnvironmentTestConfigProvider.createConfig(options)
+
 @ExperimentalProcessingApi
 private fun runTests(
     params: TestCompilationParameters,
@@ -86,6 +92,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handler: (XTestInvocation) -> Unit
 ) {
     runTests(
@@ -95,6 +102,7 @@
             options = options,
             javacArguments = javacArguments,
             kotlincArguments = kotlincArguments,
+            config = config,
             handlers = listOf(handler),
         ),
         JavacCompilationTestRunner,
@@ -124,6 +132,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handler: (XTestInvocation) -> Unit
 ) = runProcessorTest(
     sources = sources,
@@ -131,6 +140,7 @@
     options = options,
     javacArguments = javacArguments,
     kotlincArguments = kotlincArguments,
+    config = config,
     handlers = listOf(handler)
 )
 
@@ -154,6 +164,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     createProcessingStep: () -> XProcessingStep,
     onCompilationResult: (CompilationResultSubject) -> Unit
 ) {
@@ -163,6 +174,7 @@
         options = options,
         javacArguments = javacArguments,
         kotlincArguments = kotlincArguments,
+        config = config,
     ) { invocation ->
         val step = createProcessingStep()
         val elements =
@@ -190,6 +202,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handlers: List<(XTestInvocation) -> Unit>
 ) {
     val javaApRunner = if (sources.any { it is Source.KotlinSource }) {
@@ -204,7 +217,8 @@
             options = options,
             handlers = handlers,
             javacArguments = javacArguments,
-            kotlincArguments = kotlincArguments
+            kotlincArguments = kotlincArguments,
+            config = config
         ),
         javaApRunner,
         KspCompilationTestRunner
@@ -221,11 +235,13 @@
     sources: List<Source>,
     classpath: List<File> = emptyList(),
     options: Map<String, String> = emptyMap(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handler: (XTestInvocation) -> Unit
 ) = runJavaProcessorTest(
     sources = sources,
     classpath = classpath,
     options = options,
+    config = config,
     handlers = listOf(handler)
 )
 
@@ -237,6 +253,7 @@
     sources: List<Source>,
     classpath: List<File> = emptyList(),
     options: Map<String, String> = emptyMap(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handlers: List<(XTestInvocation) -> Unit>
 ) {
     runTests(
@@ -244,7 +261,8 @@
             sources = sources,
             classpath = classpath,
             options = options,
-            handlers = handlers
+            handlers = handlers,
+            config = config,
         ),
         JavacCompilationTestRunner
     )
@@ -260,6 +278,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handler: (XTestInvocation) -> Unit
 ) = runKaptTest(
     sources = sources,
@@ -267,6 +286,7 @@
     options = options,
     javacArguments = javacArguments,
     kotlincArguments = kotlincArguments,
+    config = config,
     handlers = listOf(handler)
 )
 
@@ -280,6 +300,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handlers: List<(XTestInvocation) -> Unit>
 ) {
     runTests(
@@ -289,7 +310,8 @@
             options = options,
             handlers = handlers,
             javacArguments = javacArguments,
-            kotlincArguments = kotlincArguments
+            kotlincArguments = kotlincArguments,
+            config = config,
         ),
         KaptCompilationTestRunner
     )
@@ -305,6 +327,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handler: (XTestInvocation) -> Unit
 ) = runKspTest(
     sources = sources,
@@ -312,6 +335,7 @@
     options = options,
     javacArguments = javacArguments,
     kotlincArguments = kotlincArguments,
+    config = config,
     handlers = listOf(handler)
 )
 
@@ -325,6 +349,7 @@
     options: Map<String, String> = emptyMap(),
     javacArguments: List<String> = emptyList(),
     kotlincArguments: List<String> = emptyList(),
+    config: XProcessingEnvConfig = defaultTestConfig(options),
     handlers: List<(XTestInvocation) -> Unit>
 ) {
     runTests(
@@ -335,6 +360,7 @@
             handlers = handlers,
             javacArguments = javacArguments,
             kotlincArguments = kotlincArguments,
+            config = config,
         ),
         KspCompilationTestRunner
     )
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt
index bc28069..c74bfe0 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/CompilationTestRunner.kt
@@ -17,6 +17,7 @@
 package androidx.room.compiler.processing.util.runner
 
 import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import androidx.room.compiler.processing.util.CompilationResult
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.XTestInvocation
@@ -42,5 +43,6 @@
     val options: Map<String, String> = emptyMap(),
     val javacArguments: List<String> = emptyList(),
     val kotlincArguments: List<String> = emptyList(),
-    val handlers: List<(XTestInvocation) -> Unit>
+    val config: XProcessingEnvConfig,
+    val handlers: List<(XTestInvocation) -> Unit>,
 )
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
index ab189c9..e2e5d9f 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/JavacCompilationTestRunner.kt
@@ -37,7 +37,7 @@
     }
 
     override fun compile(workingDir: File, params: TestCompilationParameters): CompilationResult {
-        val syntheticJavacProcessor = SyntheticJavacProcessor(params.handlers)
+        val syntheticJavacProcessor = SyntheticJavacProcessor(params.config, params.handlers)
         val sources = if (params.sources.isEmpty()) {
             // synthesize a source to trigger compilation
             listOf(
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
index 0911ae2..2d1f348 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KaptCompilationTestRunner.kt
@@ -34,7 +34,7 @@
     }
 
     override fun compile(workingDir: File, params: TestCompilationParameters): CompilationResult {
-        val syntheticJavacProcessor = SyntheticJavacProcessor(params.handlers)
+        val syntheticJavacProcessor = SyntheticJavacProcessor(params.config, params.handlers)
         val args = TestCompilationArguments(
             sources = params.sources,
             classpath = params.classpath,
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
index e53cc99..97e9f14 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/runner/KspCompilationTestRunner.kt
@@ -41,7 +41,11 @@
             lateinit var processor: SyntheticKspProcessor
 
             override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
-                return SyntheticKspProcessor(environment, params.handlers).also { processor = it }
+                return SyntheticKspProcessor(
+                    symbolProcessorEnvironment = environment,
+                    handlers = params.handlers,
+                    config = params.config
+                ).also { processor = it }
             }
         }
         val args = TestCompilationArguments(
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/LoadFromDefaultEnvironmentConfigurationProviderTest.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/LoadFromDefaultEnvironmentConfigurationProviderTest.kt
new file mode 100644
index 0000000..9819a5d
--- /dev/null
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/LoadFromDefaultEnvironmentConfigurationProviderTest.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2022 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.compiler.processing.util
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class LoadFromDefaultEnvironmentConfigurationProviderTest {
+    @Test
+    fun test() {
+        runProcessorTest {
+        }
+        assertThat(TestDefaultEnvironmentConfigProvider.initialized)
+            .isTrue()
+        assertThat(TestDefaultEnvironmentConfigProvider.invoked)
+            .isTrue()
+    }
+}
\ No newline at end of file
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestDefaultEnvironmentConfigProvider.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestDefaultEnvironmentConfigProvider.kt
new file mode 100644
index 0000000..fb42b59
--- /dev/null
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestDefaultEnvironmentConfigProvider.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 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.compiler.processing.util
+
+import androidx.room.compiler.processing.XProcessingEnvConfig
+import androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider
+
+class TestDefaultEnvironmentConfigProvider : XProcessingEnvironmentTestConfigProvider {
+    init {
+        initialized = true
+    }
+
+    override fun configure(options: Map<String, String>): XProcessingEnvConfig {
+        invoked = true
+        return XProcessingEnvConfig.DEFAULT
+    }
+
+    companion object {
+        /**
+         * Used in test to assert it is used
+         */
+        internal var initialized: Boolean = false
+            private set
+        internal var invoked: Boolean = false
+            private set
+    }
+}
\ No newline at end of file
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt
index 6b4cc58..8645aa3f 100644
--- a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestRunnerTest.kt
@@ -19,6 +19,7 @@
 import androidx.room.compiler.processing.ExperimentalProcessingApi
 import androidx.room.compiler.processing.SyntheticJavacProcessor
 import androidx.room.compiler.processing.SyntheticKspProcessor
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import androidx.room.compiler.processing.util.compiler.TestCompilationArguments
 import androidx.room.compiler.processing.util.compiler.compile
 import com.google.common.truth.Truth.assertThat
@@ -59,6 +60,7 @@
             override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
                 return SyntheticKspProcessor(
                     environment,
+                    XProcessingEnvConfig.DEFAULT,
                     listOf { invocation ->
                         if (
                             invocation.processingEnv.findTypeElement("gen.GeneratedKotlin")
@@ -79,6 +81,7 @@
         }
 
         val javaProcessor = SyntheticJavacProcessor(
+            XProcessingEnvConfig.DEFAULT,
             listOf { invocation ->
                 if (
                     invocation.processingEnv.findTypeElement("gen.GeneratedJava")
diff --git a/room/room-compiler-processing-testing/src/test/resources/META-INF/services/androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider b/room/room-compiler-processing-testing/src/test/resources/META-INF/services/androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider
new file mode 100644
index 0000000..39be844
--- /dev/null
+++ b/room/room-compiler-processing-testing/src/test/resources/META-INF/services/androidx.room.compiler.processing.XProcessingEnvironmentTestConfigProvider
@@ -0,0 +1,16 @@
+#
+# Copyright 2022 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.
+#
+androidx.room.compiler.processing.util.TestDefaultEnvironmentConfigProvider
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
index 93c740f..a3259ea 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnv.kt
@@ -33,6 +33,7 @@
 interface XProcessingEnv {
 
     val backend: Backend
+
     /**
      * The logger interface to log messages
      */
@@ -49,6 +50,11 @@
     val filer: XFiler
 
     /**
+     * Configuration to control certain behaviors of XProcessingEnv.
+     */
+    val config: XProcessingEnvConfig
+
+    /**
      * Looks for the [XTypeElement] with the given qualified name and returns `null` if it does not
      * exist.
      */
@@ -133,21 +139,28 @@
          * Creates a new [XProcessingEnv] implementation derived from the given Java [env].
          */
         @JvmStatic
-        fun create(env: ProcessingEnvironment): XProcessingEnv = JavacProcessingEnv(env)
+        @JvmOverloads
+        fun create(
+            env: ProcessingEnvironment,
+            config: XProcessingEnvConfig = XProcessingEnvConfig.DEFAULT
+        ): XProcessingEnv = JavacProcessingEnv(env, config)
 
         /**
          * Creates a new [XProcessingEnv] implementation derived from the given KSP environment.
          */
         @JvmStatic
+        @JvmOverloads
         fun create(
             options: Map<String, String>,
             resolver: Resolver,
             codeGenerator: CodeGenerator,
-            logger: KSPLogger
+            logger: KSPLogger,
+            config: XProcessingEnvConfig = XProcessingEnvConfig.DEFAULT
         ): XProcessingEnv = KspProcessingEnv(
             options = options,
             codeGenerator = codeGenerator,
             logger = logger,
+            config = config
         ).also { it.resolver = resolver }
     }
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnvConfig.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnvConfig.kt
new file mode 100644
index 0000000..52a6070
--- /dev/null
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XProcessingEnvConfig.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 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.compiler.processing
+
+/**
+ * Configuration class for XProcessingEnv where certain behaviors might be modified.
+ *
+ * See documentation for details.
+ *
+ * To create an instance from Java, use the provided [Builder] class.
+ * To create an instance from Kotlin, you can either use the provided [Builder] or just [copy] an
+ * existing configuration.
+ *
+ * If you are using XProcessing Testing library, you can set an implementation of
+ * `XProcessingEnvironmentTestConfigProvider` via a service configuration to load your
+ * default configuration in `runProcessorTest` calls.
+ */
+@Suppress("SyntheticAccessor", "DataClassPrivateConstructor")
+data class XProcessingEnvConfig private constructor(
+    /**
+     * TODO: not implemented yet.
+     */
+    val excludeMethodsWithInvalidJvmSourceNames: Boolean = false
+) {
+    fun toBuilder() = Builder(this)
+
+    class Builder(
+        baseline: XProcessingEnvConfig = XProcessingEnvConfig()
+    ) {
+        private var instance = baseline
+
+        fun excludeMethodsWithInvalidJvmSourceNames(value: Boolean) = apply {
+            instance = instance.copy(
+                excludeMethodsWithInvalidJvmSourceNames = value
+            )
+        }
+
+        fun build(): XProcessingEnvConfig {
+            return instance
+        }
+    }
+
+    companion object {
+        /**
+         * Default configuration for XProcessingEnv
+         */
+        val DEFAULT = Builder().build()
+    }
+}
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacBasicAnnotationProcessor.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacBasicAnnotationProcessor.kt
index 5e731de..a5dcac2 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacBasicAnnotationProcessor.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacBasicAnnotationProcessor.kt
@@ -19,6 +19,7 @@
 import androidx.room.compiler.processing.CommonProcessorDelegate
 import androidx.room.compiler.processing.XBasicAnnotationProcessor
 import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import javax.annotation.processing.AbstractProcessor
 import javax.annotation.processing.ProcessingEnvironment
 import javax.annotation.processing.RoundEnvironment
@@ -28,17 +29,22 @@
  * Javac implementation of a [XBasicAnnotationProcessor] with built-in support for validating and
  * deferring elements.
  */
-abstract class JavacBasicAnnotationProcessor :
-    AbstractProcessor(), XBasicAnnotationProcessor {
+abstract class JavacBasicAnnotationProcessor @JvmOverloads constructor(
+    configureEnv: (Map<String, String>) -> XProcessingEnvConfig = { XProcessingEnvConfig.DEFAULT }
+) : AbstractProcessor(), XBasicAnnotationProcessor {
+    constructor(config: XProcessingEnvConfig) : this({ config })
 
-    private val xEnv: JavacProcessingEnv by lazy { JavacProcessingEnv(processingEnv) }
+    private val xEnv: JavacProcessingEnv by lazy {
+        JavacProcessingEnv(processingEnv, configureEnv(processingEnv.options))
+    }
 
     // Cache and lazily get steps during the initial process() so steps initialization is done once.
     private val steps by lazy { processingSteps().toList() }
 
     private val commonDelegate by lazy { CommonProcessorDelegate(this.javaClass, xEnv, steps) }
 
-    final override val xProcessingEnv: XProcessingEnv get() = xEnv
+    final override val xProcessingEnv: XProcessingEnv
+        get() = xEnv
 
     final override fun init(processingEnv: ProcessingEnvironment?) {
         super.init(processingEnv)
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
index d7c0f7f..9b96022 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacProcessingEnv.kt
@@ -20,6 +20,7 @@
 import androidx.room.compiler.processing.XMessager
 import androidx.room.compiler.processing.XNullability
 import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.javac.kotlin.KmType
@@ -39,7 +40,8 @@
 import javax.lang.model.util.Types
 
 internal class JavacProcessingEnv(
-    val delegate: ProcessingEnvironment
+    val delegate: ProcessingEnvironment,
+    override val config: XProcessingEnvConfig,
 ) : XProcessingEnv {
     override val backend: XProcessingEnv.Backend = XProcessingEnv.Backend.JAVAC
 
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
index c6c0658..0c0cc26 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
@@ -19,6 +19,7 @@
 import androidx.room.compiler.processing.CommonProcessorDelegate
 import androidx.room.compiler.processing.XBasicAnnotationProcessor
 import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import com.google.devtools.ksp.processing.KSPLogger
 import com.google.devtools.ksp.processing.Resolver
 import com.google.devtools.ksp.processing.SymbolProcessor
@@ -30,16 +31,17 @@
  * KSP implementation of a [XBasicAnnotationProcessor] with built-in support for validating and
  * deferring symbols.
  */
-abstract class KspBasicAnnotationProcessor(
-    val symbolProcessorEnvironment: SymbolProcessorEnvironment
+abstract class KspBasicAnnotationProcessor @JvmOverloads constructor(
+    symbolProcessorEnvironment: SymbolProcessorEnvironment,
+    config: XProcessingEnvConfig = XProcessingEnvConfig.DEFAULT,
 ) : SymbolProcessor, XBasicAnnotationProcessor {
-
     private val logger = DelegateLogger(symbolProcessorEnvironment.logger)
 
     private val xEnv = KspProcessingEnv(
-        symbolProcessorEnvironment.options,
-        symbolProcessorEnvironment.codeGenerator,
-        logger
+        options = symbolProcessorEnvironment.options,
+        codeGenerator = symbolProcessorEnvironment.codeGenerator,
+        logger = logger,
+        config = config
     )
 
     // Cache and lazily get steps during the initial process() so steps initialization is done once.
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
index 06affe1..1bb4a53 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspProcessingEnv.kt
@@ -19,6 +19,7 @@
 import androidx.room.compiler.processing.XFiler
 import androidx.room.compiler.processing.XMessager
 import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.XProcessingEnvConfig
 import androidx.room.compiler.processing.XType
 import androidx.room.compiler.processing.XTypeElement
 import androidx.room.compiler.processing.javac.XTypeElementStore
@@ -41,6 +42,7 @@
     override val options: Map<String, String>,
     codeGenerator: CodeGenerator,
     logger: KSPLogger,
+    override val config: XProcessingEnvConfig,
 ) : XProcessingEnv {
     override val backend: XProcessingEnv.Backend = XProcessingEnv.Backend.KSP
     private val ksFileMemberContainers = mutableMapOf<KSFile, KspFileMemberContainer>()
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvConfigTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvConfigTest.kt
new file mode 100644
index 0000000..f1ed6e6
--- /dev/null
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingEnvConfigTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 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.compiler.processing
+
+import androidx.room.compiler.processing.util.runProcessorTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class XProcessingEnvConfigTest {
+    @Test
+    fun testConfig() {
+        val myConfig = XProcessingEnvConfig.Builder().build()
+        runProcessorTest(
+            config = myConfig
+        ) {
+            assertThat(
+                it.processingEnv.config
+            ).isSameInstanceAs(myConfig)
+        }
+    }
+
+    @Test
+    fun callItLikeJava() {
+        val myConfig = XProcessingEnvConfig.Builder().excludeMethodsWithInvalidJvmSourceNames(
+            true
+        ).build()
+        runProcessorTest(
+            config = myConfig
+        ) {
+            assertThat(
+                it.processingEnv.config.excludeMethodsWithInvalidJvmSourceNames
+            ).isTrue()
+        }
+    }
+
+    @Test
+    fun callItLikeKotlin() {
+        val myConfig = XProcessingEnvConfig.DEFAULT.copy(
+            excludeMethodsWithInvalidJvmSourceNames = true
+        )
+        runProcessorTest(
+            config = myConfig
+        ) {
+            assertThat(
+                it.processingEnv.config.excludeMethodsWithInvalidJvmSourceNames
+            ).isTrue()
+        }
+    }
+}
\ No newline at end of file