<lambda>null1 package com.android.onboarding.versions.change_collector
2 
3 import com.android.onboarding.versions.annotations.BreakingReason
4 import com.android.onboarding.versions.annotations.ChangeId
5 import com.android.onboarding.versions.annotations.ChangeId.Companion.generateChangeIdCode
6 import com.android.onboarding.versions.annotations.ChangeRadius
7 import com.android.onboarding.versions.annotations.ExpeditedReason
8 import com.google.auto.service.AutoService
9 import com.squareup.kotlinpoet.ClassName
10 import com.squareup.kotlinpoet.CodeBlock
11 import com.squareup.kotlinpoet.FileSpec
12 import java.io.IOException
13 import java.io.PrintWriter
14 import javax.annotation.processing.AbstractProcessor
15 import javax.annotation.processing.RoundEnvironment
16 import javax.annotation.processing.SupportedAnnotationTypes
17 import javax.lang.model.SourceVersion
18 import javax.lang.model.element.TypeElement
19 import javax.tools.StandardLocation
20 
21 @SupportedAnnotationTypes("com.android.onboarding.versions.annotations.ChangeId")
22 @AutoService(javax.annotation.processing.Processor::class)
23 /**
24  * Annotation processor which collects all @ChangeId annotations and indexes them in a fixed map.
25  *
26  * The map is called [com.android.onboarding.versions.changes.ALL_CHANGE_IDS], as has a (Long) key
27  * of the bugId, with the value being the [ChangeId] itself.
28  */
29 class ChangeCollector : AbstractProcessor() {
30   override fun getSupportedSourceVersion(): SourceVersion = SourceVersion.latest()
31 
32   private val changeIds = mutableListOf<ChangeId>()
33 
34   override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
35     val annotatedIds = roundEnv.getElementsAnnotatedWith(ChangeId::class.java)
36     for (annotatedId in annotatedIds) {
37       changeIds.add(annotatedId.getAnnotation(ChangeId::class.java))
38     }
39 
40     if (roundEnv.processingOver()) {
41       val changesClass = ClassName("com.android.onboarding.versions.changes", "AllChanges")
42 
43       val fileBuilder =
44         FileSpec.scriptBuilder(
45           "com.android.onboarding.versions.changes.AllChanges",
46           "com.android.onboarding.versions.changes",
47         )
48 
49       fileBuilder.addImport(
50         ChangeRadius::class.qualifiedName!!,
51         ChangeRadius.entries.map { it.name }.toList(),
52       )
53       fileBuilder.addImport(
54         ExpeditedReason::class.qualifiedName!!,
55         ExpeditedReason.entries.map { it.name }.toList(),
56       )
57       fileBuilder.addImport(
58         BreakingReason::class.qualifiedName!!,
59         BreakingReason.entries.map { it.name }.toList(),
60       )
61       fileBuilder.addImport(ChangeId::class.java.packageName, ChangeId::class.java.simpleName)
62 
63       val file =
64         fileBuilder
65           .addCode(
66             CodeBlock.builder()
67               .add(
68                 "val ALL_CHANGE_IDS = mapOf(" +
69                   changeIds
70                     .map { "${it.bugId}L to ${generateChangeIdCode(it)}" }
71                     .joinToString(",\n") +
72                   ")"
73               )
74               .build()
75           )
76           .build()
77 
78       try {
79         val builderFile =
80           processingEnv.filer.createResource(
81             StandardLocation.SOURCE_OUTPUT,
82             changesClass.packageName,
83             "${changesClass.simpleName}.kt",
84           )
85         PrintWriter(builderFile.openWriter()).use { out -> file.writeTo(out) }
86       } catch (e: IOException) {
87         throw java.lang.IllegalStateException("Error writing change map to file", e)
88       }
89     }
90     return false
91   }
92 }
93