Checking for constants values in incremental compiler.
This commit is contained in:
+43
-4
@@ -30,16 +30,39 @@ import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader
|
|||||||
import org.jetbrains.jet.descriptors.serialization.BitEncoding
|
import org.jetbrains.jet.descriptors.serialization.BitEncoding
|
||||||
import org.jetbrains.jet.utils.intellij.*
|
import org.jetbrains.jet.utils.intellij.*
|
||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
|
import com.intellij.util.io.IntInlineKeyDescriptor
|
||||||
|
import org.jetbrains.org.objectweb.asm.*
|
||||||
|
import com.intellij.util.io.EnumeratorStringDescriptor
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName
|
||||||
|
import java.util.TreeMap
|
||||||
|
|
||||||
public class IncrementalCache(baseDir: File) {
|
public class IncrementalCache(baseDir: File) {
|
||||||
class object {
|
class object {
|
||||||
val PROTO_MAP: String = "proto.tab"
|
val PROTO_MAP = "proto.tab"
|
||||||
|
val CONSTANTS_MAP = "constants.tab"
|
||||||
|
|
||||||
|
private fun getConstantsHash(bytes: ByteArray): Int {
|
||||||
|
val result = TreeMap<String, Any>() // keys order should defined to check hash of a map
|
||||||
|
|
||||||
|
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.ASM5) {
|
||||||
|
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||||
|
if (value != null) {
|
||||||
|
result[name] = value
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
|
||||||
|
|
||||||
|
return result.hashCode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val protoData: PersistentMap<ClassOrPackageId, ByteArray>
|
private val protoData: PersistentMap<ClassOrPackageId, ByteArray>
|
||||||
|
private val constantsData = PersistentHashMap(File(baseDir, CONSTANTS_MAP), EnumeratorStringDescriptor(), IntInlineKeyDescriptor())
|
||||||
|
|
||||||
{
|
;{
|
||||||
protoData = PersistentHashMap<ClassOrPackageId, ByteArray>(File(baseDir, PROTO_MAP), object : KeyDescriptor<ClassOrPackageId> {
|
protoData = PersistentHashMap(File(baseDir, PROTO_MAP), object : KeyDescriptor<ClassOrPackageId> {
|
||||||
override fun save(out: DataOutput, value: ClassOrPackageId?) {
|
override fun save(out: DataOutput, value: ClassOrPackageId?) {
|
||||||
IOUtil.writeString(value!!.moduleId, out)
|
IOUtil.writeString(value!!.moduleId, out)
|
||||||
IOUtil.writeString(value.fqName.asString(), out)
|
IOUtil.writeString(value.fqName.asString(), out)
|
||||||
@@ -74,7 +97,8 @@ public class IncrementalCache(baseDir: File) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun saveFileToCache(moduleId: String, file: File): Boolean {
|
public fun saveFileToCache(moduleId: String, file: File): Boolean {
|
||||||
val classNameAndHeader = VirtualFileKotlinClass.readClassNameAndHeader(file.readBytes())
|
val fileBytes = file.readBytes()
|
||||||
|
val classNameAndHeader = VirtualFileKotlinClass.readClassNameAndHeader(fileBytes)
|
||||||
if (classNameAndHeader == null) return false
|
if (classNameAndHeader == null) return false
|
||||||
|
|
||||||
val (className, header) = classNameAndHeader
|
val (className, header) = classNameAndHeader
|
||||||
@@ -91,6 +115,9 @@ public class IncrementalCache(baseDir: File) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
|
||||||
|
return putConstantsData(className, getConstantsHash(fileBytes))
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -105,12 +132,24 @@ public class IncrementalCache(baseDir: File) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun putConstantsData(packagePartClass: JvmClassName, constantsHash: Int): Boolean {
|
||||||
|
val key = packagePartClass.getInternalName()
|
||||||
|
|
||||||
|
val oldHash = constantsData[key]
|
||||||
|
if (oldHash == constantsHash) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
constantsData.put(key, constantsHash)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
public fun getPackageData(moduleId: String, fqName: FqName): ByteArray? {
|
public fun getPackageData(moduleId: String, fqName: FqName): ByteArray? {
|
||||||
return protoData[ClassOrPackageId(moduleId, fqName)]
|
return protoData[ClassOrPackageId(moduleId, fqName)]
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun close() {
|
public fun close() {
|
||||||
protoData.close()
|
protoData.close()
|
||||||
|
constantsData.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class ClassOrPackageId(val moduleId: String, val fqName: FqName) {
|
private data class ClassOrPackageId(val moduleId: String, val fqName: FqName) {
|
||||||
|
|||||||
@@ -16,13 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.jps.build
|
package org.jetbrains.jet.jps.build
|
||||||
|
|
||||||
import org.jetbrains.ether.IncrementalTestCase
|
|
||||||
import org.jetbrains.jps.builders.JpsBuildTestCase
|
import org.jetbrains.jps.builders.JpsBuildTestCase
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.jetbrains.jps.builders.CompileScopeTestBuilder
|
import org.jetbrains.jps.builders.CompileScopeTestBuilder
|
||||||
import org.jetbrains.jps.builders.BuildResult
|
|
||||||
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase
|
import org.jetbrains.jps.builders.impl.logging.ProjectBuilderLoggerBase
|
||||||
import org.jetbrains.jps.builders.logging.BuildLoggingManager
|
import org.jetbrains.jps.builders.logging.BuildLoggingManager
|
||||||
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
import org.jetbrains.jps.model.java.JpsJavaExtensionService
|
||||||
@@ -120,6 +118,14 @@ public class IncrementalJpsTest : JpsBuildTestCase() {
|
|||||||
doTest()
|
doTest()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun testConstantValue() {
|
||||||
|
doTest()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testConstantUnchanged() {
|
||||||
|
doTest()
|
||||||
|
}
|
||||||
|
|
||||||
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase() {
|
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase() {
|
||||||
private val logBuf = StringBuilder()
|
private val logBuf = StringBuilder()
|
||||||
public val log: String
|
public val log: String
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Cleaning output files:
|
||||||
|
out/production/module/test/TestPackage-const-*.class
|
||||||
|
out/production/module/test/TestPackage.class
|
||||||
|
End of files
|
||||||
|
Compiling files:
|
||||||
|
src/const.kt
|
||||||
|
End of files
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
val CONST = "foo"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
val CONST = "foo"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
deprecated(CONST + CONST)
|
||||||
|
class Usage
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
Cleaning output files:
|
||||||
|
out/production/module/test/TestPackage-const-*.class
|
||||||
|
out/production/module/test/TestPackage.class
|
||||||
|
End of files
|
||||||
|
Compiling files:
|
||||||
|
src/const.kt
|
||||||
|
End of files
|
||||||
|
Cleaning output files:
|
||||||
|
out/production/module/test/Usage.class
|
||||||
|
End of files
|
||||||
|
Compiling files:
|
||||||
|
src/usage.kt
|
||||||
|
End of files
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
val CONST = "foo"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
val CONST = "bar"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
deprecated(CONST + CONST)
|
||||||
|
class Usage
|
||||||
Reference in New Issue
Block a user