diff --git a/annotation/ksp/integrationtest/src/test/java/com/bumptech/glide/annotation/ksp/integrationtest/IntegrationLibraryGlideModuleTests.kt b/annotation/ksp/integrationtest/src/test/java/com/bumptech/glide/annotation/ksp/integrationtest/IntegrationLibraryGlideModuleTests.kt index 465b331088..5f0abe4d08 100644 --- a/annotation/ksp/integrationtest/src/test/java/com/bumptech/glide/annotation/ksp/integrationtest/IntegrationLibraryGlideModuleTests.kt +++ b/annotation/ksp/integrationtest/src/test/java/com/bumptech/glide/annotation/ksp/integrationtest/IntegrationLibraryGlideModuleTests.kt @@ -56,6 +56,53 @@ class IntegrationLibraryGlideModuleTests(override val sourceType: SourceType) : } } + @Test + fun compile_withOnlyAppGlideModuleThroughBaseClass_generatesGeneratedAppGlideModule_thatCallsDependencyLibraryGlideModules() { + val kotlinAppModule = + KotlinSourceFile( + "AppModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.AppGlideModule + + class BaseAppModule : AppGlideModule() + @GlideModule class AppModule : BaseAppModule() + """ + ) + val javaBaseAppModule = + JavaSourceFile( + "BaseAppModule.java", + """ + import com.bumptech.glide.module.AppGlideModule; + + public class BaseAppModule extends AppGlideModule { + public BaseAppModule() {} + } + """ + ) + val javaAppModule = + JavaSourceFile( + "AppModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class AppModule extends BaseAppModule { + public AppModule() {} + } + """ + ) + + compileCurrentSourceType( + kotlinAppModule, + javaBaseAppModule, + javaAppModule, + ) { + assertThat(it.exitCode).isEqualTo(ExitCode.OK) + assertThat(it.generatedAppGlideModuleContents()) + .hasSourceEqualTo(appGlideModuleWithOnlyDependencyLibraryModules) + } + } + @Test fun compile_withValidLibraryGlideModule_andAppGlideModule_generatesGeneratedAppGlideModule_thatCallsAllLibraryAndDependencyAndAppGlideModules() { val kotlinLibraryModule = @@ -113,6 +160,85 @@ class IntegrationLibraryGlideModuleTests(override val sourceType: SourceType) : } } + @Test + fun compile_withValidLibraryGlideModule_andAppGlideModule_ThroughBaseClass_generatesGeneratedAppGlideModule_thatCallsAllLibraryAndDependencyAndAppGlideModules() { + val kotlinLibraryModule = + KotlinSourceFile( + "LibraryModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.LibraryGlideModule + + class BaseLibraryModule : LibraryGlideModule() + @GlideModule class LibraryModule : BaseLibraryModule() + """ + ) + val kotlinAppModule = + KotlinSourceFile( + "AppModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.AppGlideModule + + class BaseAppModule : AppGlideModule() + @GlideModule class AppModule : BaseAppModule() + """ + ) + val javaBaseLibraryModule = + JavaSourceFile( + "BaseLibraryModule.java", + """ + import com.bumptech.glide.module.LibraryGlideModule; + + public class BaseLibraryModule extends LibraryGlideModule {} + """ + ) + val javaLibraryModule = + JavaSourceFile( + "LibraryModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class LibraryModule extends BaseLibraryModule {} + """ + ) + val javaBaseAppModule = + JavaSourceFile( + "BaseAppModule.java", + """ + import com.bumptech.glide.module.AppGlideModule; + + public class BaseAppModule extends AppGlideModule { + public BaseAppModule() {} + } + """ + ) + val javaAppModule = + JavaSourceFile( + "AppModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class AppModule extends BaseAppModule { + public AppModule() {} + } + """ + ) + + compileCurrentSourceType( + kotlinAppModule, + kotlinLibraryModule, + javaBaseAppModule, + javaAppModule, + javaBaseLibraryModule, + javaLibraryModule + ) { + assertThat(it.exitCode).isEqualTo(ExitCode.OK) + assertThat(it.generatedAppGlideModuleContents()) + .hasSourceEqualTo(appGlideModuleWithLibraryModuleAndDependencyLibraryModules) + } + } + @Test fun compile_withDependencyModuleInExcludes_generatesGeneratedAppGlideModule_thatDoesNotCallDependencyLibraryGlideModules() { val kotlinAppModule = diff --git a/annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/ModuleParser.kt b/annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/ModuleParser.kt index deee71cc8f..c3cc0b054f 100644 --- a/annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/ModuleParser.kt +++ b/annotation/ksp/src/main/kotlin/com/bumptech/glide/annotation/ksp/ModuleParser.kt @@ -14,7 +14,7 @@ object ModuleParser { val appAndLibraryModuleNames = listOf(APP_MODULE_QUALIFIED_NAME, LIBRARY_MODULE_QUALIFIED_NAME) val modulesBySuperType: Map> = annotatedModules.filterIsInstance().groupBy { classDeclaration -> - appAndLibraryModuleNames.singleOrNull { classDeclaration.hasSuperType(it) } + appAndLibraryModuleNames.firstOrNull { classDeclaration.hasSuperType(it) } } val (appModules, libraryModules) = @@ -22,10 +22,19 @@ object ModuleParser { return GlideModules(appModules, libraryModules) } - private fun KSClassDeclaration.hasSuperType(superTypeQualifiedName: String) = - superTypes - .map { superType -> superType.resolve().declaration.qualifiedName!!.asString() } - .contains(superTypeQualifiedName) + private fun KSClassDeclaration.hasSuperType(superTypeQualifiedName: String): Boolean { + val superDeclarations = superTypes + .map { superType -> superType.resolve().declaration } + val hasInDirectParent = superDeclarations + .map { it.qualifiedName!!.asString() } + .contains(superTypeQualifiedName) + return if (hasInDirectParent) { + true + } else { + superDeclarations.filterIsInstance(KSClassDeclaration::class.java) + .any { it.hasSuperType(superTypeQualifiedName) } + } + } private const val APP_MODULE_QUALIFIED_NAME = "com.bumptech.glide.module.AppGlideModule" private const val LIBRARY_MODULE_QUALIFIED_NAME = "com.bumptech.glide.module.LibraryGlideModule" diff --git a/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/LibraryGlideModuleTests.kt b/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/LibraryGlideModuleTests.kt index a261b07bc0..0507ab3983 100644 --- a/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/LibraryGlideModuleTests.kt +++ b/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/LibraryGlideModuleTests.kt @@ -108,6 +108,86 @@ class LibraryGlideModuleTests(override val sourceType: SourceType) : PerSourceTy } } + @Test + fun compile_withValidLibraryGlideModule_andAppGlideModule_ThroughBaseClass_generatesGeneratedAppGlideModule_andCallsBothLibraryAndAppGlideModules() { + val kotlinLibraryModule = + KotlinSourceFile( + "LibraryModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.LibraryGlideModule + + class BaseLibraryModule : LibraryGlideModule() + @GlideModule class LibraryModule : BaseLibraryModule() + """ + ) + val kotlinAppModule = + KotlinSourceFile( + "AppModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.AppGlideModule + + class BaseAppModule : AppGlideModule() + @GlideModule class AppModule : BaseAppModule() + """ + ) + val javaBaseLibraryModule = + JavaSourceFile( + "BaseLibraryModule.java", + """ + import com.bumptech.glide.module.LibraryGlideModule; + + public class BaseLibraryModule extends LibraryGlideModule {} + """ + ) + val javaLibraryModule = + JavaSourceFile( + "LibraryModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class LibraryModule extends BaseLibraryModule {} + """ + ) + val javaBaseAppModule = + JavaSourceFile( + "BaseAppModule.java", + """ + import com.bumptech.glide.module.AppGlideModule; + + public class BaseAppModule extends AppGlideModule { + public BaseAppModule() {} + } + """ + ) + val javaAppModule = + JavaSourceFile( + "AppModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class AppModule extends BaseAppModule { + public AppModule() {} + } + """ + ) + + compileCurrentSourceType( + kotlinAppModule, + kotlinLibraryModule, + javaBaseAppModule, + javaAppModule, + javaBaseLibraryModule, + javaLibraryModule + ) { + assertThat(it.messages).doesNotContainMatch("[we]: \\[ksp] .*") + assertThat(it.exitCode).isEqualTo(ExitCode.OK) + assertThat(it.generatedAppGlideModuleContents()) + .hasSourceEqualTo(appGlideModuleWithLibraryModule) + } + } + @Test fun compile_withMultipleLibraryGlideModules_andAppGlideModule_callsAllLibraryGlideModulesFromGeneratedAppGlideModule() { val kotlinLibraryModule1 = diff --git a/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/OnlyAppGlideModuleTests.kt b/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/OnlyAppGlideModuleTests.kt index 3498b2fe47..8d8f9d18d2 100644 --- a/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/OnlyAppGlideModuleTests.kt +++ b/annotation/ksp/test/src/test/kotlin/com/bumptech/glide/annotation/ksp/test/OnlyAppGlideModuleTests.kt @@ -79,6 +79,46 @@ class OnlyAppGlideModuleTests(override val sourceType: SourceType) : PerSourceTy } } + @Test + fun compile_withGlideModuleOnValidAppGlideModuleThroughBaseClass_generatedGeneratedAppGlideModule() { + val kotlinModule = + KotlinSourceFile( + "AppModule.kt", + """ + import com.bumptech.glide.annotation.GlideModule + import com.bumptech.glide.module.AppGlideModule + class BaseAppModule : AppGlideModule() + @GlideModule class AppModule : BaseAppModule() + """ + ) + val javaBaseAppModule = + JavaSourceFile( + "BaseAppModule.java", + """ + import com.bumptech.glide.module.AppGlideModule; + + public class BaseAppModule extends AppGlideModule {} + """ + .trimIndent() + ) + val javaModule = + JavaSourceFile( + "AppModule.java", + """ + import com.bumptech.glide.annotation.GlideModule; + + @GlideModule public class AppModule extends BaseAppModule {} + """ + .trimIndent() + ) + + compileCurrentSourceType(kotlinModule, javaBaseAppModule, javaModule) { + assertThat(it.generatedAppGlideModuleContents()) + .hasSourceEqualTo(CommonSources.simpleAppGlideModule) + assertThat(it.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + } + } + @Test fun compile_withAppGlideModuleConstructorAcceptingOnlyContext_generatesGeneratedAppGlideModule() { val kotlinModule = @@ -179,7 +219,7 @@ class OnlyAppGlideModuleTests(override val sourceType: SourceType) : PerSourceTy // This is quite weird, we could probably pretty reasonably just assert that this doesn't happen. @Test - fun compile_withAppGlideModuleWithOneEmptyrConstructor_andOneContextOnlyConstructor_usesTheContextOnlyConstructor() { + fun compile_withAppGlideModuleWithOneEmptyConstructor_andOneContextOnlyConstructor_usesTheContextOnlyConstructor() { val kotlinModule = KotlinSourceFile( "AppModule.kt", @@ -217,7 +257,7 @@ class OnlyAppGlideModuleTests(override val sourceType: SourceType) : PerSourceTy } @Test - fun copmile_withMultipleAppGlideModules_failes() { + fun compile_withMultipleAppGlideModules_fails() { val firstKtModule = KotlinSourceFile( "Module1.kt",