IC: Compute symbols impacted by classpath changes (#5111)

IC: Compute symbols impacted by classpath changes

Incremental compilation has 4 key steps:
  1. Compile changed/impacted files
  2. Detect symbols that have changed after compiling
  3. Detect symbols that are impacted by the changed symbols
  4. Based on the changed-or-impacted symbols, identify files that need
     to be recompiled. Go back to step 1.

Normally, step 2 and 3 are done together when the changed symbols
and impacted symbols are in the same module.

However, if the changed symbols and impacted symbols are in different
modules (e.g., a `Subclass` in lib1 extends a `Superclass` in lib2),
we currently do not compute symbols in the current module that are
impacted by changes in another module (step 3 above).

This is the case for both the new IC and the old IC.

In this commit, we will compute impacted symbols for the new IC. We can
fix the old IC later if necessary (they can't be fixed together easily).

Test: Added BaseIncrementalCompilationMultiProjectIT.testChangeInterfaceInLib
^KT-56197 Fixed
This commit is contained in:
hungvietnguyen
2023-03-21 12:12:15 +00:00
committed by GitHub
parent bb09395952
commit 4f3244fb78
9 changed files with 180 additions and 47 deletions
@@ -34,9 +34,6 @@ import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
import org.jetbrains.kotlin.utils.addToStdlib.flattenTo
import java.io.File
import java.nio.file.Files
import java.util.*
import kotlin.collections.HashSet
import kotlin.collections.LinkedHashSet
const val DELETE_MODULE_FILE_PROPERTY = "kotlin.delete.module.file.after.build"
@@ -143,7 +140,34 @@ data class DirtyData(
val dirtyClassesFqNamesForceRecompile: Collection<FqName> = emptyList()
)
fun ChangesCollector.getDirtyData(
/**
* Returns changed symbols from the changes collected by this [ChangesCollector].
*
* If impacted symbols are also needed, use [getChangedAndImpactedSymbols].
*/
fun ChangesCollector.getChangedSymbols(reporter: ICReporter): DirtyData {
// Caches are used to compute impacted symbols. Set `caches = emptyList()` so that we get changed symbols only, not impacted ones.
return changes().getChangedAndImpactedSymbols(caches = emptyList(), reporter)
}
/**
* Returns changed and impacted symbols from the changes collected by this [ChangesCollector].
*
* For example, if `Subclass` extends `Superclass` and `Superclass` has changed, `Subclass` will be impacted.
*/
fun ChangesCollector.getChangedAndImpactedSymbols(
caches: Iterable<IncrementalCacheCommon>,
reporter: ICReporter
): DirtyData {
return changes().getChangedAndImpactedSymbols(caches, reporter)
}
/**
* Returns changed and impacted symbols from this list of changes.
*
* For example, if `Subclass` extends `Superclass` and `Superclass` has changed, `Subclass` will be impacted.
*/
fun List<ChangeInfo>.getChangedAndImpactedSymbols(
caches: Iterable<IncrementalCacheCommon>,
reporter: ICReporter
): DirtyData {
@@ -152,7 +176,7 @@ fun ChangesCollector.getDirtyData(
val sealedParents = HashSet<FqName>()
for (change in changes()) {
for (change in this) {
reporter.debug { "Process $change" }
if (change is ChangeInfo.SignatureChanged) {