From e8162cd99dc26a5174d5f4f96f26410b78fd1743 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Thu, 7 Dec 2017 03:11:10 +0300 Subject: [PATCH] Unify processing of removed files for JS and JVM IC --- .../incremental/IncrementalCacheCommon.kt | 25 +++- .../kotlin/incremental/IncrementalJsCache.kt | 60 ++++----- .../kotlin/incremental/IncrementalJvmCache.kt | 116 +++++------------- .../jetbrains/kotlin/incremental/buildUtil.kt | 6 +- .../incremental/storage/DirtyClassesMaps.kt | 46 +++++++ .../incremental/storage/NameTransformers.kt | 41 +++++++ .../incremental/storage/SourceToOutputMaps.kt | 51 ++++++++ .../incremental/IncrementalCachesManager.kt | 2 +- .../IncrementalJsCompilerRunner.kt | 3 +- 9 files changed, 222 insertions(+), 128 deletions(-) create mode 100644 build-common/src/org/jetbrains/kotlin/incremental/storage/DirtyClassesMaps.kt create mode 100644 build-common/src/org/jetbrains/kotlin/incremental/storage/NameTransformers.kt create mode 100644 build-common/src/org/jetbrains/kotlin/incremental/storage/SourceToOutputMaps.kt diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheCommon.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheCommon.kt index 6ba659a5103..80327f0c197 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheCommon.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheCommon.kt @@ -28,18 +28,20 @@ import java.io.File /** * Incremental cache common for JVM and JS */ -abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) { +abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(workingDir) { companion object { private val SUBTYPES = "subtypes" private val SUPERTYPES = "supertypes" 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() - fun addDependentCache(cache: IncrementalCacheCommon) { + private val dependents = arrayListOf>() + fun addDependentCache(cache: IncrementalCacheCommon) { dependents.add(cache) } - val thisWithDependentCaches: Iterable by lazy { + val thisWithDependentCaches: Iterable> by lazy { val result = arrayListOf(this) result.addAll(dependents) result @@ -48,6 +50,8 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile)) private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile)) protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile)) + internal abstract val sourceToClassesMap: AbstractSourceToOutputMap + internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap fun getSubtypesOf(className: FqName): Sequence = subtypesMap[className].asSequence() @@ -55,7 +59,16 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working fun getSourceFileIfClass(fqName: FqName): File? = classFqNameToSourceMap[fqName] - abstract fun markDirty(removedAndCompiledSources: List) + open fun markDirty(removedAndCompiledSources: List) { + 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) { val supertypes = proto.supertypes(TypeTable(proto.typeTable)) @@ -73,6 +86,8 @@ abstract class IncrementalCacheCommon(workingDir: File) : BasicMapsOwner(working classFqNameToSourceMap[child] = srcFile } + abstract fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) + protected fun removeAllFromClassStorage(removedClasses: Collection) { if (removedClasses.isEmpty()) return diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt index 09633cc905e..0864dd78d0f 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJsCache.kt @@ -31,19 +31,20 @@ import java.io.DataInput import java.io.DataOutput import java.io.File -open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDir) { +open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDir) { companion object { private val TRANSLATION_RESULT_MAP = "translation-result" - private val SOURCES_TO_CLASSES_FQNS = "sources-to-classes" private val INLINE_FUNCTIONS = "inline-functions" private val HEADER_FILE_NAME = "header.meta" } - private val dirtySources = arrayListOf() + 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 sourcesToClasses = registerMap(SourceToClassesMap(SOURCES_TO_CLASSES_FQNS.storageFile)) private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile)) + private val dirtySources = hashSetOf() + private val headerFile: File get() = File(cachesDir, HEADER_FILE_NAME) @@ -55,30 +56,23 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi } override fun markDirty(removedAndCompiledSources: List) { + super.markDirty(removedAndCompiledSources) dirtySources.addAll(removedAndCompiledSources) } fun compareAndUpdate(incrementalResults: IncrementalResultsConsumerImpl, changesCollector: ChangesCollector) { 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) { + dirtySources.remove(srcFile) val (binaryMetadata, binaryAst) = data val oldProtoMap = translationResults[srcFile]?.metadata?.let { getProtoData(srcFile, it) } ?: emptyMap() val newProtoMap = getProtoData(srcFile, binaryMetadata) - for (protoData in newProtoMap.values) { + for ((classId, protoData) in newProtoMap) { + registerOutputForFile(srcFile, classId.asSingleFqName()) + if (protoData is ClassProtoData) { 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 = hashMapOf().apply { for (path in translationResults.keys()) { @@ -107,25 +116,6 @@ open class IncrementalJsCache(cachesDir: File) : IncrementalCacheCommon(cachesDi } } -private class SourceToClassesMap(storageFile: File) : BasicStringMap>(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 = - storage[sourceFile.canonicalPath].orEmpty().map { FqName(it) } - - override fun dumpValue(value: Collection) = value.dumpCollection() - - private fun remove(path: String) { - storage.remove(path) - } -} - private object TranslationResultValueExternalizer : DataExternalizer { override fun save(output: DataOutput, value: TranslationResultValue) { output.writeInt(value.metadata.size) diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt index faf341c59d5..6d0a8fedf87 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt @@ -44,15 +44,13 @@ val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin" open class IncrementalJvmCache( private val targetDataRoot: File, targetOutputDir: File? -) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache { +) : IncrementalCacheCommon(File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME)), IncrementalCache { companion object { private val PROTO_MAP = "proto" private val CONSTANTS_MAP = "constants" private val PACKAGE_PARTS = "package-parts" private val MULTIFILE_CLASS_FACADES = "multifile-class-facades" 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 INTERNAL_NAME_TO_SOURCE = "internal-name-to-source" 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 } + 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 constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile)) private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile)) private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.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)) // todo: try to use internal names only? private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile)) @@ -76,17 +75,6 @@ open class IncrementalJvmCache( protected open fun debugLog(message: String) {} - override fun markDirty(removedAndCompiledSources: List) { - for (sourceFile in removedAndCompiledSources) { - val classes = sourceToClassesMap[sourceFile] - classes.forEach { - dirtyOutputClassesMap.markDirty(it.internalName) - } - - sourceToClassesMap.clearOutputsForSource(sourceFile) - } - } - fun isTrackedFile(file: File) = sourceToClassesMap.contains(file) // used in gradle @@ -98,7 +86,7 @@ open class IncrementalJvmCache( internalNameToSource[internalName] fun isMultifileFacade(className: JvmClassName): Boolean = - className.internalName in multifileFacadeToParts + className in multifileFacadeToParts override fun getClassFilePath(internalClassName: String): String { return toSystemIndependentName(File(outputDir, "$internalClassName.class").canonicalPath) @@ -107,7 +95,7 @@ open class IncrementalJvmCache( fun saveModuleMappingToCache(sourceFiles: Collection, file: File) { val jvmClassName = JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME) protoMap.storeModuleMapping(jvmClassName, file.readBytes()) - dirtyOutputClassesMap.notDirty(MODULE_MAPPING_FILE_NAME) + dirtyOutputClassesMap.notDirty(jvmClassName) sourceFiles.forEach { sourceToClassesMap.add(it, jvmClassName) } } @@ -116,7 +104,7 @@ open class IncrementalJvmCache( val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass val className = kotlinClass.className - dirtyOutputClassesMap.notDirty(className.internalName) + dirtyOutputClassesMap.notDirty(className) sourceFiles.forEach { sourceToClassesMap.add(it, className) } @@ -181,7 +169,7 @@ open class IncrementalJvmCache( val (proto, nameResolver) = serializedJavaClass.toProtoData() addToClassStorage(proto, nameResolver, source) - dirtyOutputClassesMap.notDirty(jvmClassName.internalName) + dirtyOutputClassesMap.notDirty(jvmClassName) } fun getObsoleteJavaClasses(): Collection = @@ -192,31 +180,28 @@ open class IncrementalJvmCache( fun isJavaClassToTrack(classId: ClassId): Boolean { val jvmClassName = JvmClassName.byClassId(classId) - return dirtyOutputClassesMap.isDirty(jvmClassName.internalName) || - javaSourcesProtoMap[jvmClassName.internalName] == null + return dirtyOutputClassesMap.isDirty(jvmClassName) || + jvmClassName !in javaSourcesProtoMap } fun isJavaClassAlreadyInCache(classId: ClassId): Boolean { val jvmClassName = JvmClassName.byClassId(classId) - return javaSourcesProtoMap[jvmClassName.internalName] != null + return jvmClassName in javaSourcesProtoMap } - fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) { - val dirtyClasses = dirtyOutputClassesMap - .getDirtyOutputClasses() - .map(JvmClassName::byInternalName) - .toList() + override fun clearCacheForRemovedClasses(changesCollector: ChangesCollector) { + val dirtyClasses = dirtyOutputClassesMap.getDirtyOutputClasses() val facadesWithRemovedParts = hashMapOf>() for (dirtyClass in dirtyClasses) { - val facade = partToMultifileFacade.get(dirtyClass.internalName) ?: continue + val facade = partToMultifileFacade.get(dirtyClass) ?: continue val facadeClassName = JvmClassName.byInternalName(facade) val removedParts = facadesWithRemovedParts.getOrPut(facadeClassName) { hashSetOf() } removedParts.add(dirtyClass.internalName) } for ((facade, removedParts) in facadesWithRemovedParts.entries) { - val allParts = multifileFacadeToParts[facade.internalName] ?: continue + val allParts = multifileFacadeToParts[facade] ?: continue val notRemovedParts = allParts.filter { it !in removedParts } if (notRemovedParts.isEmpty()) { @@ -239,15 +224,13 @@ open class IncrementalJvmCache( } removeAllFromClassStorage(dirtyClasses.map { it.fqNameForClassNameWithoutDollars }) - dirtyOutputClassesMap.clean() } override fun getObsoletePackageParts(): Collection { - val obsoletePackageParts = - dirtyOutputClassesMap.getDirtyOutputClasses().filter { packagePartMap.isPackagePart(JvmClassName.byInternalName(it)) } + val obsoletePackageParts = dirtyOutputClassesMap.getDirtyOutputClasses().filter(packagePartMap::isPackagePart) debugLog("Obsolete package parts: $obsoletePackageParts") - return obsoletePackageParts + return obsoletePackageParts.map { it.internalName } } override fun getPackagePartData(partInternalName: String): JvmPackagePartProto? { @@ -267,8 +250,9 @@ open class IncrementalJvmCache( } override fun getStableMultifileFacadeParts(facadeInternalName: String): Collection? { - val partNames = multifileFacadeToParts.get(facadeInternalName) ?: return null - return partNames.filter { !dirtyOutputClassesMap.isDirty(it) } + val jvmClassName = JvmClassName.byInternalName(facadeInternalName) + val partNames = multifileFacadeToParts[jvmClassName] ?: return null + return partNames.filter { !dirtyOutputClassesMap.isDirty(JvmClassName.byInternalName(it)) } } override fun getModuleMappingData(): ByteArray? { @@ -351,7 +335,11 @@ open class IncrementalJvmCache( 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 = java.lang.Long.toHexString(value.proto.toByteArray().md5()) @@ -419,13 +407,15 @@ open class IncrementalJvmCache( } private inner class MultifileClassFacadeMap(storageFile: File) : BasicStringMap>(storageFile, StringCollectionExternalizer) { - operator fun set(facadeName: JvmClassName, partNames: Collection) { - storage[facadeName.internalName] = partNames + operator fun set(className: JvmClassName, partNames: Collection) { + storage[className.internalName] = partNames } - operator fun get(internalName: String): Collection? = storage[internalName] + operator fun get(className: JvmClassName): Collection? = + 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) { storage.remove(className.internalName) @@ -439,9 +429,8 @@ open class IncrementalJvmCache( storage[partName] = facadeName } - fun get(partName: String): String? { - return storage.get(partName) - } + fun get(partName: JvmClassName): String? = + storage[partName.internalName] fun remove(className: JvmClassName) { storage.remove(className.internalName) @@ -450,27 +439,6 @@ open class IncrementalJvmCache( override fun dumpValue(value: String): String = value } - inner class SourceToClassesMap(storageFile: File) : BasicStringMap>(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 = - storage[sourceFile.absolutePath].orEmpty().map { JvmClassName.byInternalName(it) } - - override fun dumpValue(value: Collection) = value.dumpCollection() - - private fun remove(path: String) { - storage.remove(path) - } - } - inner class InternalNameToSourcesMap(storageFile: File) : BasicStringMap>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) { operator fun set(internalName: String, sourceFiles: Iterable) { storage[internalName] = sourceFiles.map { it.canonicalPath } @@ -492,24 +460,6 @@ open class IncrementalJvmCache( addToClassStorage(proto, nameResolver, srcFile) } - private inner class DirtyOutputClassesMap(storageFile: File) : BasicStringMap(storageFile, BooleanDataDescriptor.INSTANCE) { - fun markDirty(className: String) { - storage[className] = true - } - - fun notDirty(className: String) { - storage.remove(className) - } - - fun getDirtyOutputClasses(): Collection = - storage.keys - - fun isDirty(className: String): Boolean = - storage.contains(className) - - override fun dumpValue(value: Boolean) = "" - } - private inner class InlineFunctionsMap(storageFile: File) : BasicStringMap>(storageFile, StringToLongMapExternalizer) { private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray): Map { val inlineFunctions = inlineFunctionsJvmNames(header) diff --git a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt index dab097657a3..24cbc8b829f 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt @@ -116,7 +116,7 @@ data class DirtyData( ) fun ChangesCollector.getDirtyData( - caches: Iterable, + caches: Iterable>, reporter: ICReporter ): DirtyData { val dirtyLookupSymbols = HashSet() @@ -170,7 +170,7 @@ fun mapLookupSymbolsToFiles( } fun mapClassesFqNamesToFiles( - caches: Iterable, + caches: Iterable>, classesFqNames: Iterable, reporter: ICReporter, excludes: Set = emptySet() @@ -192,7 +192,7 @@ fun mapClassesFqNamesToFiles( fun withSubtypes( typeFqName: FqName, - caches: Iterable + caches: Iterable> ): Set { val types = LinkedList(listOf(typeFqName)) val subtypes = hashSetOf() diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/DirtyClassesMaps.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/DirtyClassesMaps.kt new file mode 100644 index 00000000000..5a158e3bea5 --- /dev/null +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/DirtyClassesMaps.kt @@ -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(JvmClassNameTransformer, storageFile) +internal class DirtyClassesFqNameMap(storageFile: File) : AbstractDirtyClassesMap(FqNameTransformer, storageFile) + +internal abstract class AbstractDirtyClassesMap( + private val nameTransformer: NameTransformer, + storageFile: File +) : BasicStringMap(storageFile, BooleanDataDescriptor.INSTANCE) { + fun markDirty(className: Name) { + storage[nameTransformer.asString(className)] = true + } + + fun notDirty(className: Name) { + storage.remove(nameTransformer.asString(className)) + } + + fun getDirtyOutputClasses(): Collection = + storage.keys.map { nameTransformer.asName(it) } + + fun isDirty(className: Name): Boolean = + storage.contains(nameTransformer.asString(className)) + + override fun dumpValue(value: Boolean) = "" +} diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/NameTransformers.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/NameTransformers.kt new file mode 100644 index 00000000000..d5dc58329f7 --- /dev/null +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/NameTransformers.kt @@ -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 { + fun asString(name: Name): String + fun asName(string: String): Name +} + +internal object FqNameTransformer : NameTransformer { + override fun asString(name: FqName): String = + name.asString() + + override fun asName(string: String): FqName = + FqName(string) +} + +internal object JvmClassNameTransformer : NameTransformer { + override fun asString(name: JvmClassName): String = + name.internalName + + override fun asName(string: String): JvmClassName = + JvmClassName.byInternalName(string) +} \ No newline at end of file diff --git a/build-common/src/org/jetbrains/kotlin/incremental/storage/SourceToOutputMaps.kt b/build-common/src/org/jetbrains/kotlin/incremental/storage/SourceToOutputMaps.kt new file mode 100644 index 00000000000..9b17befec3c --- /dev/null +++ b/build-common/src/org/jetbrains/kotlin/incremental/storage/SourceToOutputMaps.kt @@ -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(JvmClassNameTransformer, storageFile) +internal class SourceToFqNameMap(storageFile: File) : AbstractSourceToOutputMap(FqNameTransformer, storageFile) + +internal abstract class AbstractSourceToOutputMap( + private val nameTransformer: NameTransformer, + storageFile: File +) : BasicStringMap>(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 = + storage[sourceFile.absolutePath].orEmpty().map(nameTransformer::asName) + + override fun dumpValue(value: Collection) = + value.dumpCollection() + + private fun remove(path: String) { + storage.remove(path) + } +} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt index ea55ebc2710..8b6a5511ce0 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCachesManager.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.incremental import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner import java.io.File -abstract class IncrementalCachesManager( +abstract class IncrementalCachesManager>( protected val cachesRootDir: File, protected val reporter: ICReporter ) { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt index 13b2c1c3911..829ed004b32 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt @@ -121,7 +121,8 @@ class IncrementalJsCompilerRunner( val jsCache = caches.platformCache jsCache.header = incrementalResults.headerMetadata - return jsCache.compareAndUpdate(incrementalResults, changesCollector) + jsCache.compareAndUpdate(incrementalResults, changesCollector) + jsCache.clearCacheForRemovedClasses(changesCollector) } override fun runCompiler(