KT-45777: Reorganize unit test data for classpath snapshot feature
to make it easier to add more tests in the next commits. - Add unit tests for constants and inline functions Also add tests for different kinds of Kotlin classes: CLASS, FILE_FACADE, MULTIFILE_CLASS. -Add unit test for nested classes Also remove the existing integration test for nested classes to keep the integration tests focused on the key scenarios while unit tests will cover the corner cases. Ignore inline functions that are private
This commit is contained in:
committed by
nataliya.valtman
parent
534cf0c6c8
commit
a900f2b66d
Generated
+1
@@ -1,6 +1,7 @@
|
|||||||
<component name="ProjectDictionaryState">
|
<component name="ProjectDictionaryState">
|
||||||
<dictionary name="hungnv">
|
<dictionary name="hungnv">
|
||||||
<words>
|
<words>
|
||||||
|
<w>multifile</w>
|
||||||
<w>shrinker</w>
|
<w>shrinker</w>
|
||||||
<w>snapshotter</w>
|
<w>snapshotter</w>
|
||||||
<w>snapshotter's</w>
|
<w>snapshotter's</w>
|
||||||
|
|||||||
@@ -652,8 +652,10 @@ private fun getConstantsMap(bytes: ByteArray): LinkedHashMap<String, Any> {
|
|||||||
|
|
||||||
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||||
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? {
|
||||||
val staticFinal = Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_PRIVATE
|
if (access and Opcodes.ACC_PRIVATE == Opcodes.ACC_PRIVATE) return null
|
||||||
if (value != null && access and staticFinal == Opcodes.ACC_STATIC or Opcodes.ACC_FINAL) {
|
|
||||||
|
val staticFinal = Opcodes.ACC_STATIC or Opcodes.ACC_FINAL
|
||||||
|
if (value != null && access and staticFinal == staticFinal) {
|
||||||
result[name] = value
|
result[name] = value
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
@@ -689,7 +691,9 @@ private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray):
|
|||||||
desc: String,
|
desc: String,
|
||||||
signature: String?,
|
signature: String?,
|
||||||
exceptions: Array<out String>?
|
exceptions: Array<out String>?
|
||||||
): MethodVisitor {
|
): MethodVisitor? {
|
||||||
|
if (access and Opcodes.ACC_PRIVATE == Opcodes.ACC_PRIVATE) return null
|
||||||
|
|
||||||
val dummyClassWriter = ClassWriter(0)
|
val dummyClassWriter = ClassWriter(0)
|
||||||
dummyClassWriter.visit(dummyVersion, 0, "dummy", null, AsmTypes.OBJECT_TYPE.internalName, null)
|
dummyClassWriter.visit(dummyVersion, 0, "dummy", null, AsmTypes.OBJECT_TYPE.internalName, null)
|
||||||
|
|
||||||
|
|||||||
@@ -204,6 +204,9 @@ object ConstantExternalizer : DataExternalizer<Any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The constants' values are provided by ASM, so their types can only be the following.
|
||||||
|
// See https://asm.ow2.io/javadoc/org/objectweb/asm/ClassVisitor.html#visitField(int,java.lang.String,java.lang.String,java.lang.String,java.lang.Object)
|
||||||
|
// (Note: Boolean constants have Integer (0, 1) values in ASM.)
|
||||||
private enum class Kind {
|
private enum class Kind {
|
||||||
INT, FLOAT, LONG, DOUBLE, STRING
|
INT, FLOAT, LONG, DOUBLE, STRING
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -143,7 +143,7 @@ internal fun ClasspathSnapshot.removeDuplicateAndInaccessibleClasses(): List<Cla
|
|||||||
*
|
*
|
||||||
* If there are duplicate classes on the classpath, retain only the first one to match the compiler's behavior.
|
* If there are duplicate classes on the classpath, retain only the first one to match the compiler's behavior.
|
||||||
*/
|
*/
|
||||||
internal fun ClasspathSnapshot.getNonDuplicateClassSnapshots(): List<ClassSnapshotWithHash> {
|
private fun ClasspathSnapshot.getNonDuplicateClassSnapshots(): List<ClassSnapshotWithHash> {
|
||||||
val classSnapshots = LinkedHashMap<String, ClassSnapshotWithHash>(classpathEntrySnapshots.sumOf { it.classSnapshots.size })
|
val classSnapshots = LinkedHashMap<String, ClassSnapshotWithHash>(classpathEntrySnapshots.sumOf { it.classSnapshots.size })
|
||||||
for (classpathEntrySnapshot in classpathEntrySnapshots) {
|
for (classpathEntrySnapshot in classpathEntrySnapshots) {
|
||||||
for ((unixStyleRelativePath, classSnapshot) in classpathEntrySnapshot.classSnapshots) {
|
for ((unixStyleRelativePath, classSnapshot) in classpathEntrySnapshot.classSnapshots) {
|
||||||
|
|||||||
+159
-133
@@ -8,9 +8,8 @@ package org.jetbrains.kotlin.incremental.classpathDiff
|
|||||||
import org.jetbrains.kotlin.build.report.metrics.DoNothingBuildMetricsReporter
|
import org.jetbrains.kotlin.build.report.metrics.DoNothingBuildMetricsReporter
|
||||||
import org.jetbrains.kotlin.incremental.ChangesEither
|
import org.jetbrains.kotlin.incremental.ChangesEither
|
||||||
import org.jetbrains.kotlin.incremental.LookupSymbol
|
import org.jetbrains.kotlin.incremental.LookupSymbol
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.compileAll
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.snapshot
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.snapshot
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.CompileUtil.compileAll
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.snapshotAll
|
|
||||||
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
|
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
@@ -21,20 +20,16 @@ import kotlin.test.fail
|
|||||||
|
|
||||||
abstract class ClasspathChangesComputerTest : ClasspathSnapshotTestCommon() {
|
abstract class ClasspathChangesComputerTest : ClasspathSnapshotTestCommon() {
|
||||||
|
|
||||||
// TODO Add more test cases:
|
companion object {
|
||||||
// - private/non-private fields
|
val testDataDir =
|
||||||
// - inline functions
|
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest")
|
||||||
// - changing supertype by adding somethings that changes/does not change the supertype ABI
|
}
|
||||||
// - adding an annotation
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
abstract fun testAbiChange_changePublicMethodSignature()
|
abstract fun testAbiVersusNonAbiChanges()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
abstract fun testNonAbiChange_changeMethodImplementation()
|
abstract fun testModifiedAddedRemovedElements()
|
||||||
|
|
||||||
@Test
|
|
||||||
abstract fun testVariousAbiChanges()
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
abstract fun testImpactAnalysis()
|
abstract fun testImpactAnalysis()
|
||||||
@@ -43,38 +38,21 @@ abstract class ClasspathChangesComputerTest : ClasspathSnapshotTestCommon() {
|
|||||||
class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testAbiChange_changePublicMethodSignature() {
|
override fun testAbiVersusNonAbiChanges() {
|
||||||
val sourceFile = SimpleKotlinClass(tmpDir)
|
val changes = computeClasspathChanges(File(testDataDir, "testAbiVersusNonAbiChanges/src/kotlin"), tmpDir)
|
||||||
val previousSnapshot = sourceFile.compileAndSnapshot()
|
|
||||||
val currentSnapshot = sourceFile.changePublicMethodSignature().compileAndSnapshot()
|
|
||||||
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "publicFunction", scope = "com.example.SimpleKotlinClass"),
|
LookupSymbol(name = "publicPropertyChangedType", scope = "com.example.SomeClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SimpleKotlinClass")
|
LookupSymbol(name = "publicFunctionChangedSignature", scope = "com.example.SomeClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass"),
|
||||||
),
|
),
|
||||||
fqNames = setOf("com.example.SimpleKotlinClass")
|
fqNames = setOf("com.example.SomeClass")
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testNonAbiChange_changeMethodImplementation() {
|
override fun testModifiedAddedRemovedElements() {
|
||||||
val sourceFile = SimpleKotlinClass(tmpDir)
|
val changes = computeClasspathChanges(File(testDataDir, "testModifiedAddedRemovedElements/src/kotlin"), tmpDir)
|
||||||
val previousSnapshot = sourceFile.compileAndSnapshot()
|
|
||||||
val currentSnapshot = sourceFile.changeMethodImplementation().compileAndSnapshot()
|
|
||||||
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(emptySet(), emptySet()).assertEquals(changes)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
override fun testVariousAbiChanges() {
|
|
||||||
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testVariousAbiChanges/src/kotlin").canonicalFile
|
|
||||||
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir)
|
|
||||||
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir)
|
|
||||||
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
// ModifiedClassUnchangedMembers
|
// ModifiedClassUnchangedMembers
|
||||||
@@ -94,8 +72,44 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
|||||||
|
|
||||||
// RemovedClass
|
// RemovedClass
|
||||||
LookupSymbol(name = "RemovedClass", scope = "com.example"),
|
LookupSymbol(name = "RemovedClass", scope = "com.example"),
|
||||||
|
),
|
||||||
|
fqNames = setOf(
|
||||||
|
"com.example.ModifiedClassUnchangedMembers",
|
||||||
|
"com.example.ModifiedClassChangedMembers",
|
||||||
|
"com.example.AddedClass",
|
||||||
|
"com.example.RemovedClass",
|
||||||
|
)
|
||||||
|
).assertEquals(changes)
|
||||||
|
}
|
||||||
|
|
||||||
// Top-level properties and functions
|
@Test
|
||||||
|
override fun testImpactAnalysis() {
|
||||||
|
val changes = computeClasspathChanges(File(testDataDir, "testImpactAnalysis_KotlinOnly/src"), tmpDir)
|
||||||
|
Changes(
|
||||||
|
lookupSymbols = setOf(
|
||||||
|
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedSuperClass"),
|
||||||
|
LookupSymbol(name = "changedProperty", scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
|
LookupSymbol(name = "changedProperty", scope = "com.example.SubSubClassOfChangedSuperClass"),
|
||||||
|
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedSuperClass"),
|
||||||
|
LookupSymbol(name = "changedFunction", scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
|
LookupSymbol(name = "changedFunction", scope = "com.example.SubSubClassOfChangedSuperClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedSuperClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubSubClassOfChangedSuperClass")
|
||||||
|
),
|
||||||
|
fqNames = setOf(
|
||||||
|
"com.example.ChangedSuperClass",
|
||||||
|
"com.example.SubClassOfChangedSuperClass",
|
||||||
|
"com.example.SubSubClassOfChangedSuperClass"
|
||||||
|
)
|
||||||
|
).assertEquals(changes)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testTopLevelMembers() {
|
||||||
|
val changes = computeClasspathChanges(File(testDataDir, "testTopLevelMembers_KotlinOnly/src"), tmpDir)
|
||||||
|
Changes(
|
||||||
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "modifiedTopLevelProperty", scope = "com.example"),
|
LookupSymbol(name = "modifiedTopLevelProperty", scope = "com.example"),
|
||||||
LookupSymbol(name = "addedTopLevelProperty", scope = "com.example"),
|
LookupSymbol(name = "addedTopLevelProperty", scope = "com.example"),
|
||||||
LookupSymbol(name = "removedTopLevelProperty", scope = "com.example"),
|
LookupSymbol(name = "removedTopLevelProperty", scope = "com.example"),
|
||||||
@@ -106,40 +120,78 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
|||||||
LookupSymbol(name = "movedTopLevelFunction", scope = "com.example"),
|
LookupSymbol(name = "movedTopLevelFunction", scope = "com.example"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example")
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example")
|
||||||
),
|
),
|
||||||
|
fqNames = setOf("com.example")
|
||||||
|
).assertEquals(changes)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDifferentClassKinds() {
|
||||||
|
val changes = computeClasspathChanges(File(testDataDir, "testDifferentClassKinds_KotlinOnly/src"), tmpDir)
|
||||||
|
Changes(
|
||||||
|
lookupSymbols = setOf(
|
||||||
|
// NormalClass
|
||||||
|
LookupSymbol(name = "propertyInNormalClass", scope = "com.example.NormalClass"),
|
||||||
|
LookupSymbol(name = "functionInNormalClass", scope = "com.example.NormalClass"),
|
||||||
|
|
||||||
|
// NormalClass.CompanionObject
|
||||||
|
LookupSymbol(name = "propertyInCompanionObject", scope = "com.example.NormalClass.CompanionObject"),
|
||||||
|
LookupSymbol(name = "functionInCompanionObject", scope = "com.example.NormalClass.CompanionObject"),
|
||||||
|
|
||||||
|
// NormalClass.NestedClass
|
||||||
|
LookupSymbol(name = "propertyInNestedClass", scope = "com.example.NormalClass.NestedClass"),
|
||||||
|
LookupSymbol(name = "functionInNestedClass", scope = "com.example.NormalClass.NestedClass"),
|
||||||
|
|
||||||
|
// FileFacade
|
||||||
|
LookupSymbol(name = "propertyInFileFacade", scope = "com.example"),
|
||||||
|
LookupSymbol(name = "functionInFileFacade", scope = "com.example"),
|
||||||
|
|
||||||
|
// MultifileClass
|
||||||
|
LookupSymbol(name = "propertyInMultifileClass1", scope = "com.example"),
|
||||||
|
LookupSymbol(name = "functionInMultifileClass1", scope = "com.example"),
|
||||||
|
LookupSymbol(name = "propertyInMultifileClass2", scope = "com.example"),
|
||||||
|
LookupSymbol(name = "functionInMultifileClass2", scope = "com.example"),
|
||||||
|
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.NormalClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.NormalClass.CompanionObject"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.NormalClass.NestedClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example"),
|
||||||
|
),
|
||||||
fqNames = setOf(
|
fqNames = setOf(
|
||||||
"com.example.ModifiedClassUnchangedMembers",
|
"com.example.NormalClass",
|
||||||
"com.example.ModifiedClassChangedMembers",
|
"com.example.NormalClass.CompanionObject",
|
||||||
"com.example.AddedClass",
|
"com.example.NormalClass.NestedClass",
|
||||||
"com.example.RemovedClass",
|
|
||||||
"com.example"
|
"com.example"
|
||||||
)
|
)
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testImpactAnalysis() {
|
fun testConstantsAndInlineFunctions() {
|
||||||
val classpathSourceDir =
|
val changes = computeClasspathChanges(File(testDataDir, "testConstantsAndInlineFunctions_KotlinOnly/src"), tmpDir)
|
||||||
File(testDataDir, "../ClasspathChangesComputerTest/testImpactAnalysis_KotlinOrJava/src/kotlin").canonicalFile
|
|
||||||
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir)
|
|
||||||
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir)
|
|
||||||
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedSuperClass"),
|
LookupSymbol(name = "constantChangedType", scope = "com.example.SomeClass.CompanionObject"),
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.SubClass"),
|
// TODO (Fix in next commit). Missing:
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.SubSubClass"),
|
// LookupSymbol(name = "constantChangedValue", scope = "com.example.SomeClass.CompanionObject")
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedSuperClass"),
|
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.SubClass"),
|
LookupSymbol(name = "inlineFunctionChangedSignature", scope = "com.example.SomeClass"),
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.SubSubClass"),
|
LookupSymbol(name = "inlineFunctionChangedImplementation", scope = "com.example.SomeClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedSuperClass"),
|
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubSubClass")
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass.CompanionObject"),
|
||||||
|
|
||||||
|
// TODO (Fix in next commit). Incorrect:
|
||||||
|
LookupSymbol(name = "constantChangedType", scope = "com.example.SomeClass"),
|
||||||
|
LookupSymbol(name = "constantChangedType", scope = "com.example.SomeClass.Companion"),
|
||||||
|
LookupSymbol(name = "constantChangedValue", scope = "com.example.SomeClass"),
|
||||||
|
LookupSymbol(name = "constantChangedValue", scope = "com.example.SomeClass.Companion"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass.Companion"),
|
||||||
),
|
),
|
||||||
fqNames = setOf(
|
fqNames = setOf(
|
||||||
"com.example.ChangedSuperClass",
|
"com.example.SomeClass",
|
||||||
"com.example.SubClass",
|
"com.example.SomeClass.CompanionObject",
|
||||||
"com.example.SubSubClass"
|
// TODO (Fix in next commit). Incorrect:
|
||||||
|
"com.example.SomeClass.Companion"
|
||||||
)
|
)
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
@@ -155,38 +207,21 @@ class JavaOnlyClasspathChangesComputerTest(private val protoBased: Boolean) : Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testAbiChange_changePublicMethodSignature() {
|
override fun testAbiVersusNonAbiChanges() {
|
||||||
val sourceFile = SimpleJavaClass(tmpDir)
|
val changes = computeClasspathChanges(File(testDataDir, "testAbiVersusNonAbiChanges/src/java"), tmpDir, protoBased)
|
||||||
val previousSnapshot = sourceFile.compile().snapshot(protoBased)
|
|
||||||
val currentSnapshot = sourceFile.changePublicMethodSignature().compile().snapshot(protoBased)
|
|
||||||
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "publicMethod", scope = "com.example.SimpleJavaClass"),
|
LookupSymbol(name = "publicFieldChangedType", scope = "com.example.SomeClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SimpleJavaClass")
|
LookupSymbol(name = "publicMethodChangedSignature", scope = "com.example.SomeClass"),
|
||||||
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass")
|
||||||
),
|
),
|
||||||
fqNames = setOf("com.example.SimpleJavaClass")
|
fqNames = setOf("com.example.SomeClass")
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testNonAbiChange_changeMethodImplementation() {
|
override fun testModifiedAddedRemovedElements() {
|
||||||
val sourceFile = SimpleJavaClass(tmpDir)
|
val changes = computeClasspathChanges(File(testDataDir, "testModifiedAddedRemovedElements/src/java"), tmpDir, protoBased)
|
||||||
val previousSnapshot = sourceFile.compile().snapshot(protoBased)
|
|
||||||
val currentSnapshot = sourceFile.changeMethodImplementation().compile().snapshot(protoBased)
|
|
||||||
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(emptySet(), emptySet()).assertEquals(changes)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
override fun testVariousAbiChanges() {
|
|
||||||
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testVariousAbiChanges/src/java").canonicalFile
|
|
||||||
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir, protoBased)
|
|
||||||
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir, protoBased)
|
|
||||||
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
// ModifiedClassUnchangedMembers
|
// ModifiedClassUnchangedMembers
|
||||||
@@ -218,27 +253,23 @@ class JavaOnlyClasspathChangesComputerTest(private val protoBased: Boolean) : Cl
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
override fun testImpactAnalysis() {
|
override fun testImpactAnalysis() {
|
||||||
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testImpactAnalysis_KotlinOrJava/src/java").canonicalFile
|
val changes = computeClasspathChanges(File(testDataDir, "testImpactAnalysis_JavaOnly/src"), tmpDir, protoBased)
|
||||||
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir, protoBased)
|
|
||||||
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir, protoBased)
|
|
||||||
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.ChangedSuperClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.ChangedSuperClass"),
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.SubClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.SubSubClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.SubSubClassOfChangedSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedSuperClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.SubClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.SubSubClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.SubSubClassOfChangedSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubClassOfChangedSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubSubClass")
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubSubClassOfChangedSuperClass")
|
||||||
),
|
),
|
||||||
fqNames = setOf(
|
fqNames = setOf(
|
||||||
"com.example.ChangedSuperClass",
|
"com.example.ChangedSuperClass",
|
||||||
"com.example.SubClass",
|
"com.example.SubClassOfChangedSuperClass",
|
||||||
"com.example.SubSubClass"
|
"com.example.SubSubClassOfChangedSuperClass"
|
||||||
)
|
)
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
@@ -248,52 +279,55 @@ class KotlinAndJavaClasspathChangesComputerTest : ClasspathSnapshotTestCommon()
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testImpactAnalysis() {
|
fun testImpactAnalysis() {
|
||||||
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testImpactAnalysis_KotlinAndJava/src").canonicalFile
|
val changes =
|
||||||
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir)
|
computeClasspathChanges(File(ClasspathChangesComputerTest.testDataDir, "testImpactAnalysis_KotlinAndJava/src"), tmpDir)
|
||||||
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir)
|
|
||||||
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
|
|
||||||
|
|
||||||
Changes(
|
Changes(
|
||||||
lookupSymbols = setOf(
|
lookupSymbols = setOf(
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedKotlinSuperClass"),
|
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.KotlinSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = "changedProperty", scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedProperty", scope = "com.example.JavaSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = "changedProperty", scope = "com.example.JavaSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedKotlinSuperClass"),
|
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.KotlinSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = "changedFunction", scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedFunction", scope = "com.example.JavaSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = "changedFunction", scope = "com.example.JavaSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedKotlinSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfKotlinSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfChangedKotlinSuperClass"),
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.ChangedJavaSuperClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.ChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.KotlinSubClassOfJavaSuperClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = "changedField", scope = "com.example.JavaSubClassOfJavaSuperClass"),
|
LookupSymbol(name = "changedField", scope = "com.example.JavaSubClassOfChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedJavaSuperClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.KotlinSubClassOfJavaSuperClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = "changedMethod", scope = "com.example.JavaSubClassOfJavaSuperClass"),
|
LookupSymbol(name = "changedMethod", scope = "com.example.JavaSubClassOfChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedJavaSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.ChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfJavaSuperClass"),
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
|
||||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfJavaSuperClass")
|
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfChangedJavaSuperClass")
|
||||||
),
|
),
|
||||||
fqNames = setOf(
|
fqNames = setOf(
|
||||||
"com.example.ChangedKotlinSuperClass",
|
"com.example.ChangedKotlinSuperClass",
|
||||||
"com.example.KotlinSubClassOfKotlinSuperClass",
|
"com.example.KotlinSubClassOfChangedKotlinSuperClass",
|
||||||
"com.example.JavaSubClassOfKotlinSuperClass",
|
"com.example.JavaSubClassOfChangedKotlinSuperClass",
|
||||||
"com.example.ChangedJavaSuperClass",
|
"com.example.ChangedJavaSuperClass",
|
||||||
"com.example.KotlinSubClassOfJavaSuperClass",
|
"com.example.KotlinSubClassOfChangedJavaSuperClass",
|
||||||
"com.example.JavaSubClassOfJavaSuperClass"
|
"com.example.JavaSubClassOfChangedJavaSuperClass"
|
||||||
)
|
)
|
||||||
).assertEquals(changes)
|
).assertEquals(changes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun snapshotClasspath(classpathSourceDir: File, tmpDir: TemporaryFolder, protoBased: Boolean = true): ClasspathSnapshot {
|
private fun computeClasspathChanges(classpathSourceDir: File, tmpDir: TemporaryFolder, protoBased: Boolean = false): Changes {
|
||||||
|
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir, protoBased)
|
||||||
|
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir, protoBased)
|
||||||
|
return computeClasspathChanges(currentSnapshot, previousSnapshot)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun snapshotClasspath(classpathSourceDir: File, tmpDir: TemporaryFolder, protoBased: Boolean): ClasspathSnapshot {
|
||||||
val classpath = mutableListOf<File>()
|
val classpath = mutableListOf<File>()
|
||||||
val classpathEntrySnapshots = classpathSourceDir.listFiles()!!.sortedBy { it.name }.map { classpathEntrySourceDir ->
|
val classpathEntrySnapshots = classpathSourceDir.listFiles()!!.sortedBy { it.name }.map { classpathEntrySourceDir ->
|
||||||
val classFiles = compileAll(classpathEntrySourceDir, classpath, tmpDir)
|
val classFiles = compileAll(classpathEntrySourceDir, classpath, tmpDir)
|
||||||
classpath.addAll(listOfNotNull(classFiles.firstOrNull()?.classRoot))
|
classpath.addAll(listOfNotNull(classFiles.firstOrNull()?.classRoot))
|
||||||
|
|
||||||
val relativePaths = classFiles.map { it.unixStyleRelativePath }
|
val relativePaths = classFiles.map { it.unixStyleRelativePath }
|
||||||
val classSnapshots = classFiles.snapshotAll(protoBased).map { it.withHash }
|
val classSnapshots = classFiles.snapshot(protoBased).map { it.withHash }
|
||||||
ClasspathEntrySnapshot(
|
ClasspathEntrySnapshot(
|
||||||
classSnapshots = relativePaths.zip(classSnapshots).toMap(LinkedHashMap())
|
classSnapshots = relativePaths.zip(classSnapshots).toMap(LinkedHashMap())
|
||||||
)
|
)
|
||||||
@@ -306,16 +340,8 @@ private fun computeClasspathChanges(
|
|||||||
previousClasspathSnapshot: ClasspathSnapshot
|
previousClasspathSnapshot: ClasspathSnapshot
|
||||||
): Changes {
|
): Changes {
|
||||||
return ClasspathChangesComputer.computeChangedAndImpactedSet(
|
return ClasspathChangesComputer.computeChangedAndImpactedSet(
|
||||||
currentClasspathSnapshot.getNonDuplicateClassSnapshots(),
|
currentClasspathSnapshot.removeDuplicateAndInaccessibleClasses(),
|
||||||
previousClasspathSnapshot.getNonDuplicateClassSnapshots(),
|
previousClasspathSnapshot.removeDuplicateAndInaccessibleClasses(),
|
||||||
DoNothingBuildMetricsReporter
|
|
||||||
).normalize()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun computeClassChanges(currentClassSnapshot: ClassSnapshot, previousClassSnapshot: ClassSnapshot): Changes {
|
|
||||||
return ClasspathChangesComputer.computeClassChanges(
|
|
||||||
listOf(currentClassSnapshot),
|
|
||||||
listOf(previousClassSnapshot),
|
|
||||||
DoNothingBuildMetricsReporter
|
DoNothingBuildMetricsReporter
|
||||||
).normalize()
|
).normalize()
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-17
@@ -5,19 +5,26 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.classpathDiff
|
package org.jetbrains.kotlin.incremental.classpathDiff
|
||||||
|
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.readBytes
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.JavaSourceFile
|
||||||
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.KotlinSourceFile
|
||||||
import org.jetbrains.kotlin.incremental.storage.fromByteArray
|
import org.jetbrains.kotlin.incremental.storage.fromByteArray
|
||||||
import org.jetbrains.kotlin.incremental.storage.toByteArray
|
import org.jetbrains.kotlin.incremental.storage.toByteArray
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
abstract class ClasspathSnapshotSerializerTest : ClasspathSnapshotTestCommon() {
|
abstract class ClasspathSnapshotSerializerTest : ClasspathSnapshotTestCommon() {
|
||||||
|
|
||||||
protected abstract val testSourceFile: ChangeableTestSourceFile
|
companion object {
|
||||||
|
val testDataDir =
|
||||||
|
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract val sourceFile: TestSourceFile
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
open fun `test ClassSnapshotDataSerializer`() {
|
open fun `test ClassSnapshotExternalizer`() {
|
||||||
val originalSnapshot = testSourceFile.compileAndSnapshot()
|
val originalSnapshot = sourceFile.compileAndSnapshot()
|
||||||
val serializedSnapshot = ClassSnapshotExternalizer.toByteArray(originalSnapshot)
|
val serializedSnapshot = ClassSnapshotExternalizer.toByteArray(originalSnapshot)
|
||||||
val deserializedSnapshot = ClassSnapshotExternalizer.fromByteArray(serializedSnapshot)
|
val deserializedSnapshot = ClassSnapshotExternalizer.fromByteArray(serializedSnapshot)
|
||||||
|
|
||||||
@@ -26,21 +33,20 @@ abstract class ClasspathSnapshotSerializerTest : ClasspathSnapshotTestCommon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class KotlinClassesClasspathSnapshotSerializerTest : ClasspathSnapshotSerializerTest() {
|
class KotlinClassesClasspathSnapshotSerializerTest : ClasspathSnapshotSerializerTest() {
|
||||||
override val testSourceFile = SimpleKotlinClass(tmpDir)
|
|
||||||
|
override val sourceFile = TestSourceFile(
|
||||||
|
KotlinSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src/kotlin"), relativePath = "com/example/SimpleClass.kt",
|
||||||
|
preCompiledClassFile = ClassFile(File(testDataDir, "classes/kotlin"), "com/example/SimpleClass.class")
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class JavaClassesClasspathSnapshotSerializerTest : ClasspathSnapshotSerializerTest() {
|
class JavaClassesClasspathSnapshotSerializerTest : ClasspathSnapshotSerializerTest() {
|
||||||
|
|
||||||
override val testSourceFile = SimpleJavaClass(tmpDir)
|
override val sourceFile = TestSourceFile(
|
||||||
|
JavaSourceFile(
|
||||||
@Test
|
baseDir = File(testDataDir, "src/java"), relativePath = "com/example/SimpleClass.java",
|
||||||
override fun `test ClassSnapshotDataSerializer`() {
|
), tmpDir
|
||||||
val originalSnapshot = testSourceFile.compile().let {
|
)
|
||||||
ClassSnapshotter.snapshot(listOf(ClassFileWithContents(it, it.readBytes())), includeDebugInfoInSnapshot = false)
|
|
||||||
}.single()
|
|
||||||
val serializedSnapshot = ClassSnapshotExternalizer.toByteArray(originalSnapshot)
|
|
||||||
val deserializedSnapshot = ClassSnapshotExternalizer.fromByteArray(serializedSnapshot)
|
|
||||||
|
|
||||||
assertEquals(originalSnapshot.toGson(), deserializedSnapshot.toGson())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-109
@@ -6,12 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.incremental.classpathDiff
|
package org.jetbrains.kotlin.incremental.classpathDiff
|
||||||
|
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.JavaSourceFile
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.asFile
|
||||||
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.snapshot
|
||||||
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.CompileUtil.compile
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.KotlinSourceFile
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.KotlinSourceFile
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.compile
|
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.compileAll
|
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.snapshot
|
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.snapshotAll
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
@@ -19,11 +17,6 @@ import java.io.File
|
|||||||
|
|
||||||
abstract class ClasspathSnapshotTestCommon {
|
abstract class ClasspathSnapshotTestCommon {
|
||||||
|
|
||||||
companion object {
|
|
||||||
val testDataDir =
|
|
||||||
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotTestCommon")
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Rule
|
@get:Rule
|
||||||
val tmpDir = TemporaryFolder()
|
val tmpDir = TemporaryFolder()
|
||||||
|
|
||||||
@@ -53,44 +46,31 @@ abstract class ClasspathSnapshotTestCommon {
|
|||||||
/** Same as [SourceFile] but with a [TemporaryFolder] to store the results of operations on the [SourceFile]. */
|
/** Same as [SourceFile] but with a [TemporaryFolder] to store the results of operations on the [SourceFile]. */
|
||||||
open class TestSourceFile(val sourceFile: SourceFile, private val tmpDir: TemporaryFolder) {
|
open class TestSourceFile(val sourceFile: SourceFile, private val tmpDir: TemporaryFolder) {
|
||||||
|
|
||||||
fun replace(oldValue: String, newValue: String, preCompiledKotlinClassFile: ClassFile? = null): TestSourceFile {
|
fun asFile() = sourceFile.asFile()
|
||||||
val fileContents = sourceFile.asFile().readText()
|
|
||||||
check(fileContents.contains(oldValue)) { "String '$oldValue' not found in file '${sourceFile.asFile().path}'" }
|
|
||||||
|
|
||||||
val newSourceFile = when (sourceFile) {
|
|
||||||
is KotlinSourceFile -> KotlinSourceFile(tmpDir.newFolder(), sourceFile.unixStyleRelativePath, preCompiledKotlinClassFile!!)
|
|
||||||
is JavaSourceFile -> JavaSourceFile(tmpDir.newFolder(), sourceFile.unixStyleRelativePath)
|
|
||||||
}
|
|
||||||
newSourceFile.asFile().parentFile.mkdirs()
|
|
||||||
newSourceFile.asFile().writeText(fileContents.replace(oldValue, newValue))
|
|
||||||
return TestSourceFile(newSourceFile, tmpDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles this source file and returns a single generated .class file, or fails if zero or more than one .class file was
|
|
||||||
* generated.
|
|
||||||
*
|
|
||||||
* Alternatively, the caller can call [compileAll] to get all generated .class files.
|
|
||||||
*/
|
|
||||||
fun compile(): ClassFile = compileAll().single()
|
|
||||||
|
|
||||||
/** Compiles this source file and returns all generated .class files. */
|
/** Compiles this source file and returns all generated .class files. */
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
fun compileAll(): List<ClassFile> = sourceFile.compile(tmpDir)
|
fun compile(): List<ClassFile> = sourceFile.compile(tmpDir)
|
||||||
|
|
||||||
/**
|
fun compileSingle(): ClassFile = compile().single()
|
||||||
* Compiles this source file and returns the snapshot of a single generated .class file, or fails if zero or more than one .class
|
|
||||||
* file was generated.
|
|
||||||
*
|
|
||||||
* Alternatively, the caller can call [compileAndSnapshotAll] to get the snapshots of all generated .class files.
|
|
||||||
*/
|
|
||||||
fun compileAndSnapshot() = compile().snapshot()
|
|
||||||
|
|
||||||
/** Compiles this source file and returns the snapshots of all generated .class files. */
|
fun compileAndSnapshot() = compileSingle().snapshot()
|
||||||
fun compileAndSnapshotAll(): List<ClassSnapshot> = compileAll().snapshotAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Util {
|
object CompileUtil {
|
||||||
|
|
||||||
|
fun SourceFile.compile(tmpDir: TemporaryFolder): List<ClassFile> {
|
||||||
|
return if (this is KotlinSourceFile) {
|
||||||
|
preCompiledClassFiles.forEach {
|
||||||
|
preCompileKotlinFilesIfNecessary(baseDir, it.classRoot, classpath = emptyList(), tmpDir)
|
||||||
|
}
|
||||||
|
preCompiledClassFiles
|
||||||
|
} else {
|
||||||
|
val srcDir = tmpDir.newFolder()
|
||||||
|
asFile().copyTo(File(srcDir, unixStyleRelativePath))
|
||||||
|
compileAll(srcDir, classpath = emptyList(), tmpDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Compiles the source files in the given directory and returns all generated .class files. */
|
/** Compiles the source files in the given directory and returns all generated .class files. */
|
||||||
fun compileAll(srcDir: File, classpath: List<File>, tmpDir: TemporaryFolder): List<ClassFile> {
|
fun compileAll(srcDir: File, classpath: List<File>, tmpDir: TemporaryFolder): List<ClassFile> {
|
||||||
@@ -140,19 +120,6 @@ abstract class ClasspathSnapshotTestCommon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SourceFile.compile(tmpDir: TemporaryFolder): List<ClassFile> {
|
|
||||||
return if (this is KotlinSourceFile) {
|
|
||||||
preCompiledClassFiles.forEach {
|
|
||||||
preCompileKotlinFilesIfNecessary(baseDir, it.classRoot, classpath = emptyList(), tmpDir)
|
|
||||||
}
|
|
||||||
preCompiledClassFiles
|
|
||||||
} else {
|
|
||||||
val srcDir = tmpDir.newFolder()
|
|
||||||
asFile().copyTo(File(srcDir, unixStyleRelativePath))
|
|
||||||
compileAll(srcDir, classpath = emptyList(), tmpDir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doCompileKotlin(srcDir: File, classpath: List<File>, tmpDir: TemporaryFolder): List<ClassFile> {
|
private fun doCompileKotlin(srcDir: File, classpath: List<File>, tmpDir: TemporaryFolder): List<ClassFile> {
|
||||||
if (srcDir.walk().none { it.path.endsWith(".kt") }) {
|
if (srcDir.walk().none { it.path.endsWith(".kt") }) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
@@ -187,70 +154,21 @@ abstract class ClasspathSnapshotTestCommon {
|
|||||||
.map { ClassFile(classesDir, it.toRelativeString(classesDir)) }
|
.map { ClassFile(classesDir, it.toRelativeString(classesDir)) }
|
||||||
.sortedBy { it.unixStyleRelativePath.substringBefore(".class") }
|
.sortedBy { it.unixStyleRelativePath.substringBefore(".class") }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ClassFileUtil {
|
||||||
|
|
||||||
// `ClassFile`s in production code could be in a jar, but the `ClassFile`s in tests are currently in a directory, so converting it
|
// `ClassFile`s in production code could be in a jar, but the `ClassFile`s in tests are currently in a directory, so converting it
|
||||||
// to a File is possible.
|
// to a File is possible.
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
fun ClassFile.asFile() = File(classRoot, unixStyleRelativePath)
|
fun ClassFile.asFile() = File(classRoot, unixStyleRelativePath)
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
fun ClassFile.readBytes() = asFile().readBytes()
|
fun ClassFile.readBytes() = asFile().readBytes()
|
||||||
|
|
||||||
fun ClassFile.snapshot(protoBased: Boolean? = null): ClassSnapshot = listOf(this).snapshotAll(protoBased).single()
|
fun ClassFile.snapshot(protoBased: Boolean? = null): ClassSnapshot = listOf(this).snapshot(protoBased).single()
|
||||||
|
|
||||||
fun List<ClassFile>.snapshotAll(protoBased: Boolean? = null): List<ClassSnapshot> {
|
fun List<ClassFile>.snapshot(protoBased: Boolean? = null): List<ClassSnapshot> {
|
||||||
val classFilesWithContents = this.map { ClassFileWithContents(it, it.readBytes()) }
|
val classFilesWithContents = this.map { ClassFileWithContents(it, it.readBytes()) }
|
||||||
return ClassSnapshotter.snapshot(classFilesWithContents, protoBased, includeDebugInfoInSnapshot = true)
|
return ClassSnapshotter.snapshot(classFilesWithContents, protoBased)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class ChangeableTestSourceFile(sourceFile: SourceFile, tmpDir: TemporaryFolder) : TestSourceFile(sourceFile, tmpDir) {
|
|
||||||
|
|
||||||
abstract fun changePublicMethodSignature(): TestSourceFile
|
|
||||||
|
|
||||||
abstract fun changeMethodImplementation(): TestSourceFile
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleKotlinClass(tmpDir: TemporaryFolder) : ChangeableTestSourceFile(
|
|
||||||
KotlinSourceFile(
|
|
||||||
baseDir = File(testDataDir, "src/kotlin"), relativePath = "com/example/SimpleKotlinClass.kt",
|
|
||||||
preCompiledClassFile = ClassFile(File(testDataDir, "classes/kotlin/original"), "com/example/SimpleKotlinClass.class")
|
|
||||||
), tmpDir
|
|
||||||
) {
|
|
||||||
|
|
||||||
override fun changePublicMethodSignature() = replace(
|
|
||||||
"publicFunction()", "publicFunction(newParam: Int)",
|
|
||||||
preCompiledKotlinClassFile = ClassFile(
|
|
||||||
File(testDataDir, "classes/kotlin/changedPublicMethodSignature"), "com/example/SimpleKotlinClass.class"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun changeMethodImplementation() = replace(
|
|
||||||
"I'm in a public function", "This function's implementation has changed!",
|
|
||||||
preCompiledKotlinClassFile = ClassFile(
|
|
||||||
File(testDataDir, "classes/kotlin/changedMethodImplementation"), "com/example/SimpleKotlinClass.class"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleJavaClass(tmpDir: TemporaryFolder) : ChangeableTestSourceFile(
|
|
||||||
JavaSourceFile(File(testDataDir, "src/java"), "com/example/SimpleJavaClass.java"), tmpDir
|
|
||||||
) {
|
|
||||||
|
|
||||||
override fun changePublicMethodSignature() = replace("publicMethod()", "publicMethod(int newParam)")
|
|
||||||
|
|
||||||
override fun changeMethodImplementation() = replace("I'm in a public method", "This method's implementation has changed!")
|
|
||||||
}
|
|
||||||
|
|
||||||
class JavaClassWithNestedClasses(tmpDir: TemporaryFolder) : ChangeableTestSourceFile(
|
|
||||||
JavaSourceFile(File(testDataDir, "src/java"), "com/example/JavaClassWithNestedClasses.java"), tmpDir
|
|
||||||
) {
|
|
||||||
|
|
||||||
/** The source file contains multiple classes, select the one that we want to test. */
|
|
||||||
val nestedClassToTest = "com/example/JavaClassWithNestedClasses\$InnerClass"
|
|
||||||
|
|
||||||
override fun changePublicMethodSignature() = replace("publicMethod()", "publicMethod(int newParam)")
|
|
||||||
|
|
||||||
override fun changeMethodImplementation() = replace("I'm in a public method", "This method's implementation has changed!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+65
-113
@@ -5,141 +5,93 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.classpathDiff
|
package org.jetbrains.kotlin.incremental.classpathDiff
|
||||||
|
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.Util.snapshot
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.readBytes
|
||||||
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.JavaSourceFile
|
||||||
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.SourceFile.KotlinSourceFile
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotEquals
|
import org.junit.Assert.assertNotEquals
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class ClasspathSnapshotterTest : ClasspathSnapshotTestCommon() {
|
abstract class ClasspathSnapshotterTest : ClasspathSnapshotTestCommon() {
|
||||||
|
|
||||||
protected abstract val testSourceFile: ChangeableTestSourceFile
|
|
||||||
|
|
||||||
private lateinit var testClassSnapshot: ClassSnapshot
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setUp() {
|
|
||||||
testClassSnapshot = testSourceFile.compileAndSnapshot()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter's result against expected snapshot`() {
|
|
||||||
assertEquals(getExpectedSnapshotFile().readText(), testClassSnapshot.toGson())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getExpectedSnapshotFile() = testSourceFile.sourceFile.asFile().path.let {
|
|
||||||
File(it.substringBeforeLast("src") + "expected-snapshot" + it.substringAfterLast("src").substringBeforeLast('.') + ".json")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter extracts ABI info from a class`() {
|
|
||||||
// Change public method signature
|
|
||||||
val updatedSnapshot = testSourceFile.changePublicMethodSignature().compileAndSnapshot()
|
|
||||||
|
|
||||||
// The snapshot must change
|
|
||||||
assertNotEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter does not extract non-ABI info from a class`() {
|
|
||||||
// Change method implementation
|
|
||||||
val updatedSnapshot = testSourceFile.changeMethodImplementation().compileAndSnapshot()
|
|
||||||
|
|
||||||
// The snapshot must not change
|
|
||||||
assertEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class KotlinClassesClasspathSnapshotterTest : ClasspathSnapshotterTest() {
|
|
||||||
override val testSourceFile = SimpleKotlinClass(tmpDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
class JavaClassesClasspathSnapshotterTest(private val protoBased: Boolean) : ClasspathSnapshotTestCommon() {
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@Parameterized.Parameters(name = "protoBased={0}")
|
val testDataDir =
|
||||||
@JvmStatic
|
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest")
|
||||||
fun parameters() = listOf(true, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val testSourceFile = SimpleJavaClass(tmpDir)
|
protected abstract val sourceFile: TestSourceFile
|
||||||
|
protected abstract val sourceFileWithAbiChange: TestSourceFile
|
||||||
|
protected abstract val sourceFileWithNonAbiChange: TestSourceFile
|
||||||
|
|
||||||
private lateinit var testClassSnapshot: ClassSnapshot
|
private val expectedSnapshotFile: File
|
||||||
|
get() = sourceFile.asFile().path.let {
|
||||||
@Before
|
File(it.substringBeforeLast("src") + "expected-snapshot" + it.substringAfterLast("src").substringBeforeLast('.') + ".json")
|
||||||
fun setUp() {
|
|
||||||
testClassSnapshot = testSourceFile.compile().snapshot(protoBased)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter's result against expected snapshot`() {
|
|
||||||
assertEquals(getExpectedSnapshotFile().readText(), testClassSnapshot.toGson())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getExpectedSnapshotFile() = testSourceFile.sourceFile.asFile().path.let {
|
|
||||||
File(
|
|
||||||
it.substringBeforeLast("src") + "expected-snapshot" + it.substringAfterLast("src")
|
|
||||||
.substringBeforeLast('.') + "-protoBased=$protoBased.json"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter extracts ABI info from a class`() {
|
|
||||||
// Change public method signature
|
|
||||||
val updatedSnapshot = testSourceFile.changePublicMethodSignature().compile().snapshot(protoBased)
|
|
||||||
|
|
||||||
// The snapshot must change
|
|
||||||
assertNotEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `test ClassSnapshotter does not extract non-ABI info from a class`() {
|
|
||||||
// Change method implementation
|
|
||||||
val updatedSnapshot = testSourceFile.changeMethodImplementation().compile().snapshot(protoBased)
|
|
||||||
|
|
||||||
// The snapshot must not change
|
|
||||||
assertEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class JavaClassWithNestedClassesClasspathSnapshotterTest : ClasspathSnapshotTestCommon() {
|
|
||||||
|
|
||||||
private val testSourceFile = JavaClassWithNestedClasses(tmpDir)
|
|
||||||
|
|
||||||
private lateinit var testClassSnapshot: ClassSnapshot
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setUp() {
|
|
||||||
testClassSnapshot = testSourceFile.compileAndSnapshotNestedClass()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun TestSourceFile.compileAndSnapshotNestedClass(): ClassSnapshot {
|
|
||||||
return compileAndSnapshotAll().single {
|
|
||||||
if (it is RegularJavaClassSnapshot) {
|
|
||||||
it.classAbiExcludingMembers.name == testSourceFile.nestedClassToTest
|
|
||||||
} else false
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test ClassSnapshotter's result against expected snapshot`() {
|
fun `test ClassSnapshotter's result against expected snapshot`() {
|
||||||
val expectedSnapshotFile = File("${testDataDir.path}/expected-snapshot/java/${testSourceFile.nestedClassToTest}.json")
|
val classSnapshot = sourceFile.compileSingle().let {
|
||||||
assertEquals(expectedSnapshotFile.readText(), testClassSnapshot.toGson())
|
ClassSnapshotter.snapshot(listOf(ClassFileWithContents(it, it.readBytes())), includeDebugInfoInSnapshot = true)
|
||||||
|
}.single()
|
||||||
|
|
||||||
|
assertEquals(expectedSnapshotFile.readText(), classSnapshot.toGson())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test ClassSnapshotter extracts ABI info from a class`() {
|
fun `test ClassSnapshotter extracts ABI info from a class`() {
|
||||||
val updatedSnapshot = testSourceFile.changePublicMethodSignature().compileAndSnapshotNestedClass()
|
// After an ABI change, the snapshot must change
|
||||||
assertNotEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
assertNotEquals(sourceFile.compileAndSnapshot().toGson(), sourceFileWithAbiChange.compileAndSnapshot().toGson())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test ClassSnapshotter does not extract non-ABI info from a class`() {
|
fun `test ClassSnapshotter does not extract non-ABI info from a class`() {
|
||||||
val updatedSnapshot = testSourceFile.changeMethodImplementation().compileAndSnapshotNestedClass()
|
// After a non-ABI change, the snapshot must not change
|
||||||
assertEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
|
assertEquals(sourceFile.compileAndSnapshot().toGson(), sourceFileWithNonAbiChange.compileAndSnapshot().toGson())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class KotlinOnlyClasspathSnapshotterTest : ClasspathSnapshotterTest() {
|
||||||
|
|
||||||
|
override val sourceFile = TestSourceFile(
|
||||||
|
KotlinSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src/kotlin"), relativePath = "com/example/SimpleClass.kt",
|
||||||
|
preCompiledClassFile = ClassFile(File(testDataDir, "classes/kotlin"), "com/example/SimpleClass.class")
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
|
||||||
|
override val sourceFileWithAbiChange = TestSourceFile(
|
||||||
|
KotlinSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src-changed/kotlin/abi-change"), relativePath = "com/example/SimpleClass.kt",
|
||||||
|
preCompiledClassFile = ClassFile(File(testDataDir, "classes-changed/kotllin/abi-change"), "com/example/SimpleClass.class")
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
|
||||||
|
override val sourceFileWithNonAbiChange = TestSourceFile(
|
||||||
|
KotlinSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src-changed/kotlin/non-abi-change"), relativePath = "com/example/SimpleClass.kt",
|
||||||
|
preCompiledClassFile = ClassFile(File(testDataDir, "classes-changed/kotlin/non-abi-change"), "com/example/SimpleClass.class")
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class JavaOnlyClasspathSnapshotterTest : ClasspathSnapshotterTest() {
|
||||||
|
|
||||||
|
override val sourceFile = TestSourceFile(
|
||||||
|
JavaSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src/java"), relativePath = "com/example/SimpleClass.java",
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
|
||||||
|
override val sourceFileWithAbiChange = TestSourceFile(
|
||||||
|
JavaSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src-changed/java/abi-change"), relativePath = "com/example/SimpleClass.java",
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
|
||||||
|
override val sourceFileWithNonAbiChange = TestSourceFile(
|
||||||
|
JavaSourceFile(
|
||||||
|
baseDir = File(testDataDir, "src-changed/java/non-abi-change"), relativePath = "com/example/SimpleClass.java",
|
||||||
|
), tmpDir
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SomeClass {
|
||||||
|
|
||||||
|
public long publicFieldChangedType = 0;
|
||||||
|
|
||||||
|
public int publicFieldChangedValue = 1000;
|
||||||
|
|
||||||
|
private long privateFieldChangedType = 0;
|
||||||
|
|
||||||
|
public long publicMethodChangedSignature() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int publicMethodChangedImplementation() {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long privateMethodChangedSignature() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SomeClass {
|
||||||
|
|
||||||
|
public int publicFieldChangedType = 0;
|
||||||
|
|
||||||
|
public int publicFieldChangedValue = 0;
|
||||||
|
|
||||||
|
private int privateFieldChangedType = 0;
|
||||||
|
|
||||||
|
public int publicMethodChangedSignature() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int publicMethodChangedImplementation() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int privateMethodChangedSignature() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
|
||||||
|
val publicPropertyChangedType: Long = 0
|
||||||
|
|
||||||
|
val publicPropertyChangedValue: Int = 1000
|
||||||
|
|
||||||
|
private val privatePropertyChangedType: Long = 0
|
||||||
|
|
||||||
|
fun publicFunctionChangedSignature(): Long = 0
|
||||||
|
|
||||||
|
fun publicFunctionChangedImplementation(): Int = 1000
|
||||||
|
|
||||||
|
private fun privateFunctionChangedSignature(): Long = 0
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
|
||||||
|
val publicPropertyChangedType: Int = 0
|
||||||
|
|
||||||
|
val publicPropertyChangedValue: Int = 0
|
||||||
|
|
||||||
|
private val privatePropertyChangedType: Int = 0
|
||||||
|
|
||||||
|
fun publicFunctionChangedSignature(): Int = 0
|
||||||
|
|
||||||
|
fun publicFunctionChangedImplementation(): Int = 0
|
||||||
|
|
||||||
|
private fun privateFunctionChangedSignature(): Int = 0
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
|
||||||
|
// Constants are not allowed in a class, only allowed at the top level or in an object.
|
||||||
|
|
||||||
|
companion object CompanionObject {
|
||||||
|
const val constantChangedType: Long = 0
|
||||||
|
const val constantChangedValue: Int = 1000
|
||||||
|
const val constantUnchanged: Int = 0
|
||||||
|
private const val privateConstantChangedType: Long = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineFunctionChangedSignature(): Long = 0
|
||||||
|
inline fun inlineFunctionChangedImplementation(): Int = 1000
|
||||||
|
inline fun inlineFunctionChangedUnchanged(): Int = 0
|
||||||
|
private inline fun privateInlineFunctionChangedSignature(): Long = 0
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SomeClass {
|
||||||
|
|
||||||
|
// Constants are not allowed in a class, only allowed at the top level or in an object.
|
||||||
|
|
||||||
|
companion object CompanionObject {
|
||||||
|
const val constantChangedType: Int = 0
|
||||||
|
const val constantChangedValue: Int = 0
|
||||||
|
const val constantUnchanged: Int = 0
|
||||||
|
private const val privateConstantChangedType: Int = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineFunctionChangedSignature(): Int = 0
|
||||||
|
inline fun inlineFunctionChangedImplementation(): Int = 0
|
||||||
|
inline fun inlineFunctionChangedUnchanged(): Int = 0
|
||||||
|
private inline fun privateInlineFunctionChangedSignature(): Int = 0
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
val propertyInFileFacade = 0
|
||||||
|
fun functionInFileFacade() = 0
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
@file:JvmName("MultifileClass")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
|
||||||
|
package com.example
|
||||||
|
|
||||||
|
val propertyInMultifileClass1 = 0
|
||||||
|
fun functionInMultifileClass1() = 0
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
@file:JvmName("MultifileClass")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
|
||||||
|
package com.example
|
||||||
|
|
||||||
|
val propertyInMultifileClass2 = 0
|
||||||
|
fun functionInMultifileClass2() = 0
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class NormalClass {
|
||||||
|
val propertyInNormalClass = 0
|
||||||
|
fun functionInNormalClass() = 0
|
||||||
|
|
||||||
|
companion object CompanionObject {
|
||||||
|
val propertyInCompanionObject = 0
|
||||||
|
fun functionInCompanionObject() = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedClass {
|
||||||
|
val propertyInNestedClass = 0
|
||||||
|
fun functionInNestedClass() = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
package com.example
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
@file:JvmName("MultifileClass")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
|
||||||
|
package com.example
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
@file:JvmName("MultifileClass")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
|
||||||
|
package com.example
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class NormalClass {
|
||||||
|
|
||||||
|
companion object CompanionObject {
|
||||||
|
}
|
||||||
|
|
||||||
|
class NestedClass {
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SubClassOfChangedSuperClass extends ChangedSuperClass {
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SubSubClassOfChangedSuperClass extends SubClassOfChangedSuperClass {
|
||||||
|
}
|
||||||
+2
-1
@@ -4,6 +4,7 @@ public class ChangedSuperClass {
|
|||||||
|
|
||||||
public int changedField = 0;
|
public int changedField = 0;
|
||||||
|
|
||||||
public void changedMethod() {
|
public int changedMethod() {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SubClassOfChangedSuperClass extends ChangedSuperClass {
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class SubSubClassOfChangedSuperClass extends SubClassOfChangedSuperClass {
|
||||||
|
}
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class JavaSubClassOfChangedJavaSuperClass extends ChangedJavaSuperClass {
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class JavaSubClassOfChangedKotlinSuperClass extends ChangedKotlinSuperClass {
|
||||||
|
}
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class JavaSubClassOfJavaSuperClass extends ChangedJavaSuperClass {
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class JavaSubClassOfKotlinSuperClass extends ChangedKotlinSuperClass {
|
|
||||||
}
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class KotlinSubClassOfChangedJavaSuperClass : ChangedJavaSuperClass()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class KotlinSubClassOfChangedKotlinSuperClass : ChangedKotlinSuperClass()
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class KotlinSubClassOfJavaSuperClass : ChangedJavaSuperClass()
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class KotlinSubClassOfKotlinSuperClass : ChangedKotlinSuperClass()
|
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class JavaSubClassOfChangedJavaSuperClass extends ChangedJavaSuperClass {
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
package com.example;
|
||||||
|
|
||||||
|
public class JavaSubClassOfChangedKotlinSuperClass extends ChangedKotlinSuperClass {
|
||||||
|
}
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class JavaSubClassOfJavaSuperClass extends ChangedJavaSuperClass {
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class JavaSubClassOfKotlinSuperClass extends ChangedKotlinSuperClass {
|
|
||||||
}
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class KotlinSubClassOfChangedJavaSuperClass : ChangedJavaSuperClass()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class KotlinSubClassOfChangedKotlinSuperClass : ChangedKotlinSuperClass()
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class KotlinSubClassOfJavaSuperClass : ChangedJavaSuperClass()
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class KotlinSubClassOfKotlinSuperClass : ChangedKotlinSuperClass()
|
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
open class SubClassOfChangedSuperClass : ChangedSuperClass()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SubSubClassOfChangedSuperClass : SubClassOfChangedSuperClass()
|
||||||
+1
-1
@@ -2,5 +2,5 @@ package com.example;
|
|||||||
|
|
||||||
open class ChangedSuperClass {
|
open class ChangedSuperClass {
|
||||||
val changedProperty = 0
|
val changedProperty = 0
|
||||||
fun changedFunction() {}
|
fun changedFunction() = 0
|
||||||
}
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
open class SubClassOfChangedSuperClass : ChangedSuperClass()
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
package com.example
|
||||||
|
|
||||||
|
class SubSubClassOfChangedSuperClass : SubClassOfChangedSuperClass()
|
||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class SubClass extends ChangedSuperClass {
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class SubSubClass extends SubClass {
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class SubClass extends ChangedSuperClass {
|
|
||||||
}
|
|
||||||
-4
@@ -1,4 +0,0 @@
|
|||||||
package com.example;
|
|
||||||
|
|
||||||
public class SubSubClass extends SubClass {
|
|
||||||
}
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
open class SubClass : ChangedSuperClass()
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class SubSubClass : SubClass()
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
open class SubClass : ChangedSuperClass()
|
|
||||||
-3
@@ -1,3 +0,0 @@
|
|||||||
package com.example
|
|
||||||
|
|
||||||
class SubSubClass : SubClass()
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user