Reuse code from build-common

KT-8487
This commit is contained in:
Alexey Tsvetkov
2016-02-08 16:05:55 +03:00
parent a5e3ca3596
commit f93562299c
5 changed files with 104 additions and 141 deletions
@@ -92,12 +92,11 @@ open class IncrementalCacheImpl<Target>(
private val dependents = arrayListOf<IncrementalCacheImpl<Target>>()
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory: $target" } }
// TODO: review
val dependentsWithThis: Sequence<IncrementalCacheImpl<Target>>
get() = sequenceOf(this).plus(dependents.asSequence())
internal val dependentCaches: Iterable<IncrementalCacheImpl<Target>>
get() = dependents
val thisWithDependentCaches: Iterable<IncrementalCacheImpl<Target>> by lazy {
val result = arrayListOf(this)
result.addAll(dependents)
result
}
override fun registerInline(fromPath: String, jvmSignature: String, toPath: String) {
}
@@ -578,7 +577,7 @@ open class IncrementalCacheImpl<Target>(
val removedFqNames = removedClasses.map { it.fqNameForClassNameWithoutDollars }.toSet()
for (cache in dependentsWithThis) {
for (cache in thisWithDependentCaches) {
val parentsFqNames = hashSetOf<FqName>()
val childrenFqNames = hashSetOf<FqName>()
@@ -174,36 +174,94 @@ fun<Target> OutputItemsCollectorImpl.generatedFiles(
}
}
fun<Target> CompilationResult.dirtyLookups(
caches: Sequence<IncrementalCacheImpl<TargetId>>
): Iterable<LookupSymbol> =
changes.asIterable().flatMap { change ->
when (change) {
is ChangeInfo.SignatureChanged -> {
val fqNames = if (!change.areSubclassesAffected) listOf(change.fqName) else withSubtypes(change.fqName, caches)
fqNames.map {
val scope = it.parent().asString()
val name = it.shortName().identifier
LookupSymbol(name, scope)
}
}
is ChangeInfo.MembersChanged -> {
val scopes = withSubtypes(change.fqName, caches).map { it.asString() }
change.names.flatMap { name -> scopes.map { scope -> LookupSymbol(name, scope) } }
}
else -> listOf<LookupSymbol>()
data class DirtyData(
val dirtyLookupSymbols: Iterable<LookupSymbol>,
val dirtyClassesFqNames: Iterable<FqName>
)
fun <Target> CompilationResult.getDirtyData(
caches: Iterable<IncrementalCacheImpl<Target>>,
log: (String)->Unit
): DirtyData {
val dirtyLookupSymbols = HashSet<LookupSymbol>()
val dirtyClassesFqNames = HashSet<FqName>()
for (change in changes) {
log("Process $change")
if (change is ChangeInfo.SignatureChanged) {
val fqNames = if (!change.areSubclassesAffected) listOf(change.fqName) else withSubtypes(change.fqName, caches)
for (classFqName in fqNames) {
assert(!classFqName.isRoot) { "$classFqName is root when processing $change" }
val scope = classFqName.parent().asString()
val name = classFqName.shortName().identifier
dirtyLookupSymbols.add(LookupSymbol(name, scope))
}
}
else if (change is ChangeInfo.MembersChanged) {
val fqNames = withSubtypes(change.fqName, caches)
// need to recompile subtypes because changed member might break override
dirtyClassesFqNames.addAll(fqNames)
for (name in change.names) {
for (fqName in fqNames) {
dirtyLookupSymbols.add(LookupSymbol(name, fqName.asString()))
}
}
}
}
return DirtyData(dirtyLookupSymbols, dirtyClassesFqNames)
}
fun mapLookupSymbolsToFiles(
lookupStorage: LookupStorage,
lookupSymbols: Iterable<LookupSymbol>,
log: (String)->Unit,
excludes: Set<File> = emptySet()
): Set<File> {
val dirtyFiles = HashSet<File>()
for (lookup in lookupSymbols) {
val affectedFiles = lookupStorage.get(lookup).map(::File).filter { it !in excludes }
log("${lookup.scope}#${lookup.name} caused recompilation of: $affectedFiles")
dirtyFiles.addAll(affectedFiles)
}
return dirtyFiles
}
fun <Target> mapClassesFqNamesToFiles(
caches: Iterable<IncrementalCacheImpl<Target>>,
classesFqNames: Iterable<FqName>,
log: (String)->Unit,
excludes: Set<File> = emptySet()
): Set<File> {
val dirtyFiles = HashSet<File>()
for (cache in caches) {
for (dirtyClassFqName in classesFqNames) {
val srcFile = cache.getSourceFileIfClass(dirtyClassFqName)
if (srcFile == null || srcFile in excludes) continue
log("Class $dirtyClassFqName caused recompilation of: $srcFile")
dirtyFiles.add(srcFile)
}
}
return dirtyFiles
}
private fun File.isJavaFile() = extension.equals(JavaFileType.INSTANCE.defaultExtension, ignoreCase = true)
private fun findSrcDirRoot(file: File, roots: Iterable<File>): File? =
roots.firstOrNull { FileUtil.isAncestor(it, file, false) }
private fun<TargetId> withSubtypes(
private fun <Target> withSubtypes(
typeFqName: FqName,
caches: Sequence<IncrementalCacheImpl<TargetId>>
caches: Iterable<IncrementalCacheImpl<Target>>
): Set<FqName> {
val types = LinkedList(listOf(typeFqName))
val subtypes = hashSetOf<FqName>()
@@ -211,9 +269,10 @@ private fun<TargetId> withSubtypes(
while (types.isNotEmpty()) {
val unprocessedType = types.pollFirst()
caches.flatMap { it.getSubtypesOf(unprocessedType) }
.filter { it !in subtypes }
.forEach { types.addLast(it) }
caches.asSequence()
.flatMap { it.getSubtypesOf(unprocessedType) }
.filter { it !in subtypes }
.forEach { types.addLast(it) }
subtypes.add(unprocessedType)
}