Skip to content

Commit 4016448

Browse files
sjuddglide-copybara-robot
authored andcommittedJul 19, 2022
Add support for parsing LibraryGlideModules.
Every round now writes a new Index containing all LibraryGlideModules in that round. When we encounter an AppGlideModule, we read all previously read Index classes, extract the LibraryGlideModules they point to, and write a merged AppGlideModule that calls the developer's AppGlideModule and all of the LibraryGlideModules. Excluding LibraryGlideModules is not supported yet. The library is still in a pre-release state. Progress towards #4492 PiperOrigin-RevId: 461946515
1 parent c35ad13 commit 4016448

File tree

4 files changed

+655
-8
lines changed

4 files changed

+655
-8
lines changed
 

‎annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/AppGlideModules.kt

+46-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.bumptech.glide.annotation.ksp
22

33
import com.bumptech.glide.annotation.Excludes
4+
import com.google.devtools.ksp.KspExperimental
45
import com.google.devtools.ksp.getConstructors
56
import com.google.devtools.ksp.processing.Resolver
67
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
@@ -38,6 +39,8 @@ object AppGlideModuleConstants {
3839
internal data class AppGlideModuleData(
3940
val name: ClassName,
4041
val constructor: Constructor,
42+
val allowedLibraryGlideModuleNames: List<String>,
43+
val sources: List<KSDeclaration>,
4144
) {
4245
internal data class Constructor(val hasContext: Boolean)
4346
}
@@ -57,7 +60,26 @@ internal class AppGlideModuleParser(
5760
val constructor = parseAppGlideModuleConstructorOrThrow()
5861
val name = ClassName.bestGuess(appGlideModuleClass.qualifiedName!!.asString())
5962

60-
return AppGlideModuleData(name = name, constructor = constructor)
63+
val (indexFiles, allLibraryModuleNames) = getIndexesAndLibraryGlideModuleNames()
64+
val excludedGlideModuleClassNames = getExcludedGlideModuleClassNames()
65+
val filteredGlideModuleClassNames =
66+
allLibraryModuleNames.filterNot { excludedGlideModuleClassNames.contains(it) }
67+
68+
return AppGlideModuleData(
69+
name = name,
70+
constructor = constructor,
71+
allowedLibraryGlideModuleNames = filteredGlideModuleClassNames,
72+
sources = indexFiles
73+
)
74+
}
75+
76+
private fun getExcludedGlideModuleClassNames(): Set<String> {
77+
val excludesAnnotation = appGlideModuleClass.atMostOneExcludesAnnotation()
78+
// TODO(judds): Implement support for the excludes annotation.
79+
environment.logger.logging(
80+
"Found excludes annotation arguments: ${excludesAnnotation?.arguments}"
81+
)
82+
return emptySet()
6183
}
6284

6385
private fun parseAppGlideModuleConstructorOrThrow(): AppGlideModuleData.Constructor {
@@ -80,6 +102,22 @@ internal class AppGlideModuleParser(
80102
val libraryModuleNames: List<String>,
81103
)
82104

105+
@OptIn(KspExperimental::class)
106+
private fun getIndexesAndLibraryGlideModuleNames(): IndexFilesAndLibraryModuleNames {
107+
val allIndexFiles: MutableList<KSDeclaration> = mutableListOf()
108+
val allLibraryGlideModuleNames: MutableList<String> = mutableListOf()
109+
resolver.getDeclarationsFromPackage(GlideSymbolProcessorConstants.PACKAGE_NAME).forEach {
110+
index: KSDeclaration ->
111+
val libraryGlideModuleNames = extractGlideModulesFromIndexAnnotation(index)
112+
if (libraryGlideModuleNames.isNotEmpty()) {
113+
allIndexFiles.add(index)
114+
allLibraryGlideModuleNames.addAll(libraryGlideModuleNames)
115+
}
116+
}
117+
118+
return IndexFilesAndLibraryModuleNames(allIndexFiles, allLibraryGlideModuleNames)
119+
}
120+
83121
private fun extractGlideModulesFromIndexAnnotation(
84122
index: KSDeclaration,
85123
): List<String> {
@@ -155,7 +193,7 @@ internal class AppGlideModuleGenerator(private val appGlideModuleData: AppGlideM
155193
.addModifiers(KModifier.INTERNAL)
156194
.addProperty("appGlideModule", data.name, KModifier.PRIVATE)
157195
.primaryConstructor(generateConstructor(data))
158-
.addFunction(generateRegisterComponents())
196+
.addFunction(generateRegisterComponents(data.allowedLibraryGlideModuleNames))
159197
.addFunction(generateApplyOptions())
160198
.addFunction(generateManifestParsingDisabled())
161199
.build()
@@ -183,13 +221,17 @@ internal class AppGlideModuleGenerator(private val appGlideModuleData: AppGlideM
183221
// TODO(judds): Log the discovered modules here.
184222
}
185223

186-
// TODO(judds): call registerComponents on LibraryGlideModules here.
187-
private fun generateRegisterComponents() =
224+
private fun generateRegisterComponents(allowedGlideModuleNames: List<String>) =
188225
FunSpec.builder("registerComponents")
189226
.addModifiers(KModifier.PUBLIC, KModifier.OVERRIDE)
190227
.addParameter("context", AppGlideModuleConstants.CONTEXT_CLASS_NAME)
191228
.addParameter("glide", ClassName(AppGlideModuleConstants.GLIDE_PACKAGE_NAME, "Glide"))
192229
.addParameter("registry", ClassName(AppGlideModuleConstants.GLIDE_PACKAGE_NAME, "Registry"))
230+
.apply {
231+
allowedGlideModuleNames.forEach {
232+
addStatement("%T().registerComponents(context, glide, registry)", ClassName.bestGuess(it))
233+
}
234+
}
193235
.addStatement("appGlideModule.registerComponents(context, glide, registry)")
194236
.build()
195237

‎annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/GlideSymbolProcessor.kt

+33-4
Original file line numberDiff line numberDiff line change
@@ -69,29 +69,58 @@ class GlideSymbolProcessor(private val environment: SymbolProcessorEnvironment)
6969
environment.logger.logging(
7070
"Found AppGlideModules: $appGlideModules, LibraryGlideModules: $libraryGlideModules"
7171
)
72-
// TODO(judds): Add support for parsing LibraryGlideModules here.
72+
73+
if (libraryGlideModules.isNotEmpty()) {
74+
if (isAppGlideModuleGenerated) {
75+
throw InvalidGlideSourceException(
76+
"""Found $libraryGlideModules LibraryGlideModules after processing the AppGlideModule.
77+
If you generated these LibraryGlideModules via another annotation processing, either
78+
don't or also generate the AppGlideModule and do so in the same round as the
79+
LibraryGlideModules or in a subsequent round"""
80+
)
81+
}
82+
parseLibraryModulesAndWriteIndex(libraryGlideModules)
83+
return invalidSymbols + appGlideModules
84+
}
7385

7486
if (appGlideModules.isNotEmpty()) {
75-
parseAppGlideModuleAndWriteGeneratedAppGlideModule(resolver, appGlideModules.single())
87+
parseAppGlideModuleAndIndexesAndWriteGeneratedAppGlideModule(
88+
resolver,
89+
appGlideModules.single()
90+
)
7691
}
7792

7893
return invalidSymbols
7994
}
8095

81-
private fun parseAppGlideModuleAndWriteGeneratedAppGlideModule(
96+
private fun parseAppGlideModuleAndIndexesAndWriteGeneratedAppGlideModule(
8297
resolver: Resolver,
8398
appGlideModule: KSClassDeclaration,
8499
) {
85100
val appGlideModuleData =
86101
AppGlideModuleParser(environment, resolver, appGlideModule).parseAppGlideModule()
87102
val appGlideModuleGenerator = AppGlideModuleGenerator(appGlideModuleData)
88103
val appGlideModuleFileSpec: FileSpec = appGlideModuleGenerator.generateAppGlideModule()
104+
val sources = appGlideModuleData.sources.mapNotNull { it.containingFile }.toMutableList()
105+
if (appGlideModule.containingFile != null) {
106+
sources.add(appGlideModule.containingFile!!)
107+
}
89108
writeFile(
90109
appGlideModuleFileSpec,
91-
listOfNotNull(appGlideModule.containingFile),
110+
sources,
92111
)
93112
}
94113

114+
private fun parseLibraryModulesAndWriteIndex(
115+
libraryGlideModuleClassDeclarations: List<KSClassDeclaration>,
116+
) {
117+
val libraryGlideModulesParser =
118+
LibraryGlideModulesParser(environment, libraryGlideModuleClassDeclarations)
119+
val uniqueLibraryGlideModules = libraryGlideModulesParser.parseUnique()
120+
val index: FileSpec = IndexGenerator.generate(uniqueLibraryGlideModules.map { it.name })
121+
writeFile(index, uniqueLibraryGlideModules.mapNotNull { it.containingFile })
122+
}
123+
95124
private fun writeFile(file: FileSpec, sources: List<KSFile>) {
96125
environment.codeGenerator
97126
.createNewFile(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.bumptech.glide.annotation.ksp
2+
3+
import com.bumptech.glide.annotation.GlideModule
4+
import com.bumptech.glide.annotation.ksp.LibraryGlideModuleData.LibraryModuleName
5+
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
6+
import com.google.devtools.ksp.symbol.KSClassDeclaration
7+
import com.google.devtools.ksp.symbol.KSFile
8+
import com.squareup.kotlinpoet.AnnotationSpec
9+
import com.squareup.kotlinpoet.DelicateKotlinPoetApi
10+
import com.squareup.kotlinpoet.FileSpec
11+
import com.squareup.kotlinpoet.TypeSpec
12+
import java.util.UUID
13+
14+
internal data class LibraryGlideModuleData(
15+
val name: LibraryModuleName,
16+
val containingFile: KSFile?,
17+
) {
18+
data class LibraryModuleName(val qualifiedName: String)
19+
}
20+
21+
internal class LibraryGlideModulesParser(
22+
private val environment: SymbolProcessorEnvironment,
23+
private val libraryGlideModules: List<KSClassDeclaration>,
24+
) {
25+
init {
26+
require(libraryGlideModules.isNotEmpty())
27+
}
28+
29+
fun parseUnique(): List<LibraryGlideModuleData> {
30+
val allLibraryGlideModules =
31+
libraryGlideModules
32+
.map {
33+
LibraryGlideModuleData(
34+
LibraryModuleName(it.qualifiedName!!.asString()),
35+
it.containingFile
36+
)
37+
}
38+
.toList()
39+
val uniqueLibraryGlideModules = allLibraryGlideModules.associateBy { it.name }.values.toList()
40+
if (uniqueLibraryGlideModules != libraryGlideModules) {
41+
// Find the set of modules that have been included more than once by mapping the qualified
42+
// name of the module to a count of the number of times it's been seen. Duplicates are then
43+
// any keys that have a value > 1.
44+
val duplicateModules: List<String> =
45+
allLibraryGlideModules
46+
.groupingBy { it.name.qualifiedName }
47+
.eachCount()
48+
.filter { it.value > 1 }
49+
.keys
50+
.toList()
51+
environment.logger.warn(
52+
GlideSymbolProcessorConstants.DUPLICATE_LIBRARY_MODULE_ERROR.format(duplicateModules)
53+
)
54+
}
55+
56+
return uniqueLibraryGlideModules
57+
}
58+
}
59+
60+
/**
61+
* Generates an empty class with an annotation containing the class names of one or more
62+
* LibraryGlideModules and/or one or more GlideExtensions.
63+
*
64+
* We use a separate class so that LibraryGlideModules and GlideExtensions written in libraries can
65+
* be bundled into an AAR and later retrieved by the annotation processor when it processes the
66+
* AppGlideModule in an application.
67+
*
68+
* The output file generated by this class with a single LibraryGlideModule looks like this:
69+
*
70+
* ```
71+
* @com.bumptech.glide.annotation.compiler.Index(
72+
* ["com.bumptech.glide.integration.okhttp3.OkHttpLibraryGlideModule"]
73+
* )
74+
* class Indexer_GlideModule_com_bumptech_glide_integration_okhttp3_OkHttpLibraryGlideModule
75+
* ```
76+
*
77+
* This class is not a public API and used only internally by the processor.
78+
*/
79+
internal object IndexGenerator {
80+
private const val INDEXER_NAME_PREFIX = "GlideIndexer_"
81+
private const val MAXIMUM_FILE_NAME_LENGTH = 255
82+
83+
@OptIn(DelicateKotlinPoetApi::class) // We're using AnnotationSpec.builder
84+
fun generate(
85+
libraryModuleNames: List<LibraryModuleName>,
86+
): FileSpec {
87+
val libraryModuleQualifiedNames: List<String> = libraryModuleNames.map { it.qualifiedName }
88+
89+
val indexAnnotation: AnnotationSpec =
90+
AnnotationSpec.builder(Index::class.java)
91+
.addRepeatedMember(libraryModuleQualifiedNames)
92+
.build()
93+
val indexName = generateUniqueName(libraryModuleQualifiedNames)
94+
95+
return FileSpec.builder(GlideSymbolProcessorConstants.PACKAGE_NAME, indexName)
96+
.addType(TypeSpec.classBuilder(indexName).addAnnotation(indexAnnotation).build())
97+
.build()
98+
}
99+
100+
private fun generateUniqueName(libraryModuleQualifiedNames: List<String>): String {
101+
val glideModuleBasedName = generateNameFromLibraryModules(libraryModuleQualifiedNames)
102+
103+
// If the indexer name has too many packages/modules, it can exceed the file name length
104+
// allowed by the file system, which can break compilation. To avoid that, fall back to a
105+
// deterministic UUID.
106+
return if (glideModuleBasedName.exceedsFileSystemMaxNameLength()) {
107+
generateShortUUIDBasedName(glideModuleBasedName)
108+
} else {
109+
glideModuleBasedName
110+
}
111+
}
112+
113+
private fun String.exceedsFileSystemMaxNameLength() =
114+
length >= MAXIMUM_FILE_NAME_LENGTH - INDEXER_NAME_PREFIX.length
115+
116+
private fun generateShortUUIDBasedName(glideModuleBasedName: String) =
117+
INDEXER_NAME_PREFIX +
118+
UUID.nameUUIDFromBytes(glideModuleBasedName.toByteArray()).toString().replace("-", "_")
119+
120+
private fun generateNameFromLibraryModules(libraryModuleQualifiedNames: List<String>): String {
121+
return libraryModuleQualifiedNames.joinToString(
122+
prefix = INDEXER_NAME_PREFIX + GlideModule::class.java.simpleName + "_",
123+
separator = "_"
124+
) { it.replace(".", "_") }
125+
}
126+
127+
private fun AnnotationSpec.Builder.addRepeatedMember(repeatedMember: List<String>) =
128+
addMember("[\n" + "%S,\n".repeat(repeatedMember.size) + "]", *repeatedMember.toTypedArray())
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,447 @@
1+
package com.bumptech.glide.annotation.ksp.test
2+
3+
import com.bumptech.glide.annotation.ksp.GlideSymbolProcessorConstants
4+
import com.google.common.truth.Truth.assertThat
5+
import com.tschuchort.compiletesting.KotlinCompilation.ExitCode
6+
import java.io.FileNotFoundException
7+
import kotlin.test.assertFailsWith
8+
import org.intellij.lang.annotations.Language
9+
import org.junit.Assume.assumeTrue
10+
import org.junit.Test
11+
import org.junit.runner.RunWith
12+
import org.junit.runners.Parameterized
13+
import org.junit.runners.Parameterized.Parameters
14+
15+
@RunWith(Parameterized::class)
16+
class LibraryGlideModuleTests(override val sourceType: SourceType) : PerSourceTypeTest {
17+
18+
companion object {
19+
@Parameters(name = "sourceType = {0}") @JvmStatic fun data() = SourceType.values()
20+
}
21+
22+
@Test
23+
fun compile_withAnnotatedAndValidLibraryGlideModule_succeeds_butDoesNotGenerateGeneratedAppGlideModule() {
24+
val kotlinModule =
25+
KotlinSourceFile(
26+
"Module.kt",
27+
"""
28+
import com.bumptech.glide.annotation.GlideModule
29+
import com.bumptech.glide.module.LibraryGlideModule
30+
31+
@GlideModule class Module : LibraryGlideModule()
32+
"""
33+
)
34+
val javaModule =
35+
JavaSourceFile(
36+
"Module.java",
37+
"""
38+
import com.bumptech.glide.annotation.GlideModule;
39+
import com.bumptech.glide.module.LibraryGlideModule;
40+
41+
@GlideModule public class Module extends LibraryGlideModule {}
42+
"""
43+
)
44+
45+
compileCurrentSourceType(kotlinModule, javaModule) {
46+
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
47+
assertFailsWith<FileNotFoundException> { it.generatedAppGlideModuleContents() }
48+
}
49+
}
50+
51+
@Test
52+
fun compile_withValidLibraryGlideModule_andAppGlideModule_generatesGeneratedAppGlideModule_andCallsBothLibraryAndAppGlideModules() {
53+
val kotlinLibraryModule =
54+
KotlinSourceFile(
55+
"LibraryModule.kt",
56+
"""
57+
import com.bumptech.glide.annotation.GlideModule
58+
import com.bumptech.glide.module.LibraryGlideModule
59+
60+
@GlideModule class LibraryModule : LibraryGlideModule()
61+
"""
62+
)
63+
val kotlinAppModule =
64+
KotlinSourceFile(
65+
"AppModule.kt",
66+
"""
67+
import com.bumptech.glide.annotation.GlideModule
68+
import com.bumptech.glide.module.AppGlideModule
69+
70+
@GlideModule class AppModule : AppGlideModule()
71+
"""
72+
)
73+
val javaLibraryModule =
74+
JavaSourceFile(
75+
"LibraryModule.java",
76+
"""
77+
import com.bumptech.glide.annotation.GlideModule;
78+
import com.bumptech.glide.module.LibraryGlideModule;
79+
80+
@GlideModule public class LibraryModule extends LibraryGlideModule {}
81+
"""
82+
)
83+
val javaAppModule =
84+
JavaSourceFile(
85+
"AppModule.java",
86+
"""
87+
import com.bumptech.glide.annotation.GlideModule;
88+
import com.bumptech.glide.module.AppGlideModule;
89+
90+
@GlideModule public class AppModule extends AppGlideModule {
91+
public AppModule() {}
92+
}
93+
"""
94+
)
95+
96+
compileCurrentSourceType(
97+
kotlinAppModule,
98+
kotlinLibraryModule,
99+
javaAppModule,
100+
javaLibraryModule
101+
) {
102+
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
103+
assertThat(it.generatedAppGlideModuleContents())
104+
.hasSourceEqualTo(appGlideModuleWithLibraryModule)
105+
}
106+
}
107+
108+
@Test
109+
fun compile_withMultipleLibraryGlideModules_andAppGlideModule_callsAllLibraryGlideModulesFromGeneratedAppGlideModule() {
110+
val kotlinLibraryModule1 =
111+
KotlinSourceFile(
112+
"LibraryModule1.kt",
113+
"""
114+
import com.bumptech.glide.annotation.GlideModule
115+
import com.bumptech.glide.module.LibraryGlideModule
116+
117+
@GlideModule class LibraryModule1 : LibraryGlideModule()
118+
"""
119+
)
120+
val kotlinLibraryModule2 =
121+
KotlinSourceFile(
122+
"LibraryModule2.kt",
123+
"""
124+
import com.bumptech.glide.annotation.GlideModule
125+
import com.bumptech.glide.module.LibraryGlideModule
126+
127+
@GlideModule class LibraryModule2 : LibraryGlideModule()
128+
"""
129+
)
130+
val kotlinAppModule =
131+
KotlinSourceFile(
132+
"AppModule.kt",
133+
"""
134+
import com.bumptech.glide.annotation.GlideModule
135+
import com.bumptech.glide.module.AppGlideModule
136+
137+
@GlideModule class AppModule : AppGlideModule()
138+
"""
139+
)
140+
val javaLibraryModule1 =
141+
JavaSourceFile(
142+
"LibraryModule1.java",
143+
"""
144+
import com.bumptech.glide.annotation.GlideModule;
145+
import com.bumptech.glide.module.LibraryGlideModule;
146+
147+
@GlideModule public class LibraryModule1 extends LibraryGlideModule {}
148+
"""
149+
)
150+
val javaLibraryModule2 =
151+
JavaSourceFile(
152+
"LibraryModule2.java",
153+
"""
154+
import com.bumptech.glide.annotation.GlideModule;
155+
import com.bumptech.glide.module.LibraryGlideModule;
156+
157+
@GlideModule public class LibraryModule2 extends LibraryGlideModule {}
158+
"""
159+
)
160+
val javaAppModule =
161+
JavaSourceFile(
162+
"AppModule.java",
163+
"""
164+
import com.bumptech.glide.annotation.GlideModule;
165+
import com.bumptech.glide.module.AppGlideModule;
166+
167+
@GlideModule public class AppModule extends AppGlideModule {
168+
public AppModule() {}
169+
}
170+
"""
171+
)
172+
173+
compileCurrentSourceType(
174+
kotlinAppModule,
175+
kotlinLibraryModule1,
176+
kotlinLibraryModule2,
177+
javaAppModule,
178+
javaLibraryModule1,
179+
javaLibraryModule2,
180+
) {
181+
assertThat(it.generatedAppGlideModuleContents())
182+
.hasSourceEqualTo(appGlideModuleWithMultipleLibraryModules)
183+
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
184+
}
185+
}
186+
187+
@Test
188+
fun compile_withTheSameLibraryGlideModuleInMultipleFiles_andAnAppGlideModule_generatesGeneratedAppGlideModuleThatCallsTheLibraryGlideModuleOnce() {
189+
// Kotlin seems fine with multiple identical classes. For Java this is compile time error
190+
// already, so we don't have to handle it.
191+
assumeTrue(sourceType == SourceType.KOTLIN)
192+
val kotlinLibraryModule1 =
193+
KotlinSourceFile(
194+
"LibraryModule1.kt",
195+
"""
196+
import com.bumptech.glide.annotation.GlideModule
197+
import com.bumptech.glide.module.LibraryGlideModule
198+
199+
@GlideModule class LibraryModule : LibraryGlideModule()
200+
"""
201+
)
202+
val kotlinLibraryModule2 =
203+
KotlinSourceFile(
204+
"LibraryModule2.kt",
205+
"""
206+
import com.bumptech.glide.annotation.GlideModule
207+
import com.bumptech.glide.module.LibraryGlideModule
208+
209+
@GlideModule class LibraryModule : LibraryGlideModule()
210+
"""
211+
)
212+
val kotlinAppModule =
213+
KotlinSourceFile(
214+
"AppModule.kt",
215+
"""
216+
import com.bumptech.glide.annotation.GlideModule
217+
import com.bumptech.glide.module.AppGlideModule
218+
219+
@GlideModule class AppModule : AppGlideModule()
220+
"""
221+
)
222+
223+
compileCurrentSourceType(
224+
kotlinAppModule,
225+
kotlinLibraryModule1,
226+
kotlinLibraryModule2,
227+
) {
228+
assertThat(it.generatedAppGlideModuleContents())
229+
.hasSourceEqualTo(appGlideModuleWithLibraryModule)
230+
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
231+
assertThat(it.messages)
232+
.contains(
233+
GlideSymbolProcessorConstants.DUPLICATE_LIBRARY_MODULE_ERROR.format("[LibraryModule]")
234+
)
235+
}
236+
}
237+
238+
@Test
239+
fun compile_withLibraryGlideModulesWithDifferentPackages_butSameName_andAppGlideModule_callsEachLibraryGlideModuleOnceFromGeneratedAppGlideModule() {
240+
// TODO(judds): The two java classes don't compile when run by the annotation processor, which
241+
// means we can't really test this case for java code. Fix compilation issue and re-enable this
242+
// test for Java code.
243+
assumeTrue(sourceType == SourceType.KOTLIN)
244+
val kotlinLibraryModule1 =
245+
KotlinSourceFile(
246+
"LibraryModule1.kt",
247+
"""
248+
package first_package
249+
250+
import com.bumptech.glide.annotation.GlideModule
251+
import com.bumptech.glide.module.LibraryGlideModule
252+
253+
@GlideModule class LibraryModule : LibraryGlideModule()
254+
"""
255+
)
256+
val kotlinLibraryModule2 =
257+
KotlinSourceFile(
258+
"LibraryModule2.kt",
259+
"""
260+
package second_package
261+
262+
import com.bumptech.glide.annotation.GlideModule
263+
import com.bumptech.glide.module.LibraryGlideModule
264+
265+
@GlideModule class LibraryModule : LibraryGlideModule()
266+
"""
267+
)
268+
val kotlinAppModule =
269+
KotlinSourceFile(
270+
"AppModule.kt",
271+
"""
272+
import com.bumptech.glide.annotation.GlideModule
273+
import com.bumptech.glide.module.AppGlideModule
274+
275+
@GlideModule class AppModule : AppGlideModule()
276+
"""
277+
)
278+
val javaLibraryModule1 =
279+
JavaSourceFile(
280+
"LibraryModule1.java",
281+
"""
282+
package first_package;
283+
import com.bumptech.glide.annotation.GlideModule;
284+
import com.bumptech.glide.module.LibraryGlideModule;
285+
286+
public class LibraryModule1 {
287+
@GlideModule public static final class LibraryModule extends LibraryGlideModule {}
288+
}
289+
"""
290+
)
291+
val javaLibraryModule2 =
292+
JavaSourceFile(
293+
"LibraryModule2.java",
294+
"""
295+
package second_package;
296+
import com.bumptech.glide.annotation.GlideModule;
297+
import com.bumptech.glide.module.LibraryGlideModule;
298+
299+
public class LibraryModule2 {
300+
@GlideModule public static final class LibraryModule extends LibraryGlideModule {}
301+
}
302+
"""
303+
)
304+
val javaAppModule =
305+
JavaSourceFile(
306+
"AppModule.java",
307+
"""
308+
import com.bumptech.glide.annotation.GlideModule;
309+
import com.bumptech.glide.module.AppGlideModule;
310+
311+
@GlideModule public class AppModule extends AppGlideModule {
312+
public AppModule() {}
313+
}
314+
"""
315+
)
316+
317+
compileCurrentSourceType(
318+
kotlinAppModule,
319+
kotlinLibraryModule1,
320+
kotlinLibraryModule2,
321+
javaAppModule,
322+
javaLibraryModule1,
323+
javaLibraryModule2,
324+
) {
325+
assertThat(it.generatedAppGlideModuleContents())
326+
.hasSourceEqualTo(appGlideModuleWithPackagePrefixedLibraryModules)
327+
assertThat(it.exitCode).isEqualTo(ExitCode.OK)
328+
}
329+
}
330+
}
331+
332+
@Language("kotlin")
333+
const val appGlideModuleWithPackagePrefixedLibraryModules =
334+
"""
335+
package com.bumptech.glide
336+
337+
import AppModule
338+
import android.content.Context
339+
import first_package.LibraryModule
340+
import kotlin.Boolean
341+
import kotlin.Suppress
342+
import kotlin.Unit
343+
344+
internal class GeneratedAppGlideModuleImpl(
345+
@Suppress("UNUSED_VARIABLE")
346+
context: Context,
347+
) : GeneratedAppGlideModule() {
348+
private val appGlideModule: AppModule
349+
init {
350+
appGlideModule = AppModule()
351+
}
352+
353+
public override fun registerComponents(
354+
context: Context,
355+
glide: Glide,
356+
registry: Registry,
357+
): Unit {
358+
LibraryModule().registerComponents(context, glide, registry)
359+
second_package.LibraryModule().registerComponents(context, glide, registry)
360+
appGlideModule.registerComponents(context, glide, registry)
361+
}
362+
363+
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
364+
appGlideModule.applyOptions(context, builder)
365+
}
366+
367+
public override fun isManifestParsingEnabled(): Boolean = false
368+
}
369+
"""
370+
371+
@Language("kotlin")
372+
const val appGlideModuleWithLibraryModule =
373+
"""
374+
package com.bumptech.glide
375+
376+
import AppModule
377+
import LibraryModule
378+
import android.content.Context
379+
import kotlin.Boolean
380+
import kotlin.Suppress
381+
import kotlin.Unit
382+
383+
internal class GeneratedAppGlideModuleImpl(
384+
@Suppress("UNUSED_VARIABLE")
385+
context: Context,
386+
) : GeneratedAppGlideModule() {
387+
private val appGlideModule: AppModule
388+
init {
389+
appGlideModule = AppModule()
390+
}
391+
392+
public override fun registerComponents(
393+
context: Context,
394+
glide: Glide,
395+
registry: Registry,
396+
): Unit {
397+
LibraryModule().registerComponents(context, glide, registry)
398+
appGlideModule.registerComponents(context, glide, registry)
399+
}
400+
401+
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
402+
appGlideModule.applyOptions(context, builder)
403+
}
404+
405+
public override fun isManifestParsingEnabled(): Boolean = false
406+
}
407+
"""
408+
409+
@Language("kotlin")
410+
const val appGlideModuleWithMultipleLibraryModules =
411+
"""
412+
package com.bumptech.glide
413+
414+
import AppModule
415+
import LibraryModule1
416+
import LibraryModule2
417+
import android.content.Context
418+
import kotlin.Boolean
419+
import kotlin.Suppress
420+
import kotlin.Unit
421+
422+
internal class GeneratedAppGlideModuleImpl(
423+
@Suppress("UNUSED_VARIABLE")
424+
context: Context,
425+
) : GeneratedAppGlideModule() {
426+
private val appGlideModule: AppModule
427+
init {
428+
appGlideModule = AppModule()
429+
}
430+
431+
public override fun registerComponents(
432+
context: Context,
433+
glide: Glide,
434+
registry: Registry,
435+
): Unit {
436+
LibraryModule1().registerComponents(context, glide, registry)
437+
LibraryModule2().registerComponents(context, glide, registry)
438+
appGlideModule.registerComponents(context, glide, registry)
439+
}
440+
441+
public override fun applyOptions(context: Context, builder: GlideBuilder): Unit {
442+
appGlideModule.applyOptions(context, builder)
443+
}
444+
445+
public override fun isManifestParsingEnabled(): Boolean = false
446+
}
447+
"""

0 commit comments

Comments
 (0)
Please sign in to comment.