• 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 = aggregatedRoots
32         .filterNot { processedRootNames.contains(it.root) }
33         .sortedBy { it.root.toString() }
34       val testRootsToProcess = rootsToProcess.filter { it.isTestRoot }
35       val appRootsToProcess = rootsToProcess - testRootsToProcess
36       fun Collection<AggregatedRootIr>.rootsToString() = map { it.root }.joinToString()
37       if (appRootsToProcess.size > 1) {
38         throw InvalidRootsException(
39           "Cannot process multiple app roots in the same compilation unit: " +
40             appRootsToProcess.rootsToString()
41         )
42       }
43       if (testRootsToProcess.isNotEmpty() && appRootsToProcess.isNotEmpty()) {
44         throw InvalidRootsException("""
45         Cannot process test roots and app roots in the same compilation unit:
46           App root in this compilation unit: ${appRootsToProcess.rootsToString()}
47           Test roots in this compilation unit: ${testRootsToProcess.rootsToString()}
48         """.trimIndent()
49         )
50       }
51       // Perform validation across roots previous compilation units.
52       if (!isCrossCompilationRootValidationDisabled) {
53         val alreadyProcessedTestRoots = aggregatedRoots.filter {
54           it.isTestRoot && processedRootNames.contains(it.root)
55         }
56         // TODO(b/185742783): Add an explanation or link to docs to explain why we're forbidding this.
57         if (alreadyProcessedTestRoots.isNotEmpty() && rootsToProcess.isNotEmpty()) {
58           throw InvalidRootsException("""
59           Cannot process new roots when there are test roots from a previous compilation unit:
60             Test roots from previous compilation unit: ${alreadyProcessedTestRoots.rootsToString()}
61             All roots from this compilation unit: ${rootsToProcess.rootsToString()}
62           """.trimIndent()
63           )
64         }
65         val alreadyProcessedAppRoots = aggregatedRoots.filter {
66           !it.isTestRoot && processedRootNames.contains(it.root)
67         }
68         if (alreadyProcessedAppRoots.isNotEmpty() && appRootsToProcess.isNotEmpty()) {
69           throw InvalidRootsException("""
70           Cannot process new app roots when there are app roots from a previous compilation unit:
71             App roots in previous compilation unit: ${alreadyProcessedAppRoots.rootsToString()}
72             App roots in this compilation unit: ${appRootsToProcess.rootsToString()}
73           """.trimIndent()
74           )
75         }
76       }
77       return rootsToProcess.toSet()
78     }
79 }
80 
81 // An exception thrown when root validation fails.
82 class InvalidRootsException(msg: String) : Exception(msg)
83