-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
delay @ContributesSubcomponent
generation until the last analysis rounds
#946
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,10 +89,10 @@ internal class CodeGenerationExtension( | |
|
||
// Either sync the local file state with our internal cache, | ||
// or delete any existing generated files (if caching isn't enabled). | ||
val createdChanges = syncGeneratedDir(files) | ||
val syncCreatedChanges = syncGeneratedDir(files) | ||
didSyncGeneratedDir = true | ||
|
||
if (createdChanges) { | ||
if (syncCreatedChanges) { | ||
// Tell the compiler to analyze the generated files *before* calling `analysisCompleted()`. | ||
// This ensures that the compiler will update/delete any references to stale code in the | ||
// ModuleDescriptor, as well as updating/deleting any stale .class files. | ||
|
@@ -118,10 +118,8 @@ internal class CodeGenerationExtension( | |
anvilModule.addFiles(files) | ||
|
||
val generatedFiles = generateCode( | ||
codeGenerators = codeGenerators, | ||
psiManager = psiManager, | ||
anvilModule = anvilModule, | ||
files = files, | ||
) | ||
|
||
if (trackSourceFiles) { | ||
|
@@ -189,10 +187,8 @@ internal class CodeGenerationExtension( | |
} | ||
|
||
private fun generateCode( | ||
codeGenerators: List<CodeGenerator>, | ||
psiManager: PsiManager, | ||
anvilModule: RealAnvilModuleDescriptor, | ||
files: Collection<KtFile>, | ||
): MutableCollection<FileWithContent> { | ||
|
||
val anvilContext = commandLineOptions.toAnvilContext(anvilModule) | ||
|
@@ -227,47 +223,56 @@ internal class CodeGenerationExtension( | |
} | ||
} | ||
|
||
fun Collection<CodeGenerator>.generateCode(files: Collection<KtFile>): List<KtFile> = | ||
fun Collection<CodeGenerator>.generateAndCache(files: Collection<KtFile>): List<KtFile> = | ||
flatMap { codeGenerator -> | ||
codeGenerator.generateCode(generatedDir, anvilModule, files) | ||
.onEach { file -> | ||
onGenerated( | ||
generatedFile = file, | ||
codeGenerator = codeGenerator, | ||
allowOverwrites = false, | ||
) | ||
} | ||
.toKtFiles(psiManager, anvilModule) | ||
} | ||
|
||
fun Collection<FlushingCodeGenerator>.flush(): List<KtFile> = | ||
flatMap { codeGenerator -> | ||
codeGenerator.flush(generatedDir, anvilModule) | ||
.onEach { | ||
onGenerated( | ||
generatedFile = it, | ||
codeGenerator = codeGenerator, | ||
allowOverwrites = false, | ||
// flushing code generators write the files but no content during normal rounds. | ||
allowOverwrites = true, | ||
) | ||
} | ||
.toKtFiles(psiManager, anvilModule) | ||
} | ||
|
||
fun Collection<CodeGenerator>.flush(): List<KtFile> = | ||
filterIsInstance<FlushingCodeGenerator>() | ||
.flatMap { codeGenerator -> | ||
codeGenerator.flush(generatedDir, anvilModule) | ||
.onEach { | ||
onGenerated( | ||
generatedFile = it, | ||
codeGenerator = codeGenerator, | ||
// flushing code generators write the files but no content during normal rounds. | ||
allowOverwrites = true, | ||
) | ||
} | ||
.toKtFiles(psiManager, anvilModule) | ||
} | ||
|
||
var newFiles = nonPrivateCodeGenerators.generateCode(files) | ||
|
||
while (newFiles.isNotEmpty()) { | ||
// Parse the KtFile for each generated file. Then feed the code generators with the new | ||
// parsed files until no new files are generated. | ||
newFiles = nonPrivateCodeGenerators.generateCode(newFiles) | ||
fun List<CodeGenerator>.loopGeneration() { | ||
var newFiles = generateAndCache(anvilModule.allFiles.toList()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Previously |
||
while (newFiles.isNotEmpty()) { | ||
// Parse the KtFile for each generated file. Then feed the code generators with the new | ||
// parsed files until no new files are generated. | ||
newFiles = generateAndCache(newFiles) | ||
} | ||
} | ||
|
||
nonPrivateCodeGenerators.flush() | ||
// All non-private code generators are batched together. | ||
// They will execute against the initial set of files, | ||
// then loop until no generator produces any new files. | ||
nonPrivateCodeGenerators.loopGeneration() | ||
|
||
// Flushing generators are next. | ||
// They have already seen all generated code. | ||
// Their output may be consumed by a private generator. | ||
codeGenerators.filterIsInstance<FlushingCodeGenerator>().flush() | ||
|
||
// PrivateCodeGenerators don't impact other code generators. Therefore, they can be called a | ||
// single time at the end. | ||
privateCodeGenerators.generateCode(anvilModule.allFiles.toList()) | ||
// Private generators do not affect each other, so they're invoked last. | ||
// They may require multiple iterations of their own logic, though, | ||
// so we loop them individually until there are no more changes. | ||
privateCodeGenerators.forEach { listOf(it).loopGeneration() } | ||
|
||
return generatedFiles.values | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just class-level, so no need to pass the variable around internally.