+25
-23
@@ -21,11 +21,8 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants
|
|||||||
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
||||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.incremental.ClassProtoData
|
|
||||||
import org.jetbrains.kotlin.incremental.Difference
|
|
||||||
import org.jetbrains.kotlin.incremental.difference as differenceImpl
|
|
||||||
import org.jetbrains.kotlin.incremental.PackagePartProtoData
|
|
||||||
import org.jetbrains.kotlin.incremental.ProtoData
|
import org.jetbrains.kotlin.incremental.ProtoData
|
||||||
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
|
import org.jetbrains.kotlin.incremental.utils.TestMessageCollector
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
||||||
@@ -72,28 +69,33 @@ abstract class AbstractJsProtoComparisonTest : AbstractProtoComparisonTest<Proto
|
|||||||
val classes = hashMapOf<ClassId, ProtoData>()
|
val classes = hashMapOf<ClassId, ProtoData>()
|
||||||
|
|
||||||
for ((sourceFile, protoBytes, _) in incrementalResults.packageParts) {
|
for ((sourceFile, protoBytes, _) in incrementalResults.packageParts) {
|
||||||
val proto = ProtoBuf.PackageFragment.parseFrom(protoBytes, JsSerializerProtocol.extensionRegistry)
|
classes.putAll(getProtoData(sourceFile, protoBytes))
|
||||||
val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
|
||||||
|
|
||||||
proto.class_List.forEach {
|
|
||||||
val classId = nameResolver.getClassId(it.fqName)
|
|
||||||
classes[classId] = ClassProtoData(it, nameResolver)
|
|
||||||
}
|
|
||||||
|
|
||||||
proto.`package`.apply {
|
|
||||||
val packageFqName = if (hasExtension(JsProtoBuf.packageFqName)) {
|
|
||||||
nameResolver.getPackageFqName(getExtension(JsProtoBuf.packageFqName))
|
|
||||||
}
|
|
||||||
else FqName.ROOT
|
|
||||||
|
|
||||||
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
|
|
||||||
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return classes
|
return classes
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun difference(oldData: ProtoData, newData: ProtoData): Difference? =
|
override fun ProtoData.toProtoData(): ProtoData? = this
|
||||||
differenceImpl(oldData, newData)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getProtoData(sourceFile: File, metadata: ByteArray): Map<ClassId, ProtoData> {
|
||||||
|
val classes = hashMapOf<ClassId, ProtoData>()
|
||||||
|
val proto = ProtoBuf.PackageFragment.parseFrom(metadata, JsSerializerProtocol.extensionRegistry)
|
||||||
|
val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
||||||
|
|
||||||
|
proto.class_List.forEach {
|
||||||
|
val classId = nameResolver.getClassId(it.fqName)
|
||||||
|
classes[classId] = ClassProtoData(it, nameResolver)
|
||||||
|
}
|
||||||
|
|
||||||
|
proto.`package`.apply {
|
||||||
|
val packageFqName = if (hasExtension(JsProtoBuf.packageFqName)) {
|
||||||
|
nameResolver.getPackageFqName(getExtension(JsProtoBuf.packageFqName))
|
||||||
|
}
|
||||||
|
else FqName.ROOT
|
||||||
|
|
||||||
|
val packagePartClassId = ClassId(packageFqName, Name.identifier(sourceFile.nameWithoutExtension.capitalize() + "Kt"))
|
||||||
|
classes[packagePartClassId] = PackagePartProtoData(this, nameResolver, packageFqName)
|
||||||
|
}
|
||||||
|
return classes
|
||||||
|
}
|
||||||
+5
-12
@@ -16,9 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.jps.incremental
|
package org.jetbrains.kotlin.jps.incremental
|
||||||
|
|
||||||
import org.jetbrains.kotlin.incremental.Difference
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.incremental.LocalFileKotlinClass
|
|
||||||
import org.jetbrains.kotlin.incremental.difference
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.ProtoMapValue
|
import org.jetbrains.kotlin.incremental.storage.ProtoMapValue
|
||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
|
||||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||||
@@ -36,25 +34,20 @@ abstract class AbstractJvmProtoComparisonTest : AbstractProtoComparisonTest<Loca
|
|||||||
return localClassFiles.associateBy { it.classId }
|
return localClassFiles.associateBy { it.classId }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun difference(oldData: LocalFileKotlinClass, newData: LocalFileKotlinClass): Difference? {
|
override fun LocalFileKotlinClass.toProtoData(): ProtoData? {
|
||||||
val oldProto = oldData.readProto() ?: return null
|
|
||||||
val newProto = newData.readProto() ?: return null
|
|
||||||
return difference(oldProto, newProto)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinJvmBinaryClass.readProto(): ProtoMapValue? {
|
|
||||||
assert(classHeader.metadataVersion.isCompatible()) { "Incompatible class ($classHeader): $location" }
|
assert(classHeader.metadataVersion.isCompatible()) { "Incompatible class ($classHeader): $location" }
|
||||||
|
|
||||||
val bytes by lazy { BitEncoding.decodeBytes(classHeader.data!!) }
|
val bytes by lazy { BitEncoding.decodeBytes(classHeader.data!!) }
|
||||||
val strings by lazy { classHeader.strings!! }
|
val strings by lazy { classHeader.strings!! }
|
||||||
|
val packageFqName = classId.packageFqName
|
||||||
|
|
||||||
return when (classHeader.kind) {
|
return when (classHeader.kind) {
|
||||||
KotlinClassHeader.Kind.CLASS -> {
|
KotlinClassHeader.Kind.CLASS -> {
|
||||||
ProtoMapValue(false, bytes, strings)
|
ProtoMapValue(false, bytes, strings).toProtoData(packageFqName)
|
||||||
}
|
}
|
||||||
KotlinClassHeader.Kind.FILE_FACADE,
|
KotlinClassHeader.Kind.FILE_FACADE,
|
||||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
||||||
ProtoMapValue(true, bytes, strings)
|
ProtoMapValue(true, bytes, strings).toProtoData(packageFqName)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
null
|
null
|
||||||
|
|||||||
+24
-15
@@ -17,7 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.jps.incremental
|
package org.jetbrains.kotlin.jps.incremental
|
||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
import org.jetbrains.kotlin.incremental.Difference
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
@@ -25,7 +25,7 @@ import java.io.File
|
|||||||
|
|
||||||
abstract class AbstractProtoComparisonTest<PROTO_DATA> : TestWithWorkingDir() {
|
abstract class AbstractProtoComparisonTest<PROTO_DATA> : TestWithWorkingDir() {
|
||||||
protected abstract fun compileAndGetClasses(sourceDir: File, outputDir: File): Map<ClassId, PROTO_DATA>
|
protected abstract fun compileAndGetClasses(sourceDir: File, outputDir: File): Map<ClassId, PROTO_DATA>
|
||||||
protected abstract fun difference(oldData: PROTO_DATA, newData: PROTO_DATA): Difference?
|
protected abstract fun PROTO_DATA.toProtoData(): ProtoData?
|
||||||
|
|
||||||
protected open fun expectedOutputFile(testDir: File): File =
|
protected open fun expectedOutputFile(testDir: File): File =
|
||||||
File(testDir, "result.out")
|
File(testDir, "result.out")
|
||||||
@@ -48,32 +48,41 @@ abstract class AbstractProtoComparisonTest<PROTO_DATA> : TestWithWorkingDir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(oldClassMap.keys.intersect(newClassMap.keys)).sortedBy { it.toString() }.forEach { classId ->
|
(oldClassMap.keys.intersect(newClassMap.keys)).sortedBy { it.toString() }.forEach { classId ->
|
||||||
val oldData = oldClassMap[classId]!!
|
val oldData = oldClassMap[classId]!!.toProtoData()
|
||||||
val newData = newClassMap[classId]!!
|
val newData = newClassMap[classId]!!.toProtoData()
|
||||||
val diff = difference(oldData, newData)
|
|
||||||
|
|
||||||
if (diff == null) {
|
if (oldData == null || newData == null) {
|
||||||
p.println("SKIPPED $classId")
|
p.println("SKIPPED $classId")
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
diff.rawProtoDifference?.let {
|
val rawProtoDifference = when {
|
||||||
|
oldData is ClassProtoData && newData is ClassProtoData -> {
|
||||||
|
ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver).difference(oldData.proto, newData.proto)
|
||||||
|
}
|
||||||
|
oldData is PackagePartProtoData && newData is PackagePartProtoData -> {
|
||||||
|
ProtoCompareGenerated(oldData.nameResolver, newData.nameResolver).difference(oldData.proto, newData.proto)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
rawProtoDifference?.let {
|
||||||
if (it.isNotEmpty()) {
|
if (it.isNotEmpty()) {
|
||||||
p.println("PROTO DIFFERENCE in $classId: ${it.sortedBy { it.name }.joinToString()}")
|
p.println("PROTO DIFFERENCE in $classId: ${it.sortedBy { it.name }.joinToString()}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val changes = arrayListOf<String>()
|
val changesInfo = ChangesCollector().apply { collectProtoChanges(oldData, newData) }.changes()
|
||||||
if (diff.isClassAffected) {
|
if (changesInfo.isEmpty()) {
|
||||||
changes.add("CLASS_SIGNATURE")
|
|
||||||
}
|
|
||||||
if (diff.changedMembersNames.isNotEmpty()) {
|
|
||||||
changes.add("MEMBERS\n ${diff.changedMembersNames.sorted()}")
|
|
||||||
}
|
|
||||||
if (changes.isEmpty()) {
|
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val changes = changesInfo.map {
|
||||||
|
when (it) {
|
||||||
|
is ChangeInfo.SignatureChanged -> "CLASS_SIGNATURE"
|
||||||
|
is ChangeInfo.MembersChanged -> "MEMBERS\n ${it.names.sorted()}"
|
||||||
|
}
|
||||||
|
}.sorted()
|
||||||
|
|
||||||
p.println("CHANGES in $classId: ${changes.joinToString()}")
|
p.println("CHANGES in $classId: ${changes.joinToString()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -314,8 +314,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
|
|
||||||
context.checkCanceled()
|
context.checkCanceled()
|
||||||
|
|
||||||
val changesInfo = generatedFiles.entries.fold(CompilationResult.NO_CHANGES) { acc, (target, files) ->
|
val changesCollector = ChangesCollector()
|
||||||
acc + updateIncrementalCache(files, incrementalCaches[target]!!)
|
for ((target, files) in generatedFiles) {
|
||||||
|
updateIncrementalCache(files, incrementalCaches[target]!!, changesCollector)
|
||||||
}
|
}
|
||||||
updateLookupStorage(chunk, lookupTracker, dataManager, dirtyFilesHolder, filesToCompile)
|
updateLookupStorage(chunk, lookupTracker, dataManager, dirtyFilesHolder, filesToCompile)
|
||||||
|
|
||||||
@@ -323,7 +324,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
return OK
|
return OK
|
||||||
}
|
}
|
||||||
|
|
||||||
changesInfo.processChangesUsingLookups(filesToCompile.values().toSet(), dataManager, fsOperations, incrementalCaches.values)
|
changesCollector.processChangesUsingLookups(filesToCompile.values().toSet(), dataManager, fsOperations, incrementalCaches.values)
|
||||||
|
|
||||||
return OK
|
return OK
|
||||||
}
|
}
|
||||||
@@ -432,7 +433,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
|||||||
for (target in chunk.targets) {
|
for (target in chunk.targets) {
|
||||||
val cache = incrementalCaches[target]!!
|
val cache = incrementalCaches[target]!!
|
||||||
val removedAndDirtyFiles = filesToCompile[target] + dirtyFilesHolder.getRemovedFiles(target).map(::File)
|
val removedAndDirtyFiles = filesToCompile[target] + dirtyFilesHolder.getRemovedFiles(target).map(::File)
|
||||||
cache.markOutputClassesDirty(removedAndDirtyFiles)
|
cache.markDirty(removedAndDirtyFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,7 +775,7 @@ private class JpsICReporter : ICReporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CompilationResult.processChangesUsingLookups(
|
private fun ChangesCollector.processChangesUsingLookups(
|
||||||
compiledFiles: Set<File>,
|
compiledFiles: Set<File>,
|
||||||
dataManager: BuildDataManager,
|
dataManager: BuildDataManager,
|
||||||
fsOperations: FSOperationsHelper,
|
fsOperations: FSOperationsHelper,
|
||||||
|
|||||||
Reference in New Issue
Block a user