[IC] Introduce ICContext to simplify configuration propagation to caches
#KT-49785 In Progress
This commit is contained in:
committed by
Space Team
parent
7171c2531c
commit
581bc89849
@@ -51,7 +51,7 @@ interface IncrementalCacheCommon {
|
|||||||
*/
|
*/
|
||||||
abstract class AbstractIncrementalCache<ClassName>(
|
abstract class AbstractIncrementalCache<ClassName>(
|
||||||
workingDir: File,
|
workingDir: File,
|
||||||
protected val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicMapsOwner(workingDir), IncrementalCacheCommon {
|
) : BasicMapsOwner(workingDir), IncrementalCacheCommon {
|
||||||
companion object {
|
companion object {
|
||||||
private const val CLASS_ATTRIBUTES = "class-attributes"
|
private const val CLASS_ATTRIBUTES = "class-attributes"
|
||||||
@@ -78,10 +78,10 @@ abstract class AbstractIncrementalCache<ClassName>(
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val classAttributesMap = registerMap(ClassAttributesMap(CLASS_ATTRIBUTES.storageFile))
|
internal val classAttributesMap = registerMap(ClassAttributesMap(CLASS_ATTRIBUTES.storageFile, icContext))
|
||||||
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile))
|
private val subtypesMap = registerMap(SubtypesMap(SUBTYPES.storageFile, icContext))
|
||||||
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile))
|
private val supertypesMap = registerMap(SupertypesMap(SUPERTYPES.storageFile, icContext))
|
||||||
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile, pathConverter))
|
protected val classFqNameToSourceMap = registerMap(ClassFqNameToSourceMap(CLASS_FQ_NAME_TO_SOURCE.storageFile, icContext))
|
||||||
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
internal abstract val sourceToClassesMap: AbstractSourceToOutputMap<ClassName>
|
||||||
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
internal abstract val dirtyOutputClassesMap: AbstractDirtyClassesMap<ClassName>
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ abstract class AbstractIncrementalCache<ClassName>(
|
|||||||
* about missing parts.
|
* about missing parts.
|
||||||
* TODO: provide a better solution (maintain an index of expect/actual declarations akin to IncrementalPackagePartProvider)
|
* TODO: provide a better solution (maintain an index of expect/actual declarations akin to IncrementalPackagePartProvider)
|
||||||
*/
|
*/
|
||||||
private val complementaryFilesMap = registerMap(ComplementarySourceFilesMap(COMPLEMENTARY_FILES.storageFile, pathConverter))
|
private val complementaryFilesMap = registerMap(ComplementarySourceFilesMap(COMPLEMENTARY_FILES.storageFile, icContext))
|
||||||
|
|
||||||
override fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
|
override fun classesFqNamesBySources(files: Iterable<File>): Collection<FqName> =
|
||||||
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
|
files.flatMapTo(HashSet()) { sourceToClassesMap.getFqNames(it) }
|
||||||
@@ -187,9 +187,8 @@ abstract class AbstractIncrementalCache<ClassName>(
|
|||||||
|
|
||||||
protected class ClassFqNameToSourceMap(
|
protected class ClassFqNameToSourceMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor) {
|
) : BasicStringMap<String>(storageFile, EnumeratorStringDescriptor(), PathStringDescriptor, icContext) {
|
||||||
|
|
||||||
operator fun set(fqName: FqName, sourceFile: File) {
|
operator fun set(fqName: FqName, sourceFile: File) {
|
||||||
storage[fqName.asString()] = pathConverter.toPath(sourceFile)
|
storage[fqName.asString()] = pathConverter.toPath(sourceFile)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.incremental
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
||||||
|
import org.jetbrains.kotlin.build.report.ICReporter
|
||||||
|
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
||||||
|
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
private fun createDefaultPathConverter(rootProjectDir: File?) = IncrementalFileToPathConverter(rootProjectDir)
|
||||||
|
|
||||||
|
class IncrementalCompilationContext(
|
||||||
|
val pathConverter: FileToPathConverter,
|
||||||
|
val storeFullFqNamesInLookupCache: Boolean = false,
|
||||||
|
val transaction: CompilationTransaction = DummyCompilationTransaction(),
|
||||||
|
val reporter: ICReporter = DoNothingICReporter,
|
||||||
|
val trackChangesInLookupCache: Boolean = false,
|
||||||
|
) {
|
||||||
|
constructor(
|
||||||
|
rootProjectDir: File?,
|
||||||
|
storeFullFqNamesInLookupCache: Boolean = false,
|
||||||
|
transaction: CompilationTransaction = DummyCompilationTransaction(),
|
||||||
|
reporter: ICReporter = DoNothingICReporter,
|
||||||
|
trackChangesInLookupCache: Boolean = false,
|
||||||
|
) : this(
|
||||||
|
createDefaultPathConverter(rootProjectDir),
|
||||||
|
storeFullFqNamesInLookupCache,
|
||||||
|
transaction,
|
||||||
|
reporter,
|
||||||
|
trackChangesInLookupCache,
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -40,10 +40,9 @@ import java.io.File
|
|||||||
|
|
||||||
open class IncrementalJsCache(
|
open class IncrementalJsCache(
|
||||||
cachesDir: File,
|
cachesDir: File,
|
||||||
pathConverter: FileToPathConverter,
|
private val icContext: IncrementalCompilationContext,
|
||||||
serializerProtocol: SerializerExtensionProtocol,
|
serializerProtocol: SerializerExtensionProtocol,
|
||||||
private val transaction: CompilationTransaction,
|
) : AbstractIncrementalCache<FqName>(cachesDir, icContext) {
|
||||||
) : AbstractIncrementalCache<FqName>(cachesDir, pathConverter) {
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TRANSLATION_RESULT_MAP = "translation-result"
|
private const val TRANSLATION_RESULT_MAP = "translation-result"
|
||||||
private const val IR_TRANSLATION_RESULT_MAP = "ir-translation-result"
|
private const val IR_TRANSLATION_RESULT_MAP = "ir-translation-result"
|
||||||
@@ -57,13 +56,13 @@ open class IncrementalJsCache(
|
|||||||
|
|
||||||
private val protoData = ProtoDataProvider(serializerProtocol)
|
private val protoData = ProtoDataProvider(serializerProtocol)
|
||||||
|
|
||||||
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile, pathConverter))
|
override val sourceToClassesMap = registerMap(SourceToFqNameMap(SOURCE_TO_CLASSES.storageFile, icContext))
|
||||||
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
override val dirtyOutputClassesMap = registerMap(DirtyClassesFqNameMap(DIRTY_OUTPUT_CLASSES.storageFile, icContext))
|
||||||
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, pathConverter, protoData))
|
private val translationResults = registerMap(TranslationResultMap(TRANSLATION_RESULT_MAP.storageFile, protoData, icContext))
|
||||||
private val irTranslationResults = registerMap(IrTranslationResultMap(IR_TRANSLATION_RESULT_MAP.storageFile, pathConverter))
|
private val irTranslationResults = registerMap(IrTranslationResultMap(IR_TRANSLATION_RESULT_MAP.storageFile, icContext))
|
||||||
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, pathConverter))
|
private val inlineFunctions = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, icContext))
|
||||||
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile))
|
private val packageMetadata = registerMap(PackageMetadataMap(PACKAGE_META_FILE.storageFile, icContext))
|
||||||
private val sourceToJsOutputsMap = registerMap(SourceToJsOutputMap(SOURCE_TO_JS_OUTPUT.storageFile, pathConverter))
|
private val sourceToJsOutputsMap = registerMap(SourceToJsOutputMap(SOURCE_TO_JS_OUTPUT.storageFile, icContext))
|
||||||
|
|
||||||
private val dirtySources = hashSetOf<File>()
|
private val dirtySources = hashSetOf<File>()
|
||||||
|
|
||||||
@@ -73,7 +72,7 @@ open class IncrementalJsCache(
|
|||||||
var header: ByteArray
|
var header: ByteArray
|
||||||
get() = headerFile.readBytes()
|
get() = headerFile.readBytes()
|
||||||
set(value) {
|
set(value) {
|
||||||
transaction.registerAddedOrChangedFile(headerFile.toPath())
|
icContext.transaction.registerAddedOrChangedFile(headerFile.toPath())
|
||||||
cachesDir.mkdirs()
|
cachesDir.mkdirs()
|
||||||
headerFile.writeBytes(value)
|
headerFile.writeBytes(value)
|
||||||
}
|
}
|
||||||
@@ -229,10 +228,10 @@ private object TranslationResultValueExternalizer : DataExternalizer<Translation
|
|||||||
|
|
||||||
private class TranslationResultMap(
|
private class TranslationResultMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter,
|
private val protoData: ProtoDataProvider,
|
||||||
private val protoData: ProtoDataProvider
|
icContext: IncrementalCompilationContext,
|
||||||
) :
|
) :
|
||||||
BasicStringMap<TranslationResultValue>(storageFile, TranslationResultValueExternalizer) {
|
BasicStringMap<TranslationResultValue>(storageFile, TranslationResultValueExternalizer, icContext) {
|
||||||
override fun dumpValue(value: TranslationResultValue): String =
|
override fun dumpValue(value: TranslationResultValue): String =
|
||||||
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}, InlineData: ${value.inlineData.md5()}"
|
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}, InlineData: ${value.inlineData.md5()}"
|
||||||
|
|
||||||
@@ -313,9 +312,9 @@ private object IrTranslationResultValueExternalizer : DataExternalizer<IrTransla
|
|||||||
|
|
||||||
private class IrTranslationResultMap(
|
private class IrTranslationResultMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) :
|
) :
|
||||||
BasicStringMap<IrTranslationResultValue>(storageFile, IrTranslationResultValueExternalizer) {
|
BasicStringMap<IrTranslationResultValue>(storageFile, IrTranslationResultValueExternalizer, icContext) {
|
||||||
override fun dumpValue(value: IrTranslationResultValue): String =
|
override fun dumpValue(value: IrTranslationResultValue): String =
|
||||||
"Filedata: ${value.fileData.md5()}, " +
|
"Filedata: ${value.fileData.md5()}, " +
|
||||||
"Types: ${value.types.md5()}, " +
|
"Types: ${value.types.md5()}, " +
|
||||||
@@ -395,8 +394,8 @@ fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData>
|
|||||||
|
|
||||||
private class InlineFunctionsMap(
|
private class InlineFunctionsMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer, icContext) {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
|
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
|
||||||
val key = pathConverter.toPath(srcFile)
|
val key = pathConverter.toPath(srcFile)
|
||||||
@@ -439,7 +438,10 @@ private object ByteArrayExternalizer : DataExternalizer<ByteArray> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class PackageMetadataMap(storageFile: File) : BasicStringMap<ByteArray>(storageFile, ByteArrayExternalizer) {
|
private class PackageMetadataMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<ByteArray>(storageFile, ByteArrayExternalizer, icContext) {
|
||||||
fun put(packageName: String, newMetadata: ByteArray) {
|
fun put(packageName: String, newMetadata: ByteArray) {
|
||||||
storage[packageName] = newMetadata
|
storage[packageName] = newMetadata
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,11 +44,11 @@ const val KOTLIN_CACHE_DIRECTORY_NAME = "kotlin"
|
|||||||
|
|
||||||
open class IncrementalJvmCache(
|
open class IncrementalJvmCache(
|
||||||
targetDataRoot: File,
|
targetDataRoot: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
targetOutputDir: File?,
|
targetOutputDir: File?,
|
||||||
pathConverter: FileToPathConverter
|
|
||||||
) : AbstractIncrementalCache<JvmClassName>(
|
) : AbstractIncrementalCache<JvmClassName>(
|
||||||
workingDir = File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME),
|
workingDir = File(targetDataRoot, KOTLIN_CACHE_DIRECTORY_NAME),
|
||||||
pathConverter = pathConverter
|
icContext,
|
||||||
), IncrementalCache {
|
), IncrementalCache {
|
||||||
companion object {
|
companion object {
|
||||||
private const val PROTO_MAP = "proto"
|
private const val PROTO_MAP = "proto"
|
||||||
@@ -64,20 +64,20 @@ open class IncrementalJvmCache(
|
|||||||
private const val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
private const val MODULE_MAPPING_FILE_NAME = "." + ModuleMapping.MAPPING_FILE_EXT
|
||||||
}
|
}
|
||||||
|
|
||||||
override val sourceToClassesMap = registerMap(SourceToJvmNameMap(SOURCE_TO_CLASSES.storageFile, pathConverter))
|
override val sourceToClassesMap = registerMap(SourceToJvmNameMap(SOURCE_TO_CLASSES.storageFile, icContext))
|
||||||
override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile))
|
override val dirtyOutputClassesMap = registerMap(DirtyClassesJvmNameMap(DIRTY_OUTPUT_CLASSES.storageFile, icContext))
|
||||||
|
|
||||||
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile))
|
private val protoMap = registerMap(ProtoMap(PROTO_MAP.storageFile, icContext))
|
||||||
private val feProtoMap = registerMap(ProtoMap(FE_PROTO_MAP.storageFile))
|
private val feProtoMap = registerMap(ProtoMap(FE_PROTO_MAP.storageFile, icContext))
|
||||||
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile))
|
private val constantsMap = registerMap(ConstantsMap(CONSTANTS_MAP.storageFile, icContext))
|
||||||
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile))
|
private val packagePartMap = registerMap(PackagePartMap(PACKAGE_PARTS.storageFile, icContext))
|
||||||
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile))
|
private val multifileFacadeToParts = registerMap(MultifileClassFacadeMap(MULTIFILE_CLASS_FACADES.storageFile, icContext))
|
||||||
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile))
|
private val partToMultifileFacade = registerMap(MultifileClassPartMap(MULTIFILE_CLASS_PARTS.storageFile, icContext))
|
||||||
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile))
|
private val inlineFunctionsMap = registerMap(InlineFunctionsMap(INLINE_FUNCTIONS.storageFile, icContext))
|
||||||
// todo: try to use internal names only?
|
// todo: try to use internal names only?
|
||||||
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile, pathConverter))
|
private val internalNameToSource = registerMap(InternalNameToSourcesMap(INTERNAL_NAME_TO_SOURCE.storageFile, icContext))
|
||||||
// gradle only
|
// gradle only
|
||||||
private val javaSourcesProtoMap = registerMap(JavaSourcesProtoMap(JAVA_SOURCES_PROTO_MAP.storageFile))
|
private val javaSourcesProtoMap = registerMap(JavaSourcesProtoMap(JAVA_SOURCES_PROTO_MAP.storageFile, icContext))
|
||||||
|
|
||||||
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory" } }
|
private val outputDir by lazy(LazyThreadSafetyMode.NONE) { requireNotNull(targetOutputDir) { "Target is expected to have output directory" } }
|
||||||
|
|
||||||
@@ -328,7 +328,10 @@ open class IncrementalJvmCache(
|
|||||||
return protoMap[JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)]?.bytes
|
return protoMap[JvmClassName.byInternalName(MODULE_MAPPING_FILE_NAME)]?.bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ProtoMap(storageFile: File) : BasicStringMap<ProtoMapValue>(storageFile, ProtoMapValueExternalizer) {
|
private inner class ProtoMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<ProtoMapValue>(storageFile, ProtoMapValueExternalizer, icContext) {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun process(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) {
|
fun process(kotlinClassInfo: KotlinClassInfo, changesCollector: ChangesCollector) {
|
||||||
@@ -396,8 +399,11 @@ open class IncrementalJvmCache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class JavaSourcesProtoMap(storageFile: File) :
|
private inner class JavaSourcesProtoMap(
|
||||||
BasicStringMap<SerializedJavaClass>(storageFile, JavaClassProtoMapValueExternalizer) {
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
|
BasicStringMap<SerializedJavaClass>(storageFile, JavaClassProtoMapValueExternalizer, icContext) {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun process(jvmClassName: JvmClassName, newData: SerializedJavaClass, changesCollector: ChangesCollector) {
|
fun process(jvmClassName: JvmClassName, newData: SerializedJavaClass, changesCollector: ChangesCollector) {
|
||||||
@@ -431,8 +437,11 @@ open class IncrementalJvmCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo: reuse code with InlineFunctionsMap?
|
// todo: reuse code with InlineFunctionsMap?
|
||||||
private inner class ConstantsMap(storageFile: File) :
|
private inner class ConstantsMap(
|
||||||
BasicStringMap<Map<String, Any>>(storageFile, MapExternalizer(StringExternalizer, ConstantValueExternalizer)) {
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
|
BasicStringMap<Map<String, Any>>(storageFile, MapExternalizer(StringExternalizer, ConstantValueExternalizer), icContext) {
|
||||||
|
|
||||||
operator fun contains(className: JvmClassName): Boolean =
|
operator fun contains(className: JvmClassName): Boolean =
|
||||||
className.internalName in storage
|
className.internalName in storage
|
||||||
@@ -484,7 +493,10 @@ open class IncrementalJvmCache(
|
|||||||
value.dumpMap(Any::toString)
|
value.dumpMap(Any::toString)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class PackagePartMap(storageFile: File) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
private inner class PackagePartMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE, icContext) {
|
||||||
fun addPackagePart(className: JvmClassName) {
|
fun addPackagePart(className: JvmClassName) {
|
||||||
storage[className.internalName] = true
|
storage[className.internalName] = true
|
||||||
}
|
}
|
||||||
@@ -499,8 +511,11 @@ open class IncrementalJvmCache(
|
|||||||
override fun dumpValue(value: Boolean) = ""
|
override fun dumpValue(value: Boolean) = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class MultifileClassFacadeMap(storageFile: File) :
|
private inner class MultifileClassFacadeMap(
|
||||||
BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
|
BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer, icContext) {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
operator fun set(className: JvmClassName, partNames: Collection<String>) {
|
operator fun set(className: JvmClassName, partNames: Collection<String>) {
|
||||||
@@ -521,8 +536,11 @@ open class IncrementalJvmCache(
|
|||||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class MultifileClassPartMap(storageFile: File) :
|
private inner class MultifileClassPartMap(
|
||||||
BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE) {
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
|
BasicStringMap<String>(storageFile, EnumeratorStringDescriptor.INSTANCE, icContext) {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun set(partName: String, facadeName: String) {
|
fun set(partName: String, facadeName: String) {
|
||||||
@@ -542,8 +560,8 @@ open class IncrementalJvmCache(
|
|||||||
|
|
||||||
inner class InternalNameToSourcesMap(
|
inner class InternalNameToSourcesMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer) {
|
) : BasicStringMap<Collection<String>>(storageFile, EnumeratorStringDescriptor(), PathCollectionExternalizer, icContext) {
|
||||||
operator fun set(internalName: String, sourceFiles: Collection<File>) {
|
operator fun set(internalName: String, sourceFiles: Collection<File>) {
|
||||||
storage[internalName] = pathConverter.toPaths(sourceFiles)
|
storage[internalName] = pathConverter.toPaths(sourceFiles)
|
||||||
}
|
}
|
||||||
@@ -559,10 +577,14 @@ open class IncrementalJvmCache(
|
|||||||
value.dumpCollection()
|
value.dumpCollection()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class InlineFunctionsMap(storageFile: File) :
|
private inner class InlineFunctionsMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
BasicStringMap<Map<InlineFunctionOrAccessor, Long>>(
|
BasicStringMap<Map<InlineFunctionOrAccessor, Long>>(
|
||||||
storageFile,
|
storageFile,
|
||||||
MapExternalizer(InlineFunctionOrAccessorExternalizer, LongExternalizer)
|
MapExternalizer(InlineFunctionOrAccessorExternalizer, LongExternalizer),
|
||||||
|
icContext
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|||||||
@@ -32,22 +32,22 @@ import java.util.*
|
|||||||
|
|
||||||
open class LookupStorage(
|
open class LookupStorage(
|
||||||
targetDataDir: File,
|
targetDataDir: File,
|
||||||
pathConverter: FileToPathConverter,
|
private val icContext: IncrementalCompilationContext,
|
||||||
storeFullFqNames: Boolean = false,
|
|
||||||
private val trackChanges: Boolean = false,
|
|
||||||
private val transaction: CompilationTransaction = DummyCompilationTransaction(),
|
|
||||||
) : BasicMapsOwner(targetDataDir) {
|
) : BasicMapsOwner(targetDataDir) {
|
||||||
val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder")
|
val LOG = Logger.getInstance("#org.jetbrains.kotlin.jps.build.KotlinBuilder")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DELETED_TO_SIZE_TRESHOLD = 0.5
|
private const val DELETED_TO_SIZE_THRESHOLD = 0.5
|
||||||
private val MINIMUM_GARBAGE_COLLECTIBLE_SIZE = 10000
|
private const val MINIMUM_GARBAGE_COLLECTIBLE_SIZE = 10000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val trackChanges
|
||||||
|
get() = icContext.trackChangesInLookupCache
|
||||||
|
|
||||||
private val countersFile = "counters".storageFile
|
private val countersFile = "counters".storageFile
|
||||||
private val idToFile = registerMap(IdToFileMap("id-to-file".storageFile, pathConverter))
|
private val idToFile = registerMap(IdToFileMap("id-to-file".storageFile, icContext))
|
||||||
private val fileToId = registerMap(FileToIdMap("file-to-id".storageFile, pathConverter))
|
private val fileToId = registerMap(FileToIdMap("file-to-id".storageFile, icContext))
|
||||||
private val lookupMap = TrackedLookupMap(registerMap(LookupMap("lookups".storageFile, storeFullFqNames)), trackChanges)
|
private val lookupMap = TrackedLookupMap(registerMap(LookupMap("lookups".storageFile, icContext)), trackChanges)
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
private var size: Int = 0
|
private var size: Int = 0
|
||||||
@@ -57,8 +57,9 @@ open class LookupStorage(
|
|||||||
try {
|
try {
|
||||||
if (countersFile.exists()) {
|
if (countersFile.exists()) {
|
||||||
val lines = countersFile.readLines()
|
val lines = countersFile.readLines()
|
||||||
size = lines.firstOrNull()?.toIntOrNull() ?: throw IOException("$countersFile exists, but it is empty. " +
|
size = lines.firstOrNull()?.toIntOrNull() ?: throw IOException(
|
||||||
"Counters file is corrupted"
|
"$countersFile exists, but it is empty. " +
|
||||||
|
"Counters file is corrupted"
|
||||||
)
|
)
|
||||||
oldSize = size
|
oldSize = size
|
||||||
}
|
}
|
||||||
@@ -104,7 +105,7 @@ open class LookupStorage(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > MINIMUM_GARBAGE_COLLECTIBLE_SIZE && filtered.size.toDouble() / fileIds.size.toDouble() < DELETED_TO_SIZE_TRESHOLD) {
|
if (size > MINIMUM_GARBAGE_COLLECTIBLE_SIZE && filtered.size.toDouble() / fileIds.size.toDouble() < DELETED_TO_SIZE_THRESHOLD) {
|
||||||
lookupMap[key] = filtered
|
lookupMap[key] = filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ open class LookupStorage(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun clean() {
|
override fun clean() {
|
||||||
transaction.deleteFile(countersFile.toPath())
|
icContext.transaction.deleteFile(countersFile.toPath())
|
||||||
|
|
||||||
size = 0
|
size = 0
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ open class LookupStorage(
|
|||||||
try {
|
try {
|
||||||
if (size != oldSize) {
|
if (size != oldSize) {
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
transaction.registerAddedOrChangedFile(countersFile.toPath())
|
icContext.transaction.registerAddedOrChangedFile(countersFile.toPath())
|
||||||
if (!countersFile.exists()) {
|
if (!countersFile.exists()) {
|
||||||
countersFile.parentFile.mkdirs()
|
countersFile.parentFile.mkdirs()
|
||||||
countersFile.createNewFile()
|
countersFile.createNewFile()
|
||||||
|
|||||||
@@ -20,16 +20,21 @@ import com.intellij.util.io.DataExternalizer
|
|||||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||||
import com.intellij.util.io.KeyDescriptor
|
import com.intellij.util.io.KeyDescriptor
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class BasicMap<K : Comparable<K>, V>(
|
abstract class BasicMap<K : Comparable<K>, V>(
|
||||||
internal val storageFile: File,
|
internal val storageFile: File,
|
||||||
keyDescriptor: KeyDescriptor<K>,
|
keyDescriptor: KeyDescriptor<K>,
|
||||||
valueExternalizer: DataExternalizer<V>
|
valueExternalizer: DataExternalizer<V>,
|
||||||
|
protected val icContext: IncrementalCompilationContext,
|
||||||
) {
|
) {
|
||||||
protected val storage: LazyStorage<K, V> = CachingLazyStorage(storageFile, keyDescriptor, valueExternalizer)
|
protected val storage: LazyStorage<K, V> = CachingLazyStorage(storageFile, keyDescriptor, valueExternalizer)
|
||||||
|
|
||||||
|
protected val pathConverter
|
||||||
|
get() = icContext.pathConverter
|
||||||
|
|
||||||
fun clean() {
|
fun clean() {
|
||||||
storage.clean()
|
storage.clean()
|
||||||
}
|
}
|
||||||
@@ -74,14 +79,16 @@ abstract class BasicMap<K : Comparable<K>, V>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class BasicStringMap<V>(
|
abstract class BasicStringMap<V>(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
keyDescriptor: KeyDescriptor<String>,
|
keyDescriptor: KeyDescriptor<String>,
|
||||||
valueExternalizer: DataExternalizer<V>
|
valueExternalizer: DataExternalizer<V>,
|
||||||
) : BasicMap<String, V>(storageFile, keyDescriptor, valueExternalizer) {
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicMap<String, V>(storageFile, keyDescriptor, valueExternalizer, icContext) {
|
||||||
constructor(
|
constructor(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
valueExternalizer: DataExternalizer<V>
|
valueExternalizer: DataExternalizer<V>,
|
||||||
) : this(storageFile, EnumeratorStringDescriptor.INSTANCE, valueExternalizer)
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : this(storageFile, EnumeratorStringDescriptor.INSTANCE, valueExternalizer, icContext)
|
||||||
|
|
||||||
override fun dumpKey(key: String): String = key
|
override fun dumpKey(key: String): String = key
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
import com.intellij.util.io.DataExternalizer
|
import com.intellij.util.io.DataExternalizer
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import java.io.DataInput
|
import java.io.DataInput
|
||||||
import java.io.DataOutput
|
import java.io.DataOutput
|
||||||
@@ -35,8 +36,9 @@ internal object ICClassesAttributesExternalizer : DataExternalizer<ICClassesAttr
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal open class ClassAttributesMap(
|
internal open class ClassAttributesMap(
|
||||||
storageFile: File
|
storageFile: File,
|
||||||
) : BasicStringMap<ICClassesAttributes>(storageFile, ICClassesAttributesExternalizer) {
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<ICClassesAttributes>(storageFile, ICClassesAttributesExternalizer, icContext) {
|
||||||
override fun dumpValue(value: ICClassesAttributes): String = value.toString()
|
override fun dumpValue(value: ICClassesAttributes): String = value.toString()
|
||||||
|
|
||||||
operator fun set(key: FqName, value: ICClassesAttributes) {
|
operator fun set(key: FqName, value: ICClassesAttributes) {
|
||||||
|
|||||||
@@ -16,11 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
internal open class ClassOneToManyMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer, icContext) {
|
||||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@@ -56,5 +60,12 @@ internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class SubtypesMap(storageFile: File) : ClassOneToManyMap(storageFile)
|
internal class SubtypesMap(
|
||||||
internal class SupertypesMap(storageFile: File) : ClassOneToManyMap(storageFile)
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : ClassOneToManyMap(storageFile, icContext)
|
||||||
|
|
||||||
|
internal class SupertypesMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : ClassOneToManyMap(storageFile, icContext)
|
||||||
|
|||||||
+3
-2
@@ -5,13 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class ComplementarySourceFilesMap(
|
class ComplementarySourceFilesMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer, icContext) {
|
||||||
|
|
||||||
operator fun set(sourceFile: File, complementaryFiles: Collection<File>) {
|
operator fun set(sourceFile: File, complementaryFiles: Collection<File>) {
|
||||||
storage[pathConverter.toPath(sourceFile)] = pathConverter.toPaths(complementaryFiles)
|
storage[pathConverter.toPath(sourceFile)] = pathConverter.toPaths(complementaryFiles)
|
||||||
|
|||||||
@@ -17,16 +17,25 @@
|
|||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
import com.intellij.util.io.BooleanDataDescriptor
|
import com.intellij.util.io.BooleanDataDescriptor
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class DirtyClassesJvmNameMap(storageFile: File) : AbstractDirtyClassesMap<JvmClassName>(JvmClassNameTransformer, storageFile)
|
internal class DirtyClassesJvmNameMap(
|
||||||
internal class DirtyClassesFqNameMap(storageFile: File) : AbstractDirtyClassesMap<FqName>(FqNameTransformer, storageFile)
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : AbstractDirtyClassesMap<JvmClassName>(JvmClassNameTransformer, storageFile, icContext)
|
||||||
|
internal class DirtyClassesFqNameMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : AbstractDirtyClassesMap<FqName>(FqNameTransformer, storageFile, icContext)
|
||||||
|
|
||||||
internal abstract class AbstractDirtyClassesMap<Name>(
|
internal abstract class AbstractDirtyClassesMap<Name>(
|
||||||
private val nameTransformer: NameTransformer<Name>, storageFile: File
|
private val nameTransformer: NameTransformer<Name>,
|
||||||
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE) {
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<Boolean>(storageFile, BooleanDataDescriptor.INSTANCE, icContext) {
|
||||||
fun markDirty(className: Name) {
|
fun markDirty(className: Name) {
|
||||||
storage[nameTransformer.asString(className)] = true
|
storage[nameTransformer.asString(className)] = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class FileToIdMap(
|
internal class FileToIdMap(
|
||||||
file: File,
|
file: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Int>(file, IntExternalizer) {
|
) : BasicStringMap<Int>(file, IntExternalizer, icContext) {
|
||||||
override fun dumpValue(value: Int): String = value.toString()
|
override fun dumpValue(value: Int): String = value.toString()
|
||||||
|
|
||||||
operator fun get(file: File): Int? = storage[pathConverter.toPath(file)]
|
operator fun get(file: File): Int? = storage[pathConverter.toPath(file)]
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.incremental.storage
|
|||||||
|
|
||||||
import com.intellij.util.io.EnumeratorStringDescriptor
|
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||||
import com.intellij.util.io.ExternalIntegerKeyDescriptor
|
import com.intellij.util.io.ExternalIntegerKeyDescriptor
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class IdToFileMap(
|
internal class IdToFileMap(
|
||||||
file: File,
|
file: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicMap<Int, String>(file, ExternalIntegerKeyDescriptor(), EnumeratorStringDescriptor.INSTANCE) {
|
) : BasicMap<Int, String>(file, ExternalIntegerKeyDescriptor(), EnumeratorStringDescriptor.INSTANCE, icContext) {
|
||||||
override fun dumpKey(key: Int): String = key.toString()
|
override fun dumpKey(key: Int): String = key.toString()
|
||||||
|
|
||||||
override fun dumpValue(value: String): String = value
|
override fun dumpValue(value: String): String = value
|
||||||
|
|||||||
@@ -16,10 +16,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class LookupMap(storage: File, storeFullFqNames: Boolean) :
|
class LookupMap(
|
||||||
BasicMap<LookupSymbolKey, Collection<Int>>(storage, LookupSymbolKeyDescriptor(storeFullFqNames), IntCollectionExternalizer) {
|
storage: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) :
|
||||||
|
BasicMap<LookupSymbolKey, Collection<Int>>(
|
||||||
|
storage,
|
||||||
|
LookupSymbolKeyDescriptor(icContext.storeFullFqNamesInLookupCache),
|
||||||
|
IntCollectionExternalizer,
|
||||||
|
icContext,
|
||||||
|
) {
|
||||||
|
|
||||||
override fun dumpKey(key: LookupSymbolKey): String = key.toString()
|
override fun dumpKey(key: LookupSymbolKey): String = key.toString()
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class SourceToJsOutputMap(storageFile: File, private val pathConverter: FileToPathConverter) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer) {
|
class SourceToJsOutputMap(
|
||||||
|
storageFile: File,
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
) : BasicStringMap<Collection<String>>(storageFile, StringCollectionExternalizer, icContext) {
|
||||||
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
override fun dumpValue(value: Collection<String>): String = value.dumpCollection()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
@@ -23,19 +24,19 @@ import java.io.File
|
|||||||
|
|
||||||
internal class SourceToJvmNameMap(
|
internal class SourceToJvmNameMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile, pathConverter)
|
) : AbstractSourceToOutputMap<JvmClassName>(JvmClassNameTransformer, storageFile, icContext)
|
||||||
|
|
||||||
internal class SourceToFqNameMap(
|
internal class SourceToFqNameMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile, pathConverter)
|
) : AbstractSourceToOutputMap<FqName>(FqNameTransformer, storageFile, icContext)
|
||||||
|
|
||||||
internal abstract class AbstractSourceToOutputMap<Name>(
|
internal abstract class AbstractSourceToOutputMap<Name>(
|
||||||
private val nameTransformer: NameTransformer<Name>,
|
private val nameTransformer: NameTransformer<Name>,
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer, icContext) {
|
||||||
fun clearOutputsForSource(sourceFile: File) {
|
fun clearOutputsForSource(sourceFile: File) {
|
||||||
remove(pathConverter.toPath(sourceFile))
|
remove(pathConverter.toPath(sourceFile))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.intellij.util.containers.MultiMap
|
|||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
||||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.LookupStorage
|
import org.jetbrains.kotlin.incremental.LookupStorage
|
||||||
import org.jetbrains.kotlin.incremental.LookupSymbol
|
import org.jetbrains.kotlin.incremental.LookupSymbol
|
||||||
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
|
import org.jetbrains.kotlin.incremental.testingUtils.assertEqualDirectories
|
||||||
@@ -50,11 +51,11 @@ class RelocatableCachesTest : TestWithWorkingDir() {
|
|||||||
private fun fillLookupStorage(projectRoot: File, reverseFiles: Boolean, reverseLookups: Boolean, storeFullFqNames: Boolean = false) {
|
private fun fillLookupStorage(projectRoot: File, reverseFiles: Boolean, reverseLookups: Boolean, storeFullFqNames: Boolean = false) {
|
||||||
val storageRoot = projectRoot.storageRoot
|
val storageRoot = projectRoot.storageRoot
|
||||||
val fileToPathConverter = RelativeFileToPathConverter(projectRoot)
|
val fileToPathConverter = RelativeFileToPathConverter(projectRoot)
|
||||||
val lookupStorage = LookupStorage(
|
val icContext = IncrementalCompilationContext(
|
||||||
storageRoot,
|
pathConverter = fileToPathConverter,
|
||||||
fileToPathConverter,
|
storeFullFqNamesInLookupCache = storeFullFqNames,
|
||||||
storeFullFqNames = storeFullFqNames
|
|
||||||
)
|
)
|
||||||
|
val lookupStorage = LookupStorage(storageRoot, icContext)
|
||||||
val files = LinkedHashSet<String>()
|
val files = LinkedHashSet<String>()
|
||||||
val symbols = LinkedHashSet<LookupSymbol>()
|
val symbols = LinkedHashSet<LookupSymbol>()
|
||||||
val lookups = MultiMap.createOrderedSet<LookupSymbol, String>()
|
val lookups = MultiMap.createOrderedSet<LookupSymbol, String>()
|
||||||
|
|||||||
+13
-47
@@ -17,22 +17,15 @@
|
|||||||
package org.jetbrains.kotlin.incremental
|
package org.jetbrains.kotlin.incremental
|
||||||
|
|
||||||
import com.google.common.io.Closer
|
import com.google.common.io.Closer
|
||||||
import org.jetbrains.kotlin.build.report.ICReporter
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
||||||
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
|
||||||
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class IncrementalCachesManager<PlatformCache : AbstractIncrementalCache<*>>(
|
abstract class IncrementalCachesManager<PlatformCache : AbstractIncrementalCache<*>>(
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
cachesRootDir: File,
|
cachesRootDir: File,
|
||||||
rootProjectDir: File?,
|
|
||||||
protected val reporter: ICReporter,
|
|
||||||
transaction: CompilationTransaction,
|
|
||||||
storeFullFqNamesInLookupCache: Boolean = false,
|
|
||||||
trackChangesInLookupCache: Boolean = false
|
|
||||||
) : Closeable {
|
) : Closeable {
|
||||||
val pathConverter = IncrementalFileToPathConverter(rootProjectDir)
|
|
||||||
private val caches = arrayListOf<BasicMapsOwner>()
|
private val caches = arrayListOf<BasicMapsOwner>()
|
||||||
|
|
||||||
private var isClosed = false
|
private var isClosed = false
|
||||||
@@ -46,15 +39,8 @@ abstract class IncrementalCachesManager<PlatformCache : AbstractIncrementalCache
|
|||||||
private val inputSnapshotsCacheDir = File(cachesRootDir, "inputs").apply { mkdirs() }
|
private val inputSnapshotsCacheDir = File(cachesRootDir, "inputs").apply { mkdirs() }
|
||||||
private val lookupCacheDir = File(cachesRootDir, "lookups").apply { mkdirs() }
|
private val lookupCacheDir = File(cachesRootDir, "lookups").apply { mkdirs() }
|
||||||
|
|
||||||
val inputsCache: InputsCache = InputsCache(inputSnapshotsCacheDir, reporter, pathConverter).apply { registerCache() }
|
val inputsCache: InputsCache = InputsCache(inputSnapshotsCacheDir, icContext).apply { registerCache() }
|
||||||
val lookupCache: LookupStorage =
|
val lookupCache: LookupStorage = LookupStorage(lookupCacheDir, icContext).apply { registerCache() }
|
||||||
LookupStorage(
|
|
||||||
lookupCacheDir,
|
|
||||||
pathConverter,
|
|
||||||
storeFullFqNamesInLookupCache,
|
|
||||||
trackChangesInLookupCache,
|
|
||||||
transaction,
|
|
||||||
).apply { registerCache() }
|
|
||||||
abstract val platformCache: PlatformCache
|
abstract val platformCache: PlatformCache
|
||||||
|
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
@@ -83,39 +69,19 @@ abstract class IncrementalCachesManager<PlatformCache : AbstractIncrementalCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
class IncrementalJvmCachesManager(
|
class IncrementalJvmCachesManager(
|
||||||
cacheDirectory: File,
|
icContext: IncrementalCompilationContext,
|
||||||
rootProjectDir: File?,
|
outputDir: File?,
|
||||||
outputDir: File,
|
cachesRootDir: File,
|
||||||
reporter: ICReporter,
|
) : IncrementalCachesManager<IncrementalJvmCache>(icContext, cachesRootDir) {
|
||||||
storeFullFqNamesInLookupCache: Boolean = false,
|
private val jvmCacheDir = File(cachesRootDir, "jvm").apply { mkdirs() }
|
||||||
trackChangesInLookupCache: Boolean = false,
|
override val platformCache = IncrementalJvmCache(jvmCacheDir, icContext, outputDir).apply { registerCache() }
|
||||||
transaction: CompilationTransaction = DummyCompilationTransaction(),
|
|
||||||
) : IncrementalCachesManager<IncrementalJvmCache>(
|
|
||||||
cacheDirectory,
|
|
||||||
rootProjectDir,
|
|
||||||
reporter,
|
|
||||||
transaction,
|
|
||||||
storeFullFqNamesInLookupCache,
|
|
||||||
trackChangesInLookupCache
|
|
||||||
) {
|
|
||||||
private val jvmCacheDir = File(cacheDirectory, "jvm").apply { mkdirs() }
|
|
||||||
override val platformCache = IncrementalJvmCache(jvmCacheDir, outputDir, pathConverter).apply { registerCache() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class IncrementalJsCachesManager(
|
class IncrementalJsCachesManager(
|
||||||
cachesRootDir: File,
|
icContext: IncrementalCompilationContext,
|
||||||
rootProjectDir: File?,
|
|
||||||
reporter: ICReporter,
|
|
||||||
serializerProtocol: SerializerExtensionProtocol,
|
serializerProtocol: SerializerExtensionProtocol,
|
||||||
storeFullFqNamesInLookupCache: Boolean,
|
cachesRootDir: File,
|
||||||
transaction: CompilationTransaction = DummyCompilationTransaction(),
|
) : IncrementalCachesManager<IncrementalJsCache>(icContext, cachesRootDir) {
|
||||||
) : IncrementalCachesManager<IncrementalJsCache>(
|
|
||||||
cachesRootDir,
|
|
||||||
rootProjectDir,
|
|
||||||
reporter,
|
|
||||||
transaction,
|
|
||||||
storeFullFqNamesInLookupCache,
|
|
||||||
) {
|
|
||||||
private val jsCacheFile = File(cachesRootDir, "js").apply { mkdirs() }
|
private val jsCacheFile = File(cachesRootDir, "js").apply { mkdirs() }
|
||||||
override val platformCache = IncrementalJsCache(jsCacheFile, pathConverter, serializerProtocol, transaction).apply { registerCache() }
|
override val platformCache = IncrementalJsCache(jsCacheFile, icContext, serializerProtocol).apply { registerCache() }
|
||||||
}
|
}
|
||||||
+21
-11
@@ -80,7 +80,15 @@ abstract class IncrementalCompilerRunner<
|
|||||||
private val abiSnapshotFile = File(workingDir, ABI_SNAPSHOT_FILE_NAME)
|
private val abiSnapshotFile = File(workingDir, ABI_SNAPSHOT_FILE_NAME)
|
||||||
protected open val kotlinSourceFilesExtensions: List<String> = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
protected open val kotlinSourceFilesExtensions: List<String> = DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
|
||||||
|
|
||||||
protected abstract fun createCacheManager(args: Args, projectDir: File?, transaction: CompilationTransaction): CacheManager
|
/**
|
||||||
|
* Creates an instance of [IncrementalCompilationContext] that holds common incremental compilation context mostly required for [CacheManager]
|
||||||
|
*/
|
||||||
|
protected abstract fun createIncrementalCompilationContext(
|
||||||
|
projectDir: File?,
|
||||||
|
transaction: CompilationTransaction
|
||||||
|
): IncrementalCompilationContext
|
||||||
|
|
||||||
|
protected abstract fun createCacheManager(icContext: IncrementalCompilationContext, args: Args): CacheManager
|
||||||
protected abstract fun destinationDir(args: Args): File
|
protected abstract fun destinationDir(args: Args): File
|
||||||
|
|
||||||
fun compile(
|
fun compile(
|
||||||
@@ -159,7 +167,8 @@ abstract class IncrementalCompilerRunner<
|
|||||||
changedFiles as ChangedFiles.Known?
|
changedFiles as ChangedFiles.Known?
|
||||||
|
|
||||||
createTransaction().use { transaction ->
|
createTransaction().use { transaction ->
|
||||||
val caches = createCacheManager(args, projectDir, transaction)
|
val icContext = createIncrementalCompilationContext(projectDir, transaction)
|
||||||
|
val caches = createCacheManager(icContext, args)
|
||||||
|
|
||||||
fun compile(): ICResult {
|
fun compile(): ICResult {
|
||||||
// Step 1: Get changed files
|
// Step 1: Get changed files
|
||||||
@@ -199,13 +208,13 @@ abstract class IncrementalCompilerRunner<
|
|||||||
// Step 3: Compile incrementally
|
// Step 3: Compile incrementally
|
||||||
val exitCode = try {
|
val exitCode = try {
|
||||||
compileImpl(
|
compileImpl(
|
||||||
|
icContext,
|
||||||
compilationMode as CompilationMode.Incremental,
|
compilationMode as CompilationMode.Incremental,
|
||||||
allSourceFiles,
|
allSourceFiles,
|
||||||
args,
|
args,
|
||||||
caches,
|
caches,
|
||||||
abiSnapshotData,
|
abiSnapshotData,
|
||||||
messageCollector,
|
messageCollector,
|
||||||
transaction
|
|
||||||
)
|
)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
return ICResult.Failed(IC_FAILED_TO_COMPILE_INCREMENTALLY, e)
|
return ICResult.Failed(IC_FAILED_TO_COMPILE_INCREMENTALLY, e)
|
||||||
@@ -269,8 +278,8 @@ abstract class IncrementalCompilerRunner<
|
|||||||
reporter.debug { "Cleaning ${outputDirsToClean.size} output directories" }
|
reporter.debug { "Cleaning ${outputDirsToClean.size} output directories" }
|
||||||
cleanOrCreateDirectories(outputDirsToClean)
|
cleanOrCreateDirectories(outputDirsToClean)
|
||||||
}
|
}
|
||||||
val transaction = DummyCompilationTransaction()
|
val icContext = createIncrementalCompilationContext(projectDir, DummyCompilationTransaction())
|
||||||
return createCacheManager(args, projectDir, transaction).use { caches ->
|
return createCacheManager(icContext, args).use { caches ->
|
||||||
if (trackChangedFiles) {
|
if (trackChangedFiles) {
|
||||||
caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles)
|
caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles)
|
||||||
}
|
}
|
||||||
@@ -278,7 +287,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
AbiSnapshotData(snapshot = AbiSnapshotImpl(mutableMapOf()), classpathAbiSnapshot = getClasspathAbiSnapshot(args))
|
AbiSnapshotData(snapshot = AbiSnapshotImpl(mutableMapOf()), classpathAbiSnapshot = getClasspathAbiSnapshot(args))
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
compileImpl(CompilationMode.Rebuild(rebuildReason), allSourceFiles, args, caches, abiSnapshotData, messageCollector, transaction)
|
compileImpl(icContext, CompilationMode.Rebuild(rebuildReason), allSourceFiles, args, caches, abiSnapshotData, messageCollector)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,18 +395,18 @@ abstract class IncrementalCompilerRunner<
|
|||||||
): Pair<ExitCode, Collection<File>>
|
): Pair<ExitCode, Collection<File>>
|
||||||
|
|
||||||
private fun compileImpl(
|
private fun compileImpl(
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
compilationMode: CompilationMode,
|
compilationMode: CompilationMode,
|
||||||
allSourceFiles: List<File>,
|
allSourceFiles: List<File>,
|
||||||
args: Args,
|
args: Args,
|
||||||
caches: CacheManager,
|
caches: CacheManager,
|
||||||
abiSnapshotData: AbiSnapshotData?, // Not null iff withAbiSnapshot = true
|
abiSnapshotData: AbiSnapshotData?, // Not null iff withAbiSnapshot = true
|
||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
transaction: CompilationTransaction,
|
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
performWorkBeforeCompilation(compilationMode, args)
|
performWorkBeforeCompilation(compilationMode, args)
|
||||||
|
|
||||||
val allKotlinFiles = allSourceFiles.filter { it.isKotlinFile(kotlinSourceFilesExtensions) }
|
val allKotlinFiles = allSourceFiles.filter { it.isKotlinFile(kotlinSourceFilesExtensions) }
|
||||||
val exitCode = doCompile(compilationMode, allKotlinFiles, args, caches, abiSnapshotData, messageCollector, transaction)
|
val exitCode = doCompile(icContext, caches, compilationMode, allKotlinFiles, args, abiSnapshotData, messageCollector)
|
||||||
|
|
||||||
performWorkAfterCompilation(compilationMode, exitCode, caches)
|
performWorkAfterCompilation(compilationMode, exitCode, caches)
|
||||||
return exitCode
|
return exitCode
|
||||||
@@ -426,13 +435,13 @@ abstract class IncrementalCompilerRunner<
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun doCompile(
|
private fun doCompile(
|
||||||
|
icContext: IncrementalCompilationContext,
|
||||||
|
caches: CacheManager,
|
||||||
compilationMode: CompilationMode,
|
compilationMode: CompilationMode,
|
||||||
allKotlinSources: List<File>,
|
allKotlinSources: List<File>,
|
||||||
args: Args,
|
args: Args,
|
||||||
caches: CacheManager,
|
|
||||||
abiSnapshotData: AbiSnapshotData?, // Not null iff withAbiSnapshot = true
|
abiSnapshotData: AbiSnapshotData?, // Not null iff withAbiSnapshot = true
|
||||||
originalMessageCollector: MessageCollector,
|
originalMessageCollector: MessageCollector,
|
||||||
transaction: CompilationTransaction,
|
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
val dirtySources = when (compilationMode) {
|
val dirtySources = when (compilationMode) {
|
||||||
is CompilationMode.Incremental -> compilationMode.dirtyFiles.toMutableLinkedSet()
|
is CompilationMode.Incremental -> compilationMode.dirtyFiles.toMutableLinkedSet()
|
||||||
@@ -443,6 +452,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
|
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||||
val buildDirtyFqNames = HashSet<FqName>()
|
val buildDirtyFqNames = HashSet<FqName>()
|
||||||
val allDirtySources = HashSet<File>()
|
val allDirtySources = HashSet<File>()
|
||||||
|
val transaction = icContext.transaction
|
||||||
|
|
||||||
var exitCode = ExitCode.OK
|
var exitCode = ExitCode.OK
|
||||||
|
|
||||||
@@ -454,7 +464,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
val complementaryFiles = caches.platformCache.getComplementaryFilesRecursive(dirtySources)
|
val complementaryFiles = caches.platformCache.getComplementaryFilesRecursive(dirtySources)
|
||||||
dirtySources.addAll(complementaryFiles)
|
dirtySources.addAll(complementaryFiles)
|
||||||
caches.platformCache.markDirty(dirtySources)
|
caches.platformCache.markDirty(dirtySources)
|
||||||
caches.inputsCache.removeOutputForSourceFiles(dirtySources, transaction)
|
caches.inputsCache.removeOutputForSourceFiles(dirtySources)
|
||||||
|
|
||||||
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
|
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
|
||||||
val expectActualTracker = ExpectActualTrackerImpl()
|
val expectActualTracker = ExpectActualTrackerImpl()
|
||||||
|
|||||||
+1
-1
@@ -259,7 +259,7 @@ class IncrementalFirJvmCompilerRunner(
|
|||||||
else -> it + newDirtyFilesOutputsScope
|
else -> it + newDirtyFilesOutputsScope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
caches.inputsCache.removeOutputForSourceFiles(newDirtySources, DummyCompilationTransaction())
|
caches.inputsCache.removeOutputForSourceFiles(newDirtySources)
|
||||||
newDirtySources.forEach {
|
newDirtySources.forEach {
|
||||||
dirtySources.add(KtIoFileSourceFile(it))
|
dirtySources.add(KtIoFileSourceFile(it))
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-10
@@ -98,18 +98,16 @@ class IncrementalJsCompilerRunner(
|
|||||||
withAbiSnapshot = withAbiSnapshot,
|
withAbiSnapshot = withAbiSnapshot,
|
||||||
preciseCompilationResultsBackup = preciseCompilationResultsBackup,
|
preciseCompilationResultsBackup = preciseCompilationResultsBackup,
|
||||||
) {
|
) {
|
||||||
|
override fun createIncrementalCompilationContext(projectDir: File?, transaction: CompilationTransaction) =
|
||||||
override fun createCacheManager(args: K2JSCompilerArguments, projectDir: File?, transaction: CompilationTransaction): IncrementalJsCachesManager {
|
IncrementalCompilationContext(
|
||||||
val serializerProtocol = if (!args.isIrBackendEnabled()) JsSerializerProtocol else KlibMetadataSerializerProtocol
|
|
||||||
return IncrementalJsCachesManager(
|
|
||||||
cacheDirectory,
|
|
||||||
projectDir,
|
|
||||||
reporter,
|
|
||||||
serializerProtocol,
|
|
||||||
storeFullFqNamesInLookupCache = withAbiSnapshot,
|
|
||||||
transaction = transaction,
|
transaction = transaction,
|
||||||
|
rootProjectDir = projectDir,
|
||||||
|
reporter = reporter,
|
||||||
|
storeFullFqNamesInLookupCache = withAbiSnapshot,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
override fun createCacheManager(icContext: IncrementalCompilationContext, args: K2JSCompilerArguments) =
|
||||||
|
IncrementalJsCachesManager(icContext, if (!args.isIrBackendEnabled()) JsSerializerProtocol else KlibMetadataSerializerProtocol, cacheDirectory)
|
||||||
|
|
||||||
override fun destinationDir(args: K2JSCompilerArguments): File {
|
override fun destinationDir(args: K2JSCompilerArguments): File {
|
||||||
return if (args.isIrBackendEnabled())
|
return if (args.isIrBackendEnabled())
|
||||||
|
|||||||
+9
-8
@@ -150,17 +150,18 @@ open class IncrementalJvmCompilerRunner(
|
|||||||
withAbiSnapshot = withAbiSnapshot,
|
withAbiSnapshot = withAbiSnapshot,
|
||||||
preciseCompilationResultsBackup = preciseCompilationResultsBackup,
|
preciseCompilationResultsBackup = preciseCompilationResultsBackup,
|
||||||
) {
|
) {
|
||||||
override fun createCacheManager(args: K2JVMCompilerArguments, projectDir: File?, transaction: CompilationTransaction): IncrementalJvmCachesManager =
|
override fun createIncrementalCompilationContext(projectDir: File?, transaction: CompilationTransaction) =
|
||||||
IncrementalJvmCachesManager(
|
IncrementalCompilationContext(
|
||||||
cacheDirectory,
|
|
||||||
projectDir,
|
|
||||||
File(args.destination),
|
|
||||||
reporter,
|
|
||||||
storeFullFqNamesInLookupCache = withAbiSnapshot || classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled,
|
|
||||||
trackChangesInLookupCache = classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun,
|
|
||||||
transaction = transaction,
|
transaction = transaction,
|
||||||
|
rootProjectDir = projectDir,
|
||||||
|
reporter = reporter,
|
||||||
|
trackChangesInLookupCache = classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun,
|
||||||
|
storeFullFqNamesInLookupCache = withAbiSnapshot || classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun createCacheManager(icContext: IncrementalCompilationContext, args: K2JVMCompilerArguments) =
|
||||||
|
IncrementalJvmCachesManager(icContext, args.destination?.let { File(it) }, cacheDirectory)
|
||||||
|
|
||||||
override fun destinationDir(args: K2JVMCompilerArguments): File =
|
override fun destinationDir(args: K2JVMCompilerArguments): File =
|
||||||
args.destinationAsFile
|
args.destinationAsFile
|
||||||
|
|
||||||
|
|||||||
+6
-12
@@ -18,35 +18,29 @@ package org.jetbrains.kotlin.incremental
|
|||||||
|
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.build.GeneratedFile
|
import org.jetbrains.kotlin.build.GeneratedFile
|
||||||
import org.jetbrains.kotlin.build.report.ICReporter
|
|
||||||
import org.jetbrains.kotlin.build.report.debug
|
import org.jetbrains.kotlin.build.report.debug
|
||||||
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
|
import org.jetbrains.kotlin.incremental.snapshots.FileSnapshotMap
|
||||||
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.SourceToOutputFilesMap
|
import org.jetbrains.kotlin.incremental.storage.SourceToOutputFilesMap
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class InputsCache(
|
class InputsCache(
|
||||||
workingDir: File,
|
workingDir: File,
|
||||||
private val reporter: ICReporter,
|
private val icContext: IncrementalCompilationContext,
|
||||||
pathConverter: FileToPathConverter
|
|
||||||
) : BasicMapsOwner(workingDir) {
|
) : BasicMapsOwner(workingDir) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val SOURCE_SNAPSHOTS = "source-snapshot"
|
private const val SOURCE_SNAPSHOTS = "source-snapshot"
|
||||||
private const val SOURCE_TO_OUTPUT_FILES = "source-to-output"
|
private const val SOURCE_TO_OUTPUT_FILES = "source-to-output"
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile, pathConverter))
|
internal val sourceSnapshotMap = registerMap(FileSnapshotMap(SOURCE_SNAPSHOTS.storageFile, icContext))
|
||||||
private val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile, pathConverter))
|
private val sourceToOutputMap = registerMap(SourceToOutputFilesMap(SOURCE_TO_OUTPUT_FILES.storageFile, icContext))
|
||||||
|
|
||||||
fun removeOutputForSourceFiles(
|
fun removeOutputForSourceFiles(sources: Iterable<File>) {
|
||||||
sources: Iterable<File>,
|
|
||||||
transaction: CompilationTransaction,
|
|
||||||
) {
|
|
||||||
for (sourceFile in sources) {
|
for (sourceFile in sources) {
|
||||||
sourceToOutputMap.remove(sourceFile).forEach {
|
sourceToOutputMap.remove(sourceFile).forEach {
|
||||||
reporter.debug { "Deleting $it on clearing cache for $sourceFile" }
|
icContext.reporter.debug { "Deleting $it on clearing cache for $sourceFile" }
|
||||||
transaction.deleteFile(it.toPath())
|
icContext.transaction.deleteFile(it.toPath())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -203,7 +203,8 @@ object ClasspathChangesComputer {
|
|||||||
): ProgramSymbolSet {
|
): ProgramSymbolSet {
|
||||||
val workingDir =
|
val workingDir =
|
||||||
FileUtil.createTempDirectory(this::class.java.simpleName, "_WorkingDir_${UUID.randomUUID()}", /* deleteOnExit */ true)
|
FileUtil.createTempDirectory(this::class.java.simpleName, "_WorkingDir_${UUID.randomUUID()}", /* deleteOnExit */ true)
|
||||||
val incrementalJvmCache = IncrementalJvmCache(workingDir, /* targetOutputDir */ null, FileToAbsolutePathConverter)
|
val icContext = IncrementalCompilationContext(pathConverter = FileToAbsolutePathConverter)
|
||||||
|
val incrementalJvmCache = IncrementalJvmCache(workingDir, icContext, null)
|
||||||
|
|
||||||
// Step 1:
|
// Step 1:
|
||||||
// - Add previous class snapshots to incrementalJvmCache.
|
// - Add previous class snapshots to incrementalJvmCache.
|
||||||
|
|||||||
+3
-3
@@ -17,16 +17,16 @@
|
|||||||
package org.jetbrains.kotlin.incremental.snapshots
|
package org.jetbrains.kotlin.incremental.snapshots
|
||||||
|
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
|
import org.jetbrains.kotlin.incremental.storage.BasicStringMap
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
|
import org.jetbrains.kotlin.incremental.storage.PathStringDescriptor
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class FileSnapshotMap(
|
class FileSnapshotMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer) {
|
) : BasicStringMap<FileSnapshot>(storageFile, PathStringDescriptor, FileSnapshotExternalizer, icContext) {
|
||||||
|
|
||||||
override fun dumpValue(value: FileSnapshot): String =
|
override fun dumpValue(value: FileSnapshot): String =
|
||||||
value.toString()
|
value.toString()
|
||||||
|
|||||||
+3
-3
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.dumpCollection
|
import org.jetbrains.kotlin.incremental.dumpCollection
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class SourceToOutputFilesMap(
|
class SourceToOutputFilesMap(
|
||||||
storageFile: File,
|
storageFile: File,
|
||||||
private val pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer, icContext) {
|
||||||
|
|
||||||
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
||||||
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
|
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-3
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.incremental.snapshots
|
package org.jetbrains.kotlin.incremental.snapshots
|
||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
||||||
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@@ -17,15 +18,17 @@ import kotlin.properties.Delegates
|
|||||||
|
|
||||||
class FileSnapshotMapTest : TestWithWorkingDir() {
|
class FileSnapshotMapTest : TestWithWorkingDir() {
|
||||||
private var snapshotMap: FileSnapshotMap by Delegates.notNull()
|
private var snapshotMap: FileSnapshotMap by Delegates.notNull()
|
||||||
private var pathConverter: FileToPathConverter by Delegates.notNull()
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
val caches = File(workingDir, "caches").apply { mkdirs() }
|
val caches = File(workingDir, "caches").apply { mkdirs() }
|
||||||
val snapshotMapFile = File(caches, "snapshots.tab")
|
val snapshotMapFile = File(caches, "snapshots.tab")
|
||||||
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
val pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
||||||
snapshotMap = FileSnapshotMap(snapshotMapFile, pathConverter)
|
val icContext = IncrementalCompilationContext(
|
||||||
|
pathConverter = pathConverter
|
||||||
|
)
|
||||||
|
snapshotMap = FileSnapshotMap(snapshotMapFile, icContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
+5
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertArrayEquals
|
import org.junit.Assert.assertArrayEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -23,7 +24,10 @@ class SourceToOutputFilesMapTest : TestWithWorkingDir() {
|
|||||||
val caches = File(workingDir, "caches").apply { mkdirs() }
|
val caches = File(workingDir, "caches").apply { mkdirs() }
|
||||||
val stofMapFile = File(caches, "stof.tab")
|
val stofMapFile = File(caches, "stof.tab")
|
||||||
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
||||||
stofMap = SourceToOutputFilesMap(stofMapFile, pathConverter)
|
val icContext = IncrementalCompilationContext(
|
||||||
|
pathConverter = pathConverter
|
||||||
|
)
|
||||||
|
stofMap = SourceToOutputFilesMap(stofMapFile, icContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ import org.jetbrains.jps.incremental.fs.CompilationRound
|
|||||||
import org.jetbrains.jps.incremental.messages.BuildMessage
|
import org.jetbrains.jps.incremental.messages.BuildMessage
|
||||||
import org.jetbrains.jps.incremental.messages.CompilerMessage
|
import org.jetbrains.jps.incremental.messages.CompilerMessage
|
||||||
import org.jetbrains.kotlin.build.joinToReadableString
|
import org.jetbrains.kotlin.build.joinToReadableString
|
||||||
|
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
||||||
import org.jetbrains.kotlin.config.CompilerRunnerConstants.KOTLIN_COMPILER_NAME
|
import org.jetbrains.kotlin.config.CompilerRunnerConstants.KOTLIN_COMPILER_NAME
|
||||||
|
import org.jetbrains.kotlin.incremental.DummyCompilationTransaction
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.LookupSymbol
|
import org.jetbrains.kotlin.incremental.LookupSymbol
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
||||||
import org.jetbrains.kotlin.jps.KotlinJpsBundle
|
import org.jetbrains.kotlin.jps.KotlinJpsBundle
|
||||||
@@ -81,7 +84,9 @@ class KotlinCompileContext(val jpsContext: CompileContext) {
|
|||||||
val fileToPathConverter: FileToPathConverter =
|
val fileToPathConverter: FileToPathConverter =
|
||||||
JpsFileToPathConverter(jpsContext.projectDescriptor.project)
|
JpsFileToPathConverter(jpsContext.projectDescriptor.project)
|
||||||
|
|
||||||
val lookupStorageManager = JpsLookupStorageManager(dataManager, fileToPathConverter)
|
val icContext = IncrementalCompilationContext(pathConverter = fileToPathConverter)
|
||||||
|
|
||||||
|
val lookupStorageManager = JpsLookupStorageManager(dataManager, icContext)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to prevent rebuilding twice.
|
* Flag to prevent rebuilding twice.
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ import org.jetbrains.jps.builders.storage.StorageProvider
|
|||||||
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
import org.jetbrains.jps.incremental.ModuleBuildTarget
|
||||||
import org.jetbrains.jps.incremental.storage.BuildDataManager
|
import org.jetbrains.jps.incremental.storage.BuildDataManager
|
||||||
import org.jetbrains.jps.incremental.storage.StorageOwner
|
import org.jetbrains.jps.incremental.storage.StorageOwner
|
||||||
import org.jetbrains.kotlin.incremental.DummyCompilationTransaction
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalCacheCommon
|
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalJsCache
|
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalJvmCache
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
||||||
import org.jetbrains.kotlin.jps.build.KotlinBuilder
|
import org.jetbrains.kotlin.jps.build.KotlinBuilder
|
||||||
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
|
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
|
||||||
@@ -38,8 +35,8 @@ interface JpsIncrementalCache : IncrementalCacheCommon, StorageOwner {
|
|||||||
class JpsIncrementalJvmCache(
|
class JpsIncrementalJvmCache(
|
||||||
target: ModuleBuildTarget,
|
target: ModuleBuildTarget,
|
||||||
paths: BuildDataPaths,
|
paths: BuildDataPaths,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext
|
||||||
) : IncrementalJvmCache(paths.getTargetDataRoot(target), target.outputDir, pathConverter), JpsIncrementalCache {
|
) : IncrementalJvmCache(paths.getTargetDataRoot(target), icContext, target.outputDir), JpsIncrementalCache {
|
||||||
override fun addJpsDependentCache(cache: JpsIncrementalCache) {
|
override fun addJpsDependentCache(cache: JpsIncrementalCache) {
|
||||||
if (cache is JpsIncrementalJvmCache) {
|
if (cache is JpsIncrementalJvmCache) {
|
||||||
addDependentCache(cache)
|
addDependentCache(cache)
|
||||||
@@ -54,8 +51,8 @@ class JpsIncrementalJvmCache(
|
|||||||
class JpsIncrementalJsCache(
|
class JpsIncrementalJsCache(
|
||||||
target: ModuleBuildTarget,
|
target: ModuleBuildTarget,
|
||||||
paths: BuildDataPaths,
|
paths: BuildDataPaths,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext
|
||||||
) : IncrementalJsCache(paths.getTargetDataRoot(target), pathConverter, JsSerializerProtocol, DummyCompilationTransaction()), JpsIncrementalCache {
|
) : IncrementalJsCache(paths.getTargetDataRoot(target), icContext, JsSerializerProtocol), JpsIncrementalCache {
|
||||||
override fun addJpsDependentCache(cache: JpsIncrementalCache) {
|
override fun addJpsDependentCache(cache: JpsIncrementalCache) {
|
||||||
if (cache is JpsIncrementalJsCache) {
|
if (cache is JpsIncrementalJsCache) {
|
||||||
addDependentCache(cache)
|
addDependentCache(cache)
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import org.jetbrains.jps.builders.storage.BuildDataCorruptedException
|
|||||||
import org.jetbrains.jps.builders.storage.StorageProvider
|
import org.jetbrains.jps.builders.storage.StorageProvider
|
||||||
import org.jetbrains.jps.incremental.storage.BuildDataManager
|
import org.jetbrains.jps.incremental.storage.BuildDataManager
|
||||||
import org.jetbrains.jps.incremental.storage.StorageOwner
|
import org.jetbrains.jps.incremental.storage.StorageOwner
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.LookupStorage
|
import org.jetbrains.kotlin.incremental.LookupStorage
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ private object LookupStorageLock
|
|||||||
|
|
||||||
class JpsLookupStorageManager(
|
class JpsLookupStorageManager(
|
||||||
private val buildDataManager: BuildDataManager,
|
private val buildDataManager: BuildDataManager,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext,
|
||||||
) {
|
) {
|
||||||
private val storageProvider = JpsLookupStorageProvider(pathConverter)
|
private val storageProvider = JpsLookupStorageProvider(icContext)
|
||||||
|
|
||||||
fun cleanLookupStorage(log: Logger) {
|
fun cleanLookupStorage(log: Logger) {
|
||||||
synchronized(LookupStorageLock) {
|
synchronized(LookupStorageLock) {
|
||||||
@@ -58,14 +58,14 @@ class JpsLookupStorageManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class JpsLookupStorageProvider(
|
private class JpsLookupStorageProvider(
|
||||||
private val pathConverter: FileToPathConverter
|
private val icContext: IncrementalCompilationContext
|
||||||
) : StorageProvider<JpsLookupStorage>() {
|
) : StorageProvider<JpsLookupStorage>() {
|
||||||
override fun createStorage(targetDataDir: File): JpsLookupStorage =
|
override fun createStorage(targetDataDir: File): JpsLookupStorage =
|
||||||
JpsLookupStorage(targetDataDir, pathConverter)
|
JpsLookupStorage(targetDataDir, icContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JpsLookupStorage(
|
private class JpsLookupStorage(
|
||||||
targetDataDir: File,
|
targetDataDir: File,
|
||||||
pathConverter: FileToPathConverter
|
icContext: IncrementalCompilationContext
|
||||||
) : StorageOwner, LookupStorage(targetDataDir, pathConverter)
|
) : StorageOwner, LookupStorage(targetDataDir, icContext)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ class KotlinJsModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleBu
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun createCacheStorage(paths: BuildDataPaths) =
|
override fun createCacheStorage(paths: BuildDataPaths) =
|
||||||
JpsIncrementalJsCache(jpsModuleBuildTarget, paths, kotlinContext.fileToPathConverter)
|
JpsIncrementalJsCache(jpsModuleBuildTarget, paths, kotlinContext.icContext)
|
||||||
|
|
||||||
override fun updateCaches(
|
override fun updateCaches(
|
||||||
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
dirtyFilesHolder: KotlinDirtySourceFilesHolder,
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class KotlinJvmModuleBuildTarget(kotlinContext: KotlinCompileContext, jpsModuleB
|
|||||||
get() = IncrementalCompilation.isEnabledForJvm()
|
get() = IncrementalCompilation.isEnabledForJvm()
|
||||||
|
|
||||||
override fun createCacheStorage(paths: BuildDataPaths) =
|
override fun createCacheStorage(paths: BuildDataPaths) =
|
||||||
JpsIncrementalJvmCache(jpsModuleBuildTarget, paths, kotlinContext.fileToPathConverter)
|
JpsIncrementalJvmCache(jpsModuleBuildTarget, paths, kotlinContext.icContext)
|
||||||
|
|
||||||
override val compilerArgumentsFileName
|
override val compilerArgumentsFileName
|
||||||
get() = JVM_BUILD_META_INFO_FILE_NAME
|
get() = JVM_BUILD_META_INFO_FILE_NAME
|
||||||
|
|||||||
Reference in New Issue
Block a user