Skip to content

Commit

Permalink
Merge pull request #5052 from sjudd:handle_java_indexes_in_ksp_processor
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 515131629
  • Loading branch information
glide-copybara-robot committed Mar 8, 2023
2 parents 4cf46ff + 16306e8 commit 902bbd4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,23 +191,58 @@ internal class AppGlideModuleParser(
private fun getIndexesAndLibraryGlideModuleNames(): IndexFilesAndLibraryModuleNames {
val allIndexFiles: MutableList<KSDeclaration> = mutableListOf()
val allLibraryGlideModuleNames: MutableList<String> = mutableListOf()
resolver.getDeclarationsFromPackage(GlideSymbolProcessorConstants.PACKAGE_NAME).forEach {
index: KSDeclaration ->
val libraryGlideModuleNames = extractGlideModulesFromIndexAnnotation(index)
if (libraryGlideModuleNames.isNotEmpty()) {
allIndexFiles.add(index)
allLibraryGlideModuleNames.addAll(libraryGlideModuleNames)
}

val allIndexesAndLibraryModules =
getAllLibraryNamesFromJavaIndexes() + getAllLibraryNamesFromKspIndexes()
for ((index, libraryGlideModuleNames) in allIndexesAndLibraryModules) {
allIndexFiles.add(index)
allLibraryGlideModuleNames.addAll(libraryGlideModuleNames)
}

return IndexFilesAndLibraryModuleNames(allIndexFiles, allLibraryGlideModuleNames)
}

private fun extractGlideModulesFromIndexAnnotation(
internal data class IndexAndLibraryModuleNames(
val index: KSDeclaration, val libraryModuleNames: List<String>
)

private fun getAllLibraryNamesFromKspIndexes(): List<IndexAndLibraryModuleNames> =
getAllLibraryNamesFromIndexes(GlideSymbolProcessorConstants.PACKAGE_NAME) { index ->
extractGlideModulesFromKspIndexAnnotation(index)
}

private fun getAllLibraryNamesFromJavaIndexes(): List<IndexAndLibraryModuleNames> =
getAllLibraryNamesFromIndexes(GlideSymbolProcessorConstants.JAVA_ANNOTATION_PACKAGE_NAME) {
index -> extractGlideModulesFromJavaIndexAnnotation(index)
}

@OptIn(KspExperimental::class)
private fun getAllLibraryNamesFromIndexes(
packageName: String, extractLibraryModuleNamesFromIndex: (KSDeclaration) -> List<String>
) = buildList {
resolver.getDeclarationsFromPackage(packageName)
.forEach { index: KSDeclaration ->
val libraryGlideModuleNames = extractLibraryModuleNamesFromIndex(index)
if (libraryGlideModuleNames.isNotEmpty()) {
environment.logger.info(
"Found index annotation: $index with modules: $libraryGlideModuleNames"
)
add(IndexAndLibraryModuleNames(index, libraryGlideModuleNames))
}
}
}

private fun extractGlideModulesFromJavaIndexAnnotation(
index: KSDeclaration,
): List<String> {
val indexAnnotation: KSAnnotation = index.atMostOneJavaIndexAnnotation() ?: return emptyList()
return indexAnnotation.getModuleArgumentValues().toList()
}

private fun extractGlideModulesFromKspIndexAnnotation(
index: KSDeclaration,
): List<String> {
val indexAnnotation: KSAnnotation = index.atMostOneIndexAnnotation() ?: return emptyList()
environment.logger.info("Found index annotation: $indexAnnotation")
val indexAnnotation: KSAnnotation = index.atMostOneKspIndexAnnotation() ?: return emptyList()
return indexAnnotation.getModuleArgumentValues().toList()
}

Expand All @@ -220,25 +255,31 @@ internal class AppGlideModuleParser(
throw InvalidGlideSourceException("Found an invalid internal Glide index: $this")
}

private fun KSDeclaration.atMostOneIndexAnnotation() = atMostOneAnnotation(Index::class)
private fun KSDeclaration.atMostOneJavaIndexAnnotation() =
atMostOneAnnotation("com.bumptech.glide.annotation.compiler.Index")
private fun KSDeclaration.atMostOneKspIndexAnnotation() = atMostOneAnnotation(Index::class)

private fun KSDeclaration.atMostOneExcludesAnnotation() = atMostOneAnnotation(Excludes::class)

private fun KSDeclaration.atMostOneAnnotation(
annotation: KClass<out Annotation>,
): KSAnnotation? = atMostOneAnnotation(annotation.qualifiedName)

private fun KSDeclaration.atMostOneAnnotation(
annotationQualifiedName: String?,
): KSAnnotation? {
val matchingAnnotations: List<KSAnnotation> =
annotations
.filter {
annotation.qualifiedName?.equals(
annotationQualifiedName?.equals(
it.annotationType.resolve().declaration.qualifiedName?.asString()
)
?: false
}
.toList()
if (matchingAnnotations.size > 1) {
throw InvalidGlideSourceException(
"""Expected 0 or 1 $annotation annotations on $qualifiedName, but found:
"""Expected 0 or 1 $annotationQualifiedName annotations on $qualifiedName, but found:
${matchingAnnotations.size}"""
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ object GlideSymbolProcessorConstants {
// This variable is visible only for testing
// TODO(b/174783094): Add @VisibleForTesting when internal is supported.
val PACKAGE_NAME: String = GlideSymbolProcessor::class.java.`package`.name
val JAVA_ANNOTATION_PACKAGE_NAME: String = "com.bumptech.glide.annotation.compiler"
const val SINGLE_APP_MODULE_ERROR = "You can have at most one AppGlideModule, but found: %s"
const val DUPLICATE_LIBRARY_MODULE_ERROR =
"LibraryGlideModules %s are included more than once, keeping only one!"
Expand Down
29 changes: 27 additions & 2 deletions glide/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import com.android.build.gradle.api.LibraryVariant

/**
* This module is used for two things:
* <ul>
* <li>Compiling a single unified set of javadocs for Glide
* <li>Providing a jar version of Glide for internal libraries, like
* Glide's annotation processor.
* </ul>
*
* <p>Previously this module was used to produce a release jar for Glide, but
* we've long since stopped releasing the jar. Now all release artifacts come
* from the upload script, which uploads aars for each production submodule
*/

apply plugin: 'java'

// The paths of Android projects that should be included only in Javadoc, not in the jar.
Expand All @@ -18,6 +31,10 @@ static def getAndroidPathsForJavadoc() {
]
}

static def getAndroidPathsForJar() {
[':library', ':third_party:disklrucache', ':third_party:gif_decoder']
}

// The paths of Java projects that should be included only in Javadoc, not in the jar.
static def getJavaPathsForJavadoc() {
[':annotation']
Expand All @@ -43,8 +60,16 @@ def getAndroidProjectsForJavadoc() {
asProjects(getAndroidPathsForJavadoc())
}

def getAndroidLibraryVariantsForJar() {
getAndroidLibraryVariantsForProjects(asProjects(getAndroidPathsForJar()))
}

def getAndroidLibraryVariantsForJavadoc() {
getAndroidProjectsForJavadoc().collect { project ->
getAndroidLibraryVariantsForProjects(getAndroidProjectsForJavadoc())
}

def getAndroidLibraryVariantsForProjects(projects) {
projects.collect { project ->
project.android.libraryVariants.findAll { type ->
type.buildType.name.equalsIgnoreCase("release")
}
Expand Down Expand Up @@ -114,7 +139,7 @@ javadocJarTask.dependsOn(javadocTask)

jar {
from files(
getAndroidLibraryVariantsForJavadoc().collect { LibraryVariant variant ->
getAndroidLibraryVariantsForJar().collect { LibraryVariant variant ->
variant.getJavaCompileProvider().get().destinationDirectory
}
)
Expand Down

0 comments on commit 902bbd4

Please sign in to comment.