• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Dagger Authors.
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 dagger.hilt.processor.internal.root.ir
18 
19 import kotlin.jvm.Throws
20 
21 // Validates roots being processed.
22 object AggregatedRootIrValidator {
23   @JvmStatic
24   @Throws(InvalidRootsException::class)
rootsToProcessnull25   fun rootsToProcess(
26     isCrossCompilationRootValidationDisabled: Boolean,
27     processedRoots: Set<ProcessedRootSentinelIr>,
28     aggregatedRoots: Set<AggregatedRootIr>
29   ): Set<AggregatedRootIr> {
30     val processedRootNames = processedRoots.flatMap { it.roots }.toSet()
31     val rootsToProcess =
32       aggregatedRoots.filterNot { processedRootNames.contains(it.root.canonicalName()) }.sortedBy {
33         it.root.canonicalName()
34       }
35     val testRootsToProcess = rootsToProcess.filter { it.isTestRoot }
36     val appRootsToProcess = rootsToProcess - testRootsToProcess
37     fun Collection<AggregatedRootIr>.rootsToString() = map { it.root }.joinToString()
38     if (appRootsToProcess.size > 1) {
39       throw InvalidRootsException(
40         "Cannot process multiple app roots in the same compilation unit: " +
41           appRootsToProcess.rootsToString()
42       )
43     }
44     if (testRootsToProcess.isNotEmpty() && appRootsToProcess.isNotEmpty()) {
45       throw InvalidRootsException(
46         """
47         Cannot process test roots and app roots in the same compilation unit:
48           App root in this compilation unit: ${appRootsToProcess.rootsToString()}
49           Test roots in this compilation unit: ${testRootsToProcess.rootsToString()}
50         """.trimIndent()
51       )
52     }
53     // Perform validation across roots previous compilation units.
54     if (!isCrossCompilationRootValidationDisabled) {
55       val alreadyProcessedTestRoots =
56         aggregatedRoots.filter {
57           it.isTestRoot && processedRootNames.contains(it.root.canonicalName())
58         }
59       // TODO(b/185742783): Add an explanation or link to docs to explain why we're forbidding this.
60       if (alreadyProcessedTestRoots.isNotEmpty() && rootsToProcess.isNotEmpty()) {
61         throw InvalidRootsException(
62           """
63           Cannot process new roots when there are test roots from a previous compilation unit:
64             Test roots from previous compilation unit: ${alreadyProcessedTestRoots.rootsToString()}
65             All roots from this compilation unit: ${rootsToProcess.rootsToString()}
66           """.trimIndent()
67         )
68       }
69 
70       val alreadyProcessedAppRoots =
71         aggregatedRoots.filter {
72           !it.isTestRoot && processedRootNames.contains(it.root.canonicalName())
73         }
74       if (alreadyProcessedAppRoots.isNotEmpty() && appRootsToProcess.isNotEmpty()) {
75         throw InvalidRootsException(
76           """
77           Cannot process new app roots when there are app roots from a previous compilation unit:
78             App roots in previous compilation unit: ${alreadyProcessedAppRoots.rootsToString()}
79             App roots in this compilation unit: ${appRootsToProcess.rootsToString()}
80           """.trimIndent()
81         )
82       }
83     }
84     return rootsToProcess.toSet()
85   }
86 }
87 
88 // An exception thrown when root validation fails.
89 class InvalidRootsException(msg: String) : Exception(msg)
90