|
1 | | -@file:Suppress("UnstableApiUsage") |
2 | | - |
3 | 1 | package com.squareup.anvil.plugin |
4 | 2 |
|
5 | | -import com.android.build.gradle.internal.workeractions.WorkerActionServiceRegistry |
6 | | -import com.android.ide.common.process.ProcessException |
7 | | -import com.google.common.io.Closer |
8 | 3 | import org.gradle.api.Project |
| 4 | +import org.gradle.api.provider.Provider |
9 | 5 | import org.gradle.api.services.BuildService |
10 | 6 | import org.gradle.api.services.BuildServiceParameters.None |
11 | | -import java.io.IOException |
12 | | -import java.util.UUID |
13 | | - |
14 | | -/** Used to get unique build service name. Each class loader will initialize it's onw version. */ |
15 | | -private val ANVIL_INCREMENTAL_SIGNAL_BUILD_SERVICE_NAME = |
16 | | - "anvil-incremental-signal-build-service" + UUID.randomUUID() |
17 | | - |
18 | | -/** |
19 | | - * Registers incremental signal build service and returns a service key that can be used to access |
20 | | - * the service later. |
| 7 | +import kotlin.random.Random |
| 8 | + |
| 9 | +/* |
| 10 | + * The key is important. Gradle uses different class loaders for different modules when the plugin |
| 11 | + * is applied through the new plugins { } syntax. If we'd use the same key, then the |
| 12 | + * IncrementalSignal class would be different for the same entry and Gradle would throw an error. |
| 13 | + * |
| 14 | + * By using a random key per class loader we avoid this issue. Since this service isn't shared |
| 15 | + * across modules and only within a module it's not causing any problems tasks only use the service |
| 16 | + * for their project. |
| 17 | + * |
| 18 | + * We could also create one service per module, but that seems wasteful. When the Gradle plugin is |
| 19 | + * added to classpath of the root project, then the key is always the same and all modules share |
| 20 | + * a single build service and a single cache. |
21 | 21 | */ |
22 | | -fun registerIncrementalSignalBuildService(project: Project): IncrementalSignalServiceKey { |
23 | | - val buildServiceProvider = project.gradle.sharedServices.registerIfAbsent( |
24 | | - ANVIL_INCREMENTAL_SIGNAL_BUILD_SERVICE_NAME, |
25 | | - IncrementalSignalBuildService::class.java |
26 | | - ) {} |
27 | | - return buildServiceProvider.get() |
28 | | - .registerIncrementalSignalService(project.path) |
29 | | -} |
30 | | - |
31 | | -/** |
32 | | - * Service registry used to store IncrementalSignal services so they are accessible from the worker |
33 | | - * actions. |
34 | | - */ |
35 | | -var incrementalSignalServiceRegistry: WorkerActionServiceRegistry = WorkerActionServiceRegistry() |
36 | | - |
37 | | -/** Intended for use from worker actions. */ |
38 | | -@Throws(ProcessException::class, IOException::class) |
39 | | -fun useIncrementalSignalService( |
40 | | - incrementalSignalServiceKey: IncrementalSignalServiceKey, |
41 | | - serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry, |
42 | | - block: (IncrementalSignalService) -> Unit |
43 | | -) = serviceRegistry.getService(incrementalSignalServiceKey).service.let(block) |
44 | | - |
45 | | -fun getIncrementalSignalService( |
46 | | - incrementalSignalServiceKey: IncrementalSignalServiceKey, |
47 | | - serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry |
48 | | -): IncrementalSignalService = serviceRegistry.getService(incrementalSignalServiceKey).service |
49 | | - |
50 | | -data class IncrementalSignalServiceKey( |
51 | | - val projectPath: String |
52 | | -) : WorkerActionServiceRegistry.ServiceKey<IncrementalSignalService> { |
53 | | - override val type: Class<IncrementalSignalService> get() = IncrementalSignalService::class.java |
54 | | -} |
55 | | - |
56 | | -data class IncrementalSignalService(var incremental: Boolean? = null) |
| 22 | +private val KEY = "incrementalSignal-" + Random.nextLong() |
57 | 23 |
|
58 | 24 | /** This signal is used to share state between the task above and Kotlin compile tasks. */ |
59 | | -abstract class IncrementalSignalBuildService : BuildService<None>, AutoCloseable { |
60 | | - private val registeredServices = mutableSetOf<IncrementalSignalServiceKey>() |
61 | | - private val closer = Closer.create() |
| 25 | +@Suppress("UnstableApiUsage") |
| 26 | +abstract class IncrementalSignal : BuildService<None> { |
| 27 | + private val incremental = mutableMapOf<String, Boolean?>() |
62 | 28 |
|
63 | | - @Synchronized |
64 | | - fun registerIncrementalSignalService( |
| 29 | + @Synchronized fun setIncremental( |
65 | 30 | projectPath: String, |
66 | | - serviceRegistry: WorkerActionServiceRegistry = incrementalSignalServiceRegistry |
67 | | - ): IncrementalSignalServiceKey { |
68 | | - val key = IncrementalSignalServiceKey(projectPath) |
69 | | - |
70 | | - if (registeredServices.add(key)) { |
71 | | - closer.register(serviceRegistry.registerServiceAsCloseable(key, IncrementalSignalService())) |
72 | | - } |
73 | | - |
74 | | - return key |
| 31 | + incremental: Boolean |
| 32 | + ) { |
| 33 | + this.incremental[projectPath] = incremental |
75 | 34 | } |
76 | 35 |
|
77 | | - override fun close() { |
78 | | - closer.close() |
| 36 | + @Synchronized fun isIncremental(projectPath: String): Boolean? = incremental[projectPath] |
| 37 | + |
| 38 | + companion object { |
| 39 | + fun registerIfAbsent(project: Project): Provider<IncrementalSignal> = |
| 40 | + project.gradle.sharedServices.registerIfAbsent(KEY, IncrementalSignal::class.java) { } |
79 | 41 | } |
80 | 42 | } |
0 commit comments