Unify processing of removed files for JS and JVM IC
This commit is contained in:
@@ -28,18 +28,20 @@ import java.io.File
|
|||||||
/**
|
/**
|
||||||
* Incremental cache common for JVM and JS
|
* Incremental cache common for JVM and JS
|
||||||
*/
|
*/
|
||||||
abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) {
|
abstract class IncrementalCacheCommon<ClassName>(workingDir: File) : BasicMapsOwner(workingDir) {
|
||||||
companion object {
|
companion object {
|
||||||
private val SUBTYPES = "subtypes"
|
private val SUBTYPES = "subtypes"
|
||||||
private val SUPERTYPES = "supertypes"
|
private val SUPERTYPES = "supertypes"
|
||||||
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
private val CLASS_FQ_NAME_TO_SOURCE = "class-fq-name-to-source"
|
||||||
|
@JvmStatic protected val SOURCE_TO_CLASSES = "source-to-classes"
|
||||||
|
@JvmStatic protected val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val dependents = arrayListOf<IncrementalCacheCommon>()
|
private val dependents = arrayListOf<IncrementalCacheCommon<ClassName>>()
|
||||||
fun addDependentCache(cache: IncrementalCacheCommon) {
|
fun addDependentCache(cache: IncrementalCacheCommon<ClassName>) {
|
||||||
dependents.add(cache)
|
dependents.add(cache)
|
||||||
}
|
}
|
||||||
val thisWithDependentCaches: Iterable<IncrementalCacheCommon> by lazy {
|
val thisWithDependentCaches: Iterable<IncrementalCacheCommon<ClassName>> by lazy {
|
||||||
val result = arrayListOf(this)
|
val result = arrayListOf(this)
|
||||||
result.addAll(dependents)
|
result.addAll(dependents)
|
||||||
result
|
result
|
||||||
@@ -48,6 +50,8 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
|||||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
||||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
||||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile))
|
||||||
|
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||||
|
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||||
|
|
||||||
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||||
subtypesMap[className].asSequence()
|
subtypesMap[className].asSequence()
|
||||||
@@ -55,7 +59,16 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
|||||||
fun getSourceFileIfClass(fqName: FqName): File? =
|
fun getSourceFileIfClass(fqName: FqName): File? =
|
||||||
classFqNameToSourceMap[fqName]
|
classFqNameToSourceMap[fqName]
|
||||||
|
|
||||||
abstract fun markDirty(removedAndCompiledSources: List<File>)
|
open fun markDirty(removedAndCompiledSources: List<File>) {
|
||||||
|
for (sourceFile in removedAndCompiledSources) {
|
||||||
|
val classes = sourceToClassesMap[sourceFile]
|
||||||
|
classes.forEach {
|
||||||
|
dirtyOutputClassesMap.markDirty(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
protected fun addToClassStorage(proto: ProtoBuf.Class, nameResolver: NameResolver, srcFile: File) {
|
||||||
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
val supertypes = proto.supertypes(TypeTable(proto.typeTable))
|
||||||
@@ -73,6 +86,8 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working
|
|||||||
classFqNameToSourceMap[child] = srcFile
|
classFqNameToSourceMap[child] = srcFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun clearCacheForRemovedClasses(changesCollector: ChangesCollector)
|
||||||
|
|
||||||
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>) {
|
protected fun removeAllFromClassStorage(removedClasses: Collection<FqName>) {
|
||||||
if (removedClasses.isEmpty()) return
|
if (removedClasses.isEmpty()) return
|
||||||
|
|
||||||
|
|||||||
@@ -31,19 +31,20 @@ import java.io.DataInput
|
|||||||
import java.io.DataOutput
|
import java.io.DataOutput
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDir) {
|
open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon<FqName>(cachesDir) {
|
||||||
companion object {
|
companion object {
|
||||||
private val TRANSLATION_RESULT_MAP = "translation-result"
|
private val TRANSLATION_RESULT_MAP = "translation-result"
|
||||||
private val SOURCES_TO_CLASSES_FQNS = "sources-to-classes"
|
|
||||||
private val INLINE_FUNCTIONS = "inline-functions"
|
private val INLINE_FUNCTIONS = "inline-functions"
|
||||||
private val HEADER_FILE_NAME = "header.meta"
|
private val HEADER_FILE_NAME = "header.meta"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val dirtySources = arrayListOf<File>()
|
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile))
|
||||||
|
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||||
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile))
|
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile))
|
||||||
private val sourcesToClasses = registerMap(SourceToClassesMap(SOURCES_TO_CLASSES_FQNS.storageFile))
|
|
||||||
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||||
|
|
||||||
|
private val dirtySources = hashSetOf<File>()
|
||||||
|
|
||||||
private val headerFile: File
|
private val headerFile: File
|
||||||
get() = File(cachesDir, HEADER_FILE_NAME)
|
get() = File(cachesDir, HEADER_FILE_NAME)
|
||||||
|
|
||||||
@@ -55,30 +56,23 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
override fun markDirty(removedAndCompiledSources: List<File>) {
|
||||||
|
super.markDirty(removedAndCompiledSources)
|
||||||
dirtySources.addAll(removedAndCompiledSources)
|
dirtySources.addAll(removedAndCompiledSources)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
|
fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) {
|
||||||
val translatedFiles = incrementalResults.packageParts
|
val translatedFiles = incrementalResults.packageParts
|
||||||
|
|
||||||
dirtySources.forEach {
|
|
||||||
if (it !in translatedFiles) {
|
|
||||||
translationResults.remove(it, changesCollector)
|
|
||||||
inlineFunctions.remove(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeAllFromClassStorage(sourcesToClasses[it])
|
|
||||||
sourcesToClasses.clearOutputsForSource(it)
|
|
||||||
}
|
|
||||||
dirtySources.clear()
|
|
||||||
|
|
||||||
for ((srcFile, data) in translatedFiles) {
|
for ((srcFile, data) in translatedFiles) {
|
||||||
|
dirtySources.remove(srcFile)
|
||||||
val (binaryMetadata, binaryAst) = data
|
val (binaryMetadata, binaryAst) = data
|
||||||
|
|
||||||
val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap()
|
val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap()
|
||||||
val newProtoMap = getProtoData(srcFile, binaryMetadata)
|
val newProtoMap = getProtoData(srcFile, binaryMetadata)
|
||||||
|
|
||||||
for (protoData in newProtoMap.values) {
|
for ((classId, protoData) in newProtoMap) {
|
||||||
|
registerOutputForFile(srcFile, classId.asSingleFqName())
|
||||||
|
|
||||||
if (protoData is ClassProtoData) {
|
if (protoData is ClassProtoData) {
|
||||||
addToClassStorage(protoData.proto, protoData.nameResolver, srcFile)
|
addToClassStorage(protoData.proto, protoData.nameResolver, srcFile)
|
||||||
}
|
}
|
||||||
@@ -96,6 +90,21 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun registerOutputForFile(srcFile: File, name: FqName) {
|
||||||
|
sourceToClassesMap.add(srcFile, name)
|
||||||
|
dirtyOutputClassesMap.notDirty(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||||
|
dirtySources.forEach {
|
||||||
|
translationResults.remove(it, changesCollector)
|
||||||
|
inlineFunctions.remove(it)
|
||||||
|
}
|
||||||
|
removeAllFromClassStorage(dirtyOutputClassesMap.getDirtyOutputClasses())
|
||||||
|
dirtySources.clear()
|
||||||
|
dirtyOutputClassesMap.clean()
|
||||||
|
}
|
||||||
|
|
||||||
fun nonDirtyPackageParts(): Map<File, TranslationResultValue> =
|
fun nonDirtyPackageParts(): Map<File, TranslationResultValue> =
|
||||||
hashMapOf<File, TranslationResultValue>().apply {
|
hashMapOf<File, TranslationResultValue>().apply {
|
||||||
for (path in translationResults.keys()) {
|
for (path in translationResults.keys()) {
|
||||||
@@ -107,25 +116,6 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
|
||||||
fun clearOutputsForSource(sourceFile: File) {
|
|
||||||
remove(sourceFile.canonicalPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(sourceFile: File, className: FqName) {
|
|
||||||
storage.append(sourceFile.canonicalPath, className.asString())
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun get(sourceFile: File): Collection<FqName> =
|
|
||||||
storage[sourceFile.canonicalPath].orEmpty().map { FqName(it) }
|
|
||||||
|
|
||||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
|
||||||
|
|
||||||
private fun remove(path: String) {
|
|
||||||
storage.remove(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
private object TranslationResultValueExternalizer : DataExternalizer<TranslationResultValue> {
|
||||||
override fun save(output: DataOutput, value: TranslationResultValue) {
|
override fun save(output: DataOutput, value: TranslationResultValue) {
|
||||||
output.writeInt(value.metadata.size)
|
output.writeInt(value.metadata.size)
|
||||||
|
|||||||
@@ -44,15 +44,13 @@ val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
|||||||
open class IncrementalJvmCache(
|
open class IncrementalJvmCache(
|
||||||
private val targetDataRoot: File,
|
private val targetDataRoot: File,
|
||||||
targetOutputDir: File?
|
targetOutputDir: File?
|
||||||
) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
) : IncrementalCacheCommon<JvmClassName>(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache {
|
||||||
companion object {
|
companion object {
|
||||||
private val PROTO_MAP = "proto"
|
private val PROTO_MAP = "proto"
|
||||||
private val CONSTANTS_MAP = "constants"
|
private val CONSTANTS_MAP = "constants"
|
||||||
private val PACKAGE_PARTS = "package-parts"
|
private val PACKAGE_PARTS = "package-parts"
|
||||||
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
|
private val MULTIFILE_CLASS_FACADES = "multifile-class-facades"
|
||||||
private val MULTIFILE_CLASS_PARTS = "multifile-class-parts"
|
private val MULTIFILE_CLASS_PARTS = "multifile-class-parts"
|
||||||
private val SOURCE_TO_CLASSES = "source-to-classes"
|
|
||||||
private val DIRTY_OUTPUT_CLASSES = "dirty-output-classes"
|
|
||||||
private val INLINE_FUNCTIONS = "inline-functions"
|
private val INLINE_FUNCTIONS = "inline-functions"
|
||||||
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
|
private val INTERNAL_NAME_TO_SOURCE = "internal-name-to-source"
|
||||||
private val JAVA_SOURCES_PROTO_MAP = "java-sources-proto-map"
|
private val JAVA_SOURCES_PROTO_MAP = "java-sources-proto-map"
|
||||||
@@ -60,13 +58,14 @@ open class IncrementalJvmCache(
|
|||||||
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
private val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val sourceToClassesMap = registerMap(SourceToJvmNameMap(SOURCE_TO_CLASSES.storageFile))
|
||||||
|
override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
||||||
|
|
||||||
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
||||||
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
||||||
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
||||||
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
||||||
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
||||||
private val sourceToClassesMap = registerMap(SourceToClassesMap(SOURCE_TO_CLASSES.storageFile))
|
|
||||||
private val dirtyOutputClassesMap = registerMap(DirtyOutputClassesMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
|
||||||
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
||||||
// todo: try to use internal names only?
|
// todo: try to use internal names only?
|
||||||
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
|
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile))
|
||||||
@@ -76,17 +75,6 @@ open class IncrementalJvmCache(
|
|||||||
|
|
||||||
protected open fun debugLog(message: String) {}
|
protected open fun debugLog(message: String) {}
|
||||||
|
|
||||||
override fun markDirty(removedAndCompiledSources: List<File>) {
|
|
||||||
for (sourceFile in removedAndCompiledSources) {
|
|
||||||
val classes = sourceToClassesMap[sourceFile]
|
|
||||||
classes.forEach {
|
|
||||||
dirtyOutputClassesMap.markDirty(it.internalName)
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceToClassesMap.clearOutputsForSource(sourceFile)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isTrackedFile(file: File) = sourceToClassesMap.contains(file)
|
fun isTrackedFile(file: File) = sourceToClassesMap.contains(file)
|
||||||
|
|
||||||
// used in gradle
|
// used in gradle
|
||||||
@@ -98,7 +86,7 @@ open class IncrementalJvmCache(
|
|||||||
internalNameToSource[internalName]
|
internalNameToSource[internalName]
|
||||||
|
|
||||||
fun isMultifileFacade(className: JvmClassName): Boolean =
|
fun isMultifileFacade(className: JvmClassName): Boolean =
|
||||||
className.internalName in multifileFacadeToParts
|
className in multifileFacadeToParts
|
||||||
|
|
||||||
override fun getClassFilePath(internalClassName: String): String {
|
override fun getClassFilePath(internalClassName: String): String {
|
||||||
return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath)
|
return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath)
|
||||||
@@ -107,7 +95,7 @@ open class IncrementalJvmCache(
|
|||||||
fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File) {
|
fun saveModuleMappingToCache(sourceFiles: Collection<File>, file: File) {
|
||||||
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)
|
||||||
protoMap.storeModuleMapping(jvmClassName, file.readBytes())
|
protoMap.storeModuleMapping(jvmClassName, file.readBytes())
|
||||||
dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME)
|
dirtyOutputClassesMap.notDirty(jvmClassName)
|
||||||
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +104,7 @@ open class IncrementalJvmCache(
|
|||||||
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
|
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
|
||||||
val className = kotlinClass.className
|
val className = kotlinClass.className
|
||||||
|
|
||||||
dirtyOutputClassesMap.notDirty(className.internalName)
|
dirtyOutputClassesMap.notDirty(className)
|
||||||
sourceFiles.forEach {
|
sourceFiles.forEach {
|
||||||
sourceToClassesMap.add(it, className)
|
sourceToClassesMap.add(it, className)
|
||||||
}
|
}
|
||||||
@@ -181,7 +169,7 @@ open class IncrementalJvmCache(
|
|||||||
val (proto, nameResolver) = serializedJavaClass.toProtoData()
|
val (proto, nameResolver) = serializedJavaClass.toProtoData()
|
||||||
addToClassStorage(proto, nameResolver, source)
|
addToClassStorage(proto, nameResolver, source)
|
||||||
|
|
||||||
dirtyOutputClassesMap.notDirty(jvmClassName.internalName)
|
dirtyOutputClassesMap.notDirty(jvmClassName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getObsoleteJavaClasses(): Collection<ClassId> =
|
fun getObsoleteJavaClasses(): Collection<ClassId> =
|
||||||
@@ -192,31 +180,28 @@ open class IncrementalJvmCache(
|
|||||||
|
|
||||||
fun isJavaClassToTrack(classId: ClassId): Boolean {
|
fun isJavaClassToTrack(classId: ClassId): Boolean {
|
||||||
val jvmClassName = JvmClassName.byClassId(classId)
|
val jvmClassName = JvmClassName.byClassId(classId)
|
||||||
return dirtyOutputClassesMap.isDirty(jvmClassName.internalName) ||
|
return dirtyOutputClassesMap.isDirty(jvmClassName) ||
|
||||||
javaSourcesProtoMap[jvmClassName.internalName] == null
|
jvmClassName !in javaSourcesProtoMap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isJavaClassAlreadyInCache(classId: ClassId): Boolean {
|
fun isJavaClassAlreadyInCache(classId: ClassId): Boolean {
|
||||||
val jvmClassName = JvmClassName.byClassId(classId)
|
val jvmClassName = JvmClassName.byClassId(classId)
|
||||||
return javaSourcesProtoMap[jvmClassName.internalName] != null
|
return jvmClassName in javaSourcesProtoMap
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) {
|
||||||
val dirtyClasses = dirtyOutputClassesMap
|
val dirtyClasses = dirtyOutputClassesMap.getDirtyOutputClasses()
|
||||||
.getDirtyOutputClasses()
|
|
||||||
.map(JvmClassName::byInternalName)
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
|
val facadesWithRemovedParts = hashMapOf<JvmClassName, MutableSet<String>>()
|
||||||
for (dirtyClass in dirtyClasses) {
|
for (dirtyClass in dirtyClasses) {
|
||||||
val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue
|
val facade = partToMultifileFacade.get(dirtyClass) ?: continue
|
||||||
val facadeClassName = JvmClassName.byInternalName(facade)
|
val facadeClassName = JvmClassName.byInternalName(facade)
|
||||||
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
|
val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() }
|
||||||
removedParts.add(dirtyClass.internalName)
|
removedParts.add(dirtyClass.internalName)
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
|
for ((facade, removedParts) in facadesWithRemovedParts.entries) {
|
||||||
val allParts = multifileFacadeToParts[facade.internalName] ?: continue
|
val allParts = multifileFacadeToParts[facade] ?: continue
|
||||||
val notRemovedParts = allParts.filter { it !in removedParts }
|
val notRemovedParts = allParts.filter { it !in removedParts }
|
||||||
|
|
||||||
if (notRemovedParts.isEmpty()) {
|
if (notRemovedParts.isEmpty()) {
|
||||||
@@ -239,15 +224,13 @@ open class IncrementalJvmCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars })
|
removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars })
|
||||||
|
|
||||||
dirtyOutputClassesMap.clean()
|
dirtyOutputClassesMap.clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getObsoletePackageParts(): Collection<String> {
|
override fun getObsoletePackageParts(): Collection<String> {
|
||||||
val obsoletePackageParts =
|
val obsoletePackageParts = dirtyOutputClassesMap.getDirtyOutputClasses().filter(packagePartMap::isPackagePart)
|
||||||
dirtyOutputClassesMap.getDirtyOutputClasses().filter { packagePartMap.isPackagePart(JvmClassName.byInternalName(it)) }
|
|
||||||
debugLog("Obsolete package parts: $obsoletePackageParts")
|
debugLog("Obsolete package parts: $obsoletePackageParts")
|
||||||
return obsoletePackageParts
|
return obsoletePackageParts.map { it.internalName }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? {
|
override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? {
|
||||||
@@ -267,8 +250,9 @@ open class IncrementalJvmCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
|
override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection<String>? {
|
||||||
val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null
|
val jvmClassName = JvmClassName.byInternalName(facadeInternalName)
|
||||||
return partNames.filter { !dirtyOutputClassesMap.isDirty(it) }
|
val partNames = multifileFacadeToParts[jvmClassName] ?: return null
|
||||||
|
return partNames.filter { !dirtyOutputClassesMap.isDirty(JvmClassName.byInternalName(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getModuleMappingData(): ByteArray? {
|
override fun getModuleMappingData(): ByteArray? {
|
||||||
@@ -351,7 +335,11 @@ open class IncrementalJvmCache(
|
|||||||
changesCollector.collectProtoChanges(oldValue.toProtoData(), newData = null)
|
changesCollector.collectProtoChanges(oldValue.toProtoData(), newData = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(internalName: String) = storage[internalName]
|
operator fun get(className: JvmClassName): SerializedJavaClass? =
|
||||||
|
storage[className.internalName]
|
||||||
|
|
||||||
|
operator fun contains(className: JvmClassName): Boolean =
|
||||||
|
className.internalName in storage
|
||||||
|
|
||||||
override fun dumpValue(value: SerializedJavaClass): String =
|
override fun dumpValue(value: SerializedJavaClass): String =
|
||||||
java.lang.Long.toHexString(value.proto.toByteArray().md5())
|
java.lang.Long.toHexString(value.proto.toByteArray().md5())
|
||||||
@@ -419,13 +407,15 @@ open class IncrementalJvmCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
||||||
operator fun set(facadeName: JvmClassName, partNames: Collection<String>) {
|
operator fun set(className: JvmClassName, partNames: Collection<String>) {
|
||||||
storage[facadeName.internalName] = partNames
|
storage[className.internalName] = partNames
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(internalName: String): Collection<String>? = storage[internalName]
|
operator fun get(className: JvmClassName): Collection<String>? =
|
||||||
|
storage[className.internalName]
|
||||||
|
|
||||||
operator fun contains(internalName: String): Boolean = internalName in storage
|
operator fun contains(className: JvmClassName): Boolean =
|
||||||
|
className.internalName in storage
|
||||||
|
|
||||||
fun remove(className: JvmClassName) {
|
fun remove(className: JvmClassName) {
|
||||||
storage.remove(className.internalName)
|
storage.remove(className.internalName)
|
||||||
@@ -439,9 +429,8 @@ open class IncrementalJvmCache(
|
|||||||
storage[partName] = facadeName
|
storage[partName] = facadeName
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(partName: String): String? {
|
fun get(partName: JvmClassName): String? =
|
||||||
return storage.get(partName)
|
storage[partName.internalName]
|
||||||
}
|
|
||||||
|
|
||||||
fun remove(className: JvmClassName) {
|
fun remove(className: JvmClassName) {
|
||||||
storage.remove(className.internalName)
|
storage.remove(className.internalName)
|
||||||
@@ -450,27 +439,6 @@ open class IncrementalJvmCache(
|
|||||||
override fun dumpValue(value: String): String = value
|
override fun dumpValue(value: String): String = value
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class SourceToClassesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
|
||||||
fun clearOutputsForSource(sourceFile: File) {
|
|
||||||
remove(sourceFile.absolutePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun add(sourceFile: File, className: JvmClassName) {
|
|
||||||
storage.append(sourceFile.absolutePath, className.internalName)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contains(sourceFile: File) = sourceFile.absolutePath in storage
|
|
||||||
|
|
||||||
operator fun get(sourceFile: File): Collection<JvmClassName> =
|
|
||||||
storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) }
|
|
||||||
|
|
||||||
override fun dumpValue(value: Collection<String>) = value.dumpCollection()
|
|
||||||
|
|
||||||
private fun remove(path: String) {
|
|
||||||
storage.remove(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
||||||
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
|
operator fun set(internalName: String, sourceFiles: Iterable<File>) {
|
||||||
storage[internalName] = sourceFiles.map { it.canonicalPath }
|
storage[internalName] = sourceFiles.map { it.canonicalPath }
|
||||||
@@ -492,24 +460,6 @@ open class IncrementalJvmCache(
|
|||||||
addToClassStorage(proto, nameResolver, srcFile)
|
addToClassStorage(proto, nameResolver, srcFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
|
||||||
fun markDirty(className: String) {
|
|
||||||
storage[className] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun notDirty(className: String) {
|
|
||||||
storage.remove(className)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDirtyOutputClasses(): Collection<String> =
|
|
||||||
storage.keys
|
|
||||||
|
|
||||||
fun isDirty(className: String): Boolean =
|
|
||||||
storage.contains(className)
|
|
||||||
|
|
||||||
override fun dumpValue(value: Boolean) = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||||
private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map<String, Long> {
|
private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map<String, Long> {
|
||||||
val inlineFunctions = inlineFunctionsJvmNames(header)
|
val inlineFunctions = inlineFunctionsJvmNames(header)
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ data class DirtyData(
|
|||||||
)
|
)
|
||||||
|
|
||||||
fun ChangesCollector.getDirtyData(
|
fun ChangesCollector.getDirtyData(
|
||||||
caches: Iterable<IncrementalCacheCommon>,
|
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||||
reporter: ICReporter
|
reporter: ICReporter
|
||||||
): DirtyData {
|
): DirtyData {
|
||||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||||
@@ -170,7 +170,7 @@ fun mapLookupSymbolsToFiles(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun mapClassesFqNamesToFiles(
|
fun mapClassesFqNamesToFiles(
|
||||||
caches: Iterable<IncrementalCacheCommon>,
|
caches: Iterable<IncrementalCacheCommon<*>>,
|
||||||
classesFqNames: Iterable<FqName>,
|
classesFqNames: Iterable<FqName>,
|
||||||
reporter: ICReporter,
|
reporter: ICReporter,
|
||||||
excludes: Set<File> = emptySet()
|
excludes: Set<File> = emptySet()
|
||||||
@@ -192,7 +192,7 @@ fun mapClassesFqNamesToFiles(
|
|||||||
|
|
||||||
fun withSubtypes(
|
fun withSubtypes(
|
||||||
typeFqName: FqName,
|
typeFqName: FqName,
|
||||||
caches: Iterable<IncrementalCacheCommon>
|
caches: Iterable<IncrementalCacheCommon<*>>
|
||||||
): Set<FqName> {
|
): Set<FqName> {
|
||||||
val types = LinkedList(listOf(typeFqName))
|
val types = LinkedList(listOf(typeFqName))
|
||||||
val subtypes = hashSetOf<FqName>()
|
val subtypes = hashSetOf<FqName>()
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import com.intellij.util.io.BooleanDataDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class DirtyClassesJvmNameMap(storageFile: File) : AbstractDirtyClassesMap<JvmClassName>(JvmClassNameTransformer, storageFile)
|
||||||
|
internal class DirtyClassesFqNameMap(storageFile: File) : AbstractDirtyClassesMap<FqName>(FqNameTransformer, storageFile)
|
||||||
|
|
||||||
|
internal abstract class AbstractDirtyClassesMap<Name>(
|
||||||
|
private val nameTransformer: NameTransformer<Name>,
|
||||||
|
storageFile: File
|
||||||
|
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
||||||
|
fun markDirty(className: Name) {
|
||||||
|
storage[nameTransformer.asString(className)] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun notDirty(className: Name) {
|
||||||
|
storage.remove(nameTransformer.asString(className))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDirtyOutputClasses(): Collection<Name> =
|
||||||
|
storage.keys.map { nameTransformer.asName(it) }
|
||||||
|
|
||||||
|
fun isDirty(className: Name): Boolean =
|
||||||
|
storage.contains(nameTransformer.asString(className))
|
||||||
|
|
||||||
|
override fun dumpValue(value: Boolean) = ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
|
||||||
|
internal interface NameTransformer<Name> {
|
||||||
|
fun asString(name: Name): String
|
||||||
|
fun asName(string: String): Name
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object FqNameTransformer : NameTransformer<FqName> {
|
||||||
|
override fun asString(name: FqName): String =
|
||||||
|
name.asString()
|
||||||
|
|
||||||
|
override fun asName(string: String): FqName =
|
||||||
|
FqName(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object JvmClassNameTransformer : NameTransformer<JvmClassName> {
|
||||||
|
override fun asString(name: JvmClassName): String =
|
||||||
|
name.internalName
|
||||||
|
|
||||||
|
override fun asName(string: String): JvmClassName =
|
||||||
|
JvmClassName.byInternalName(string)
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class SourceToJvmNameMap(storageFile: File) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile)
|
||||||
|
internal class SourceToFqNameMap(storageFile: File) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile)
|
||||||
|
|
||||||
|
internal abstract class AbstractSourceToOutputMap<Name>(
|
||||||
|
private val nameTransformer: NameTransformer<Name>,
|
||||||
|
storageFile: File
|
||||||
|
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||||
|
fun clearOutputsForSource(sourceFile: File) {
|
||||||
|
remove(sourceFile.absolutePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(sourceFile: File, className: Name) {
|
||||||
|
storage.append(sourceFile.absolutePath, nameTransformer.asString(className))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun contains(sourceFile: File): Boolean =
|
||||||
|
sourceFile.absolutePath in storage
|
||||||
|
|
||||||
|
operator fun get(sourceFile: File): Collection<Name> =
|
||||||
|
storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asName)
|
||||||
|
|
||||||
|
override fun dumpValue(value: Collection<String>) =
|
||||||
|
value.dumpCollection()
|
||||||
|
|
||||||
|
private fun remove(path: String) {
|
||||||
|
storage.remove(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental
|
|||||||
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class IncrementalCachesManager<PlatformCache : IncrementalCacheCommon>(
|
abstract class IncrementalCachesManager<PlatformCache : IncrementalCacheCommon<*>>(
|
||||||
protected val cachesRootDir: File,
|
protected val cachesRootDir: File,
|
||||||
protected val reporter: ICReporter
|
protected val reporter: ICReporter
|
||||||
) {
|
) {
|
||||||
|
|||||||
+2
-1
@@ -121,7 +121,8 @@ class IncrementalJsCompilerRunner(
|
|||||||
val jsCache = caches.platformCache
|
val jsCache = caches.platformCache
|
||||||
jsCache.header = incrementalResults.headerMetadata
|
jsCache.header = incrementalResults.headerMetadata
|
||||||
|
|
||||||
return jsCache.compareAndUpdate(incrementalResults, changesCollector)
|
jsCache.compareAndUpdate(incrementalResults, changesCollector)
|
||||||
|
jsCache.clearCacheForRemovedClasses(changesCollector)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun runCompiler(
|
override fun runCompiler(
|
||||||
|
|||||||
Reference in New Issue
Block a user