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:
Hung Nguyen
2021-12-15 19:38:47 +00:00
committed by nataliya.valtman
parent 534cf0c6c8
commit a900f2b66d
153 changed files with 605 additions and 1790 deletions
+1
View File
@@ -1,6 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="hungnv">
<words>
<w>multifile</w>
<w>shrinker</w>
<w>snapshotter</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) {
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 (value != null && access and staticFinal == Opcodes.ACC_STATIC or Opcodes.ACC_FINAL) {
if (access and Opcodes.ACC_PRIVATE == Opcodes.ACC_PRIVATE) return null
val staticFinal = Opcodes.ACC_STATIC or Opcodes.ACC_FINAL
if (value != null && access and staticFinal == staticFinal) {
result[name] = value
}
return null
@@ -689,7 +691,9 @@ private fun getInlineFunctionsMap(header: KotlinClassHeader, bytes: ByteArray):
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor {
): MethodVisitor? {
if (access and Opcodes.ACC_PRIVATE == Opcodes.ACC_PRIVATE) return null
val dummyClassWriter = ClassWriter(0)
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 {
INT, FLOAT, LONG, DOUBLE, STRING
}
@@ -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.
*/
internal fun ClasspathSnapshot.getNonDuplicateClassSnapshots(): List<ClassSnapshotWithHash> {
private fun ClasspathSnapshot.getNonDuplicateClassSnapshots(): List<ClassSnapshotWithHash> {
val classSnapshots = LinkedHashMap<String, ClassSnapshotWithHash>(classpathEntrySnapshots.sumOf { it.classSnapshots.size })
for (classpathEntrySnapshot in classpathEntrySnapshots) {
for ((unixStyleRelativePath, classSnapshot) in classpathEntrySnapshot.classSnapshots) {
@@ -8,9 +8,8 @@ package org.jetbrains.kotlin.incremental.classpathDiff
import org.jetbrains.kotlin.build.report.metrics.DoNothingBuildMetricsReporter
import org.jetbrains.kotlin.incremental.ChangesEither
import org.jetbrains.kotlin.incremental.LookupSymbol
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.incremental.classpathDiff.ClasspathSnapshotTestCommon.ClassFileUtil.snapshot
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotTestCommon.CompileUtil.compileAll
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
import org.junit.Test
import org.junit.rules.TemporaryFolder
@@ -21,20 +20,16 @@ import kotlin.test.fail
abstract class ClasspathChangesComputerTest : ClasspathSnapshotTestCommon() {
// TODO Add more test cases:
// - private/non-private fields
// - inline functions
// - changing supertype by adding somethings that changes/does not change the supertype ABI
// - adding an annotation
companion object {
val testDataDir =
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest")
}
@Test
abstract fun testAbiChange_changePublicMethodSignature()
abstract fun testAbiVersusNonAbiChanges()
@Test
abstract fun testNonAbiChange_changeMethodImplementation()
@Test
abstract fun testVariousAbiChanges()
abstract fun testModifiedAddedRemovedElements()
@Test
abstract fun testImpactAnalysis()
@@ -43,38 +38,21 @@ abstract class ClasspathChangesComputerTest : ClasspathSnapshotTestCommon() {
class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
@Test
override fun testAbiChange_changePublicMethodSignature() {
val sourceFile = SimpleKotlinClass(tmpDir)
val previousSnapshot = sourceFile.compileAndSnapshot()
val currentSnapshot = sourceFile.changePublicMethodSignature().compileAndSnapshot()
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
override fun testAbiVersusNonAbiChanges() {
val changes = computeClasspathChanges(File(testDataDir, "testAbiVersusNonAbiChanges/src/kotlin"), tmpDir)
Changes(
lookupSymbols = setOf(
LookupSymbol(name = "publicFunction", scope = "com.example.SimpleKotlinClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SimpleKotlinClass")
LookupSymbol(name = "publicPropertyChangedType", scope = "com.example.SomeClass"),
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)
}
@Test
override fun testNonAbiChange_changeMethodImplementation() {
val sourceFile = SimpleKotlinClass(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)
override fun testModifiedAddedRemovedElements() {
val changes = computeClasspathChanges(File(testDataDir, "testModifiedAddedRemovedElements/src/kotlin"), tmpDir)
Changes(
lookupSymbols = setOf(
// ModifiedClassUnchangedMembers
@@ -94,8 +72,44 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
// RemovedClass
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 = "addedTopLevelProperty", scope = "com.example"),
LookupSymbol(name = "removedTopLevelProperty", scope = "com.example"),
@@ -106,40 +120,78 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
LookupSymbol(name = "movedTopLevelFunction", 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(
"com.example.ModifiedClassUnchangedMembers",
"com.example.ModifiedClassChangedMembers",
"com.example.AddedClass",
"com.example.RemovedClass",
"com.example.NormalClass",
"com.example.NormalClass.CompanionObject",
"com.example.NormalClass.NestedClass",
"com.example"
)
).assertEquals(changes)
}
@Test
override fun testImpactAnalysis() {
val classpathSourceDir =
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)
fun testConstantsAndInlineFunctions() {
val changes = computeClasspathChanges(File(testDataDir, "testConstantsAndInlineFunctions_KotlinOnly/src"), tmpDir)
Changes(
lookupSymbols = setOf(
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedSuperClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.SubClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.SubSubClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedSuperClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.SubClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.SubSubClass"),
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.SubSubClass")
LookupSymbol(name = "constantChangedType", scope = "com.example.SomeClass.CompanionObject"),
// TODO (Fix in next commit). Missing:
// LookupSymbol(name = "constantChangedValue", scope = "com.example.SomeClass.CompanionObject")
LookupSymbol(name = "inlineFunctionChangedSignature", scope = "com.example.SomeClass"),
LookupSymbol(name = "inlineFunctionChangedImplementation", scope = "com.example.SomeClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass"),
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(
"com.example.ChangedSuperClass",
"com.example.SubClass",
"com.example.SubSubClass"
"com.example.SomeClass",
"com.example.SomeClass.CompanionObject",
// TODO (Fix in next commit). Incorrect:
"com.example.SomeClass.Companion"
)
).assertEquals(changes)
}
@@ -155,38 +207,21 @@ class JavaOnlyClasspathChangesComputerTest(private val protoBased: Boolean) : Cl
}
@Test
override fun testAbiChange_changePublicMethodSignature() {
val sourceFile = SimpleJavaClass(tmpDir)
val previousSnapshot = sourceFile.compile().snapshot(protoBased)
val currentSnapshot = sourceFile.changePublicMethodSignature().compile().snapshot(protoBased)
val changes = computeClassChanges(currentSnapshot, previousSnapshot)
override fun testAbiVersusNonAbiChanges() {
val changes = computeClasspathChanges(File(testDataDir, "testAbiVersusNonAbiChanges/src/java"), tmpDir, protoBased)
Changes(
lookupSymbols = setOf(
LookupSymbol(name = "publicMethod", scope = "com.example.SimpleJavaClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SimpleJavaClass")
LookupSymbol(name = "publicFieldChangedType", scope = "com.example.SomeClass"),
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)
}
@Test
override fun testNonAbiChange_changeMethodImplementation() {
val sourceFile = SimpleJavaClass(tmpDir)
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)
override fun testModifiedAddedRemovedElements() {
val changes = computeClasspathChanges(File(testDataDir, "testModifiedAddedRemovedElements/src/java"), tmpDir, protoBased)
Changes(
lookupSymbols = setOf(
// ModifiedClassUnchangedMembers
@@ -218,27 +253,23 @@ class JavaOnlyClasspathChangesComputerTest(private val protoBased: Boolean) : Cl
@Test
override fun testImpactAnalysis() {
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testImpactAnalysis_KotlinOrJava/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)
val changes = computeClasspathChanges(File(testDataDir, "testImpactAnalysis_JavaOnly/src"), tmpDir, protoBased)
Changes(
lookupSymbols = setOf(
LookupSymbol(name = "changedField", scope = "com.example.ChangedSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.SubClass"),
LookupSymbol(name = "changedField", scope = "com.example.SubSubClass"),
LookupSymbol(name = "changedField", scope = "com.example.SubClassOfChangedSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.SubSubClassOfChangedSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.SubClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.SubSubClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.SubClassOfChangedSuperClass"),
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.SubClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SubSubClass")
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.SubClass",
"com.example.SubSubClass"
"com.example.SubClassOfChangedSuperClass",
"com.example.SubSubClassOfChangedSuperClass"
)
).assertEquals(changes)
}
@@ -248,52 +279,55 @@ class KotlinAndJavaClasspathChangesComputerTest : ClasspathSnapshotTestCommon()
@Test
fun testImpactAnalysis() {
val classpathSourceDir = File(testDataDir, "../ClasspathChangesComputerTest/testImpactAnalysis_KotlinAndJava/src").canonicalFile
val currentSnapshot = snapshotClasspath(File(classpathSourceDir, "current-classpath"), tmpDir)
val previousSnapshot = snapshotClasspath(File(classpathSourceDir, "previous-classpath"), tmpDir)
val changes = computeClasspathChanges(currentSnapshot, previousSnapshot)
val changes =
computeClasspathChanges(File(ClasspathChangesComputerTest.testDataDir, "testImpactAnalysis_KotlinAndJava/src"), tmpDir)
Changes(
lookupSymbols = setOf(
LookupSymbol(name = "changedProperty", scope = "com.example.ChangedKotlinSuperClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.KotlinSubClassOfKotlinSuperClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.JavaSubClassOfKotlinSuperClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
LookupSymbol(name = "changedProperty", scope = "com.example.JavaSubClassOfChangedKotlinSuperClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.ChangedKotlinSuperClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.KotlinSubClassOfKotlinSuperClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.JavaSubClassOfKotlinSuperClass"),
LookupSymbol(name = "changedFunction", scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
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.KotlinSubClassOfKotlinSuperClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfKotlinSuperClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfChangedKotlinSuperClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfChangedKotlinSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.ChangedJavaSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.KotlinSubClassOfJavaSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.JavaSubClassOfJavaSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
LookupSymbol(name = "changedField", scope = "com.example.JavaSubClassOfChangedJavaSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.ChangedJavaSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.KotlinSubClassOfJavaSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.JavaSubClassOfJavaSuperClass"),
LookupSymbol(name = "changedMethod", scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
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.KotlinSubClassOfJavaSuperClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfJavaSuperClass")
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.KotlinSubClassOfChangedJavaSuperClass"),
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.JavaSubClassOfChangedJavaSuperClass")
),
fqNames = setOf(
"com.example.ChangedKotlinSuperClass",
"com.example.KotlinSubClassOfKotlinSuperClass",
"com.example.JavaSubClassOfKotlinSuperClass",
"com.example.KotlinSubClassOfChangedKotlinSuperClass",
"com.example.JavaSubClassOfChangedKotlinSuperClass",
"com.example.ChangedJavaSuperClass",
"com.example.KotlinSubClassOfJavaSuperClass",
"com.example.JavaSubClassOfJavaSuperClass"
"com.example.KotlinSubClassOfChangedJavaSuperClass",
"com.example.JavaSubClassOfChangedJavaSuperClass"
)
).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 classpathEntrySnapshots = classpathSourceDir.listFiles()!!.sortedBy { it.name }.map { classpathEntrySourceDir ->
val classFiles = compileAll(classpathEntrySourceDir, classpath, tmpDir)
classpath.addAll(listOfNotNull(classFiles.firstOrNull()?.classRoot))
val relativePaths = classFiles.map { it.unixStyleRelativePath }
val classSnapshots = classFiles.snapshotAll(protoBased).map { it.withHash }
val classSnapshots = classFiles.snapshot(protoBased).map { it.withHash }
ClasspathEntrySnapshot(
classSnapshots = relativePaths.zip(classSnapshots).toMap(LinkedHashMap())
)
@@ -306,16 +340,8 @@ private fun computeClasspathChanges(
previousClasspathSnapshot: ClasspathSnapshot
): Changes {
return ClasspathChangesComputer.computeChangedAndImpactedSet(
currentClasspathSnapshot.getNonDuplicateClassSnapshots(),
previousClasspathSnapshot.getNonDuplicateClassSnapshots(),
DoNothingBuildMetricsReporter
).normalize()
}
private fun computeClassChanges(currentClassSnapshot: ClassSnapshot, previousClassSnapshot: ClassSnapshot): Changes {
return ClasspathChangesComputer.computeClassChanges(
listOf(currentClassSnapshot),
listOf(previousClassSnapshot),
currentClasspathSnapshot.removeDuplicateAndInaccessibleClasses(),
previousClasspathSnapshot.removeDuplicateAndInaccessibleClasses(),
DoNothingBuildMetricsReporter
).normalize()
}
@@ -5,19 +5,26 @@
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.toByteArray
import org.junit.Assert.assertEquals
import org.junit.Test
import java.io.File
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
open fun `test ClassSnapshotDataSerializer`() {
val originalSnapshot = testSourceFile.compileAndSnapshot()
open fun `test ClassSnapshotExternalizer`() {
val originalSnapshot = sourceFile.compileAndSnapshot()
val serializedSnapshot = ClassSnapshotExternalizer.toByteArray(originalSnapshot)
val deserializedSnapshot = ClassSnapshotExternalizer.fromByteArray(serializedSnapshot)
@@ -26,21 +33,20 @@ abstract class ClasspathSnapshotSerializerTest : ClasspathSnapshotTestCommon() {
}
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() {
override val testSourceFile = SimpleJavaClass(tmpDir)
@Test
override fun `test ClassSnapshotDataSerializer`() {
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())
}
override val sourceFile = TestSourceFile(
JavaSourceFile(
baseDir = File(testDataDir, "src/java"), relativePath = "com/example/SimpleClass.java",
), tmpDir
)
}
@@ -6,12 +6,10 @@
package org.jetbrains.kotlin.incremental.classpathDiff
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.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.junit.Rule
import org.junit.rules.TemporaryFolder
@@ -19,11 +17,6 @@ import java.io.File
abstract class ClasspathSnapshotTestCommon {
companion object {
val testDataDir =
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotTestCommon")
}
@get:Rule
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]. */
open class TestSourceFile(val sourceFile: SourceFile, private val tmpDir: TemporaryFolder) {
fun replace(oldValue: String, newValue: String, preCompiledKotlinClassFile: ClassFile? = null): TestSourceFile {
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()
fun asFile() = sourceFile.asFile()
/** Compiles this source file and returns all generated .class files. */
@Suppress("MemberVisibilityCanBePrivate")
fun compileAll(): List<ClassFile> = sourceFile.compile(tmpDir)
fun compile(): List<ClassFile> = sourceFile.compile(tmpDir)
/**
* 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()
fun compileSingle(): ClassFile = compile().single()
/** Compiles this source file and returns the snapshots of all generated .class files. */
fun compileAndSnapshotAll(): List<ClassSnapshot> = compileAll().snapshotAll()
fun compileAndSnapshot() = compileSingle().snapshot()
}
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. */
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> {
if (srcDir.walk().none { it.path.endsWith(".kt") }) {
return emptyList()
@@ -187,70 +154,21 @@ abstract class ClasspathSnapshotTestCommon {
.map { ClassFile(classesDir, it.toRelativeString(classesDir)) }
.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
// to a File is possible.
@Suppress("MemberVisibilityCanBePrivate")
fun ClassFile.asFile() = File(classRoot, unixStyleRelativePath)
@Suppress("MemberVisibilityCanBePrivate")
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()) }
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!")
}
}
@@ -5,141 +5,93 @@
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.assertNotEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.io.File
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 {
@Parameterized.Parameters(name = "protoBased={0}")
@JvmStatic
fun parameters() = listOf(true, false)
val testDataDir =
File("compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest")
}
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
@Before
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
private val expectedSnapshotFile: File
get() = sourceFile.asFile().path.let {
File(it.substringBeforeLast("src") + "expected-snapshot" + it.substringAfterLast("src").substringBeforeLast('.') + ".json")
}
}
@Test
fun `test ClassSnapshotter's result against expected snapshot`() {
val expectedSnapshotFile = File("${testDataDir.path}/expected-snapshot/java/${testSourceFile.nestedClassToTest}.json")
assertEquals(expectedSnapshotFile.readText(), testClassSnapshot.toGson())
val classSnapshot = sourceFile.compileSingle().let {
ClassSnapshotter.snapshot(listOf(ClassFileWithContents(it, it.readBytes())), includeDebugInfoInSnapshot = true)
}.single()
assertEquals(expectedSnapshotFile.readText(), classSnapshot.toGson())
}
@Test
fun `test ClassSnapshotter extracts ABI info from a class`() {
val updatedSnapshot = testSourceFile.changePublicMethodSignature().compileAndSnapshotNestedClass()
assertNotEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
// After an ABI change, the snapshot must change
assertNotEquals(sourceFile.compileAndSnapshot().toGson(), sourceFileWithAbiChange.compileAndSnapshot().toGson())
}
@Test
fun `test ClassSnapshotter does not extract non-ABI info from a class`() {
val updatedSnapshot = testSourceFile.changeMethodImplementation().compileAndSnapshotNestedClass()
assertEquals(testClassSnapshot.toGson(), updatedSnapshot.toGson())
// After a non-ABI change, the snapshot must not change
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
)
}
@@ -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;
}
}
@@ -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;
}
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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
}
@@ -0,0 +1,7 @@
@file:JvmName("MultifileClass")
@file:JvmMultifileClass
package com.example
val propertyInMultifileClass1 = 0
fun functionInMultifileClass1() = 0
@@ -0,0 +1,7 @@
@file:JvmName("MultifileClass")
@file:JvmMultifileClass
package com.example
val propertyInMultifileClass2 = 0
fun functionInMultifileClass2() = 0
@@ -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
}
}
@@ -0,0 +1,10 @@
package com.example
class NormalClass {
companion object CompanionObject {
}
class NestedClass {
}
}
@@ -0,0 +1,4 @@
package com.example;
public class SubSubClassOfChangedSuperClass extends SubClassOfChangedSuperClass {
}
@@ -0,0 +1,4 @@
package com.example;
public class SubSubClassOfChangedSuperClass extends SubClassOfChangedSuperClass {
}
@@ -0,0 +1,4 @@
package com.example;
public class JavaSubClassOfChangedJavaSuperClass extends ChangedJavaSuperClass {
}
@@ -0,0 +1,4 @@
package com.example;
public class JavaSubClassOfChangedKotlinSuperClass extends ChangedKotlinSuperClass {
}
@@ -1,4 +0,0 @@
package com.example;
public class JavaSubClassOfKotlinSuperClass extends ChangedKotlinSuperClass {
}
@@ -0,0 +1,4 @@
package com.example;
public class JavaSubClassOfChangedJavaSuperClass extends ChangedJavaSuperClass {
}
@@ -0,0 +1,4 @@
package com.example;
public class JavaSubClassOfChangedKotlinSuperClass extends ChangedKotlinSuperClass {
}
@@ -1,4 +0,0 @@
package com.example;
public class JavaSubClassOfKotlinSuperClass extends ChangedKotlinSuperClass {
}

Some files were not shown because too many files have changed in this diff Show More