New IC: Include inline property accessors in class/package members
Problem: ClasspathChangesComputer (a core component of the new IC) uses
the existing inline function analysis from the old IC
(IncrementalJvmCache.InlineFunctionsMap). If an inline property accessor
has changed, the inline function analysis will report the name of the
property accessor, not the name of the property.
ClasspathChangesComputer doesn't see the property accessor's name in the
list of class/package members, so it will throw an exception.
Solution: There are 2 options:
1. If an inline property accessor has changed, the inline function
analysis can report the name of the property instead of the
property accessor.
2. ClasspathChangesComputer can include property accessors in the list
of class/package members.
In this commit, we will choose option 2 as it is simpler.
Test: New KotlinOnlyClasspathChangesComputerTest.testPropertyAccessors
Small cleanup - PLS SQUASH INTO PREVIOUS COMMIT
- Address review
- Fix failed tests
- Add some trivial changes
^KT-53871 Fixed
This commit is contained in:
committed by
nataliya.valtman
parent
2ba7c7b8a9
commit
03f83ff339
+2
-2
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.jetbrains.kotlin.incremental.ChangesCollector.Companion.getNonPrivateMemberNames
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.Visibility.PRIVATE
|
||||
import org.jetbrains.kotlin.metadata.deserialization.Flags
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -98,7 +97,8 @@ class AbiSnapshotDiffService() {
|
||||
when (protoData) {
|
||||
is ClassProtoData -> {
|
||||
fqNames.add(fqName)
|
||||
symbols.addAll(protoData.getNonPrivateMemberNames().map { LookupSymbol(it, fqName.asString()) })
|
||||
symbols.addAll(
|
||||
protoData.getNonPrivateMemberNames(includeInlineAccessors = true).map { LookupSymbol(it, fqName.asString()) })
|
||||
}
|
||||
is PackagePartProtoData -> {
|
||||
symbols.addAll(
|
||||
|
||||
+4
-2
@@ -12,7 +12,8 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader.*
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
|
||||
@@ -47,7 +48,8 @@ class BasicClassInfo(
|
||||
val innerClassesClassVisitor = InnerClassesClassVisitor(kotlinClassHeaderClassVisitor)
|
||||
val basicClassInfoVisitor = BasicClassInfoClassVisitor(innerClassesClassVisitor)
|
||||
|
||||
ClassReader(classContents).accept(basicClassInfoVisitor, SKIP_CODE or SKIP_DEBUG or SKIP_FRAMES)
|
||||
// parsingOptions = (SKIP_CODE, SKIP_DEBUG) as method bodies and debug info are not important
|
||||
ClassReader(classContents).accept(basicClassInfoVisitor, SKIP_CODE or SKIP_DEBUG)
|
||||
|
||||
val className = basicClassInfoVisitor.getClassName()
|
||||
val innerClassesInfo = innerClassesClassVisitor.getInnerClassesInfo()
|
||||
|
||||
+2
-2
@@ -186,7 +186,7 @@ internal object KotlinClassInfoExternalizer : DataExternalizer<KotlinClassInfo>
|
||||
ListExternalizer(StringExternalizer).save(output, info.classHeaderStrings.toList())
|
||||
NullableValueExternalizer(StringExternalizer).save(output, info.multifileClassName)
|
||||
LinkedHashMapExternalizer(StringExternalizer, ConstantExternalizer).save(output, info.constantsMap)
|
||||
LinkedHashMapExternalizer(StringExternalizer, LongExternalizer).save(output, info.inlineFunctionsMap)
|
||||
LinkedHashMapExternalizer(StringExternalizer, LongExternalizer).save(output, info.inlineFunctionsAndAccessorsMap)
|
||||
}
|
||||
|
||||
override fun read(input: DataInput): KotlinClassInfo {
|
||||
@@ -198,7 +198,7 @@ internal object KotlinClassInfoExternalizer : DataExternalizer<KotlinClassInfo>
|
||||
classHeaderStrings = ListExternalizer(StringExternalizer).read(input).toTypedArray(),
|
||||
multifileClassName = NullableValueExternalizer(StringExternalizer).read(input),
|
||||
constantsMap = LinkedHashMapExternalizer(StringExternalizer, ConstantExternalizer).read(input),
|
||||
inlineFunctionsMap = LinkedHashMapExternalizer(StringExternalizer, LongExternalizer).read(input)
|
||||
inlineFunctionsAndAccessorsMap = LinkedHashMapExternalizer(StringExternalizer, LongExternalizer).read(input)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -9,10 +9,9 @@ import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||
import org.jetbrains.kotlin.build.report.metrics.BuildTime
|
||||
import org.jetbrains.kotlin.build.report.metrics.DoNothingBuildMetricsReporter
|
||||
import org.jetbrains.kotlin.build.report.metrics.measure
|
||||
import org.jetbrains.kotlin.incremental.ChangesCollector.Companion.getNonPrivateMemberNames
|
||||
import org.jetbrains.kotlin.incremental.KotlinClassInfo
|
||||
import org.jetbrains.kotlin.incremental.PackagePartProtoData
|
||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClassSnapshotGranularity.CLASS_MEMBER_LEVEL
|
||||
import org.jetbrains.kotlin.incremental.getNonPrivateMemberNames
|
||||
import org.jetbrains.kotlin.incremental.md5
|
||||
import org.jetbrains.kotlin.incremental.storage.toByteArray
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.*
|
||||
@@ -97,7 +96,7 @@ object ClassSnapshotter {
|
||||
)
|
||||
FILE_FACADE, MULTIFILE_CLASS_PART -> PackageFacadeKotlinClassSnapshot(
|
||||
classId, classAbiHash, classMemberLevelSnapshot,
|
||||
packageMemberNames = (kotlinClassInfo.protoData as PackagePartProtoData).getNonPrivateMemberNames()
|
||||
packageMemberNames = kotlinClassInfo.protoData.getNonPrivateMemberNames(includeInlineAccessors = true).toSet()
|
||||
)
|
||||
MULTIFILE_CLASS -> MultifileClassKotlinClassSnapshot(
|
||||
classId, classAbiHash, classMemberLevelSnapshot,
|
||||
|
||||
+5
-1
@@ -183,7 +183,10 @@ private object ConstantsInCompanionObjectsImpact : Impact {
|
||||
} else null
|
||||
}
|
||||
}.toMap()
|
||||
val classToCompanionObject: Map<ClassId, ClassId> = companionObjectToConstants.keys.associateBy { it.parentClassId!! }
|
||||
val classToCompanionObject: Map<ClassId, ClassId> = companionObjectToConstants.keys.associateBy { companionObject ->
|
||||
// companionObject.parentClassId should be present in `allClasses` as this is a companion object
|
||||
companionObject.parentClassId!!
|
||||
}
|
||||
|
||||
return object : ImpactedSymbolsResolver {
|
||||
override fun getImpactedClasses(classId: ClassId): Set<ClassId> {
|
||||
@@ -211,6 +214,7 @@ private object ConstantsInCompanionObjectsImpact : Impact {
|
||||
return object : ImpactingClassesResolver {
|
||||
override fun getImpactingClasses(classId: ClassId): Set<ClassId> {
|
||||
return if (classId in companionObjects) {
|
||||
// classId.parentClassId should be present in `allClasses` as this is a companion object
|
||||
setOf(classId.parentClassId!!)
|
||||
} else emptySet()
|
||||
}
|
||||
|
||||
+4
-4
@@ -28,11 +28,11 @@ object JavaClassSnapshotter {
|
||||
|
||||
// First, collect all info.
|
||||
// Note the parsing options passed to ClassReader:
|
||||
// - SKIP_CODE and SKIP_FRAMES are set as method bodies will not be part of the ABI of the class.
|
||||
// - SKIP_DEBUG is not set as it would skip method parameters, which may be used by annotation processors like Room.
|
||||
// - EXPAND_FRAMES is not needed (and not relevant when SKIP_CODE is set).
|
||||
// - SKIP_CODE is set as method bodies will not be part of the ABI of the class.
|
||||
// - SKIP_DEBUG seems possible but is *not* set just to be safe, so that we don't skip any info that might be important.
|
||||
// - SKIP_FRAMES or EXPAND_FRAMES is not needed (and not relevant when SKIP_CODE is set).
|
||||
val classReader = ClassReader(classFile.contents)
|
||||
classReader.accept(abiClass, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES)
|
||||
classReader.accept(abiClass, ClassReader.SKIP_CODE)
|
||||
|
||||
// Then, remove non-ABI info, which includes:
|
||||
// - Method bodies: Should have already been removed (see SKIP_CODE above)
|
||||
|
||||
+25
@@ -202,6 +202,7 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
||||
|
||||
LookupSymbol(name = "inlineFunctionChangedSignature", scope = "com.example.SomeClass"),
|
||||
LookupSymbol(name = "inlineFunctionChangedImplementation", scope = "com.example.SomeClass"),
|
||||
LookupSymbol(name = "inlineFunctionChangedLineNumber", 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"),
|
||||
@@ -213,6 +214,30 @@ class KotlinOnlyClasspathChangesComputerTest : ClasspathChangesComputerTest() {
|
||||
).assertEquals(changes)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPropertyAccessors() {
|
||||
val changes = computeClasspathChanges(File(testDataDir, "KotlinOnly/testPropertyAccessors/src"), tmpDir)
|
||||
Changes(
|
||||
lookupSymbols = setOf(
|
||||
LookupSymbol(name = "property_ChangedType", scope = "com.example.SomeClass"),
|
||||
|
||||
LookupSymbol(name = "inlineProperty_ChangedType", scope = "com.example"),
|
||||
LookupSymbol(name = "inlineProperty_ChangedType_BackingField", scope = "com.example"),
|
||||
LookupSymbol(name = "getInlineProperty_ChangedType", scope = "com.example"),
|
||||
LookupSymbol(name = "setInlineProperty_ChangedType", scope = "com.example"),
|
||||
|
||||
LookupSymbol(name = "getInlineProperty_ChangedGetterImpl", scope = "com.example"),
|
||||
LookupSymbol(name = "setInlineProperty_ChangedSetterImpl", scope = "com.example"),
|
||||
|
||||
LookupSymbol(name = SAM_LOOKUP_NAME.asString(), scope = "com.example.SomeClass")
|
||||
),
|
||||
fqNames = setOf(
|
||||
"com.example",
|
||||
"com.example.SomeClass"
|
||||
)
|
||||
).assertEquals(changes)
|
||||
}
|
||||
|
||||
/** Tests [SupertypesInheritorsImpact]. */
|
||||
@Test
|
||||
override fun testImpactComputation_SupertypesInheritors() {
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
+2
@@ -14,6 +14,8 @@ class SomeClass {
|
||||
|
||||
inline fun inlineFunctionChangedSignature(): Long = 0
|
||||
inline fun inlineFunctionChangedImplementation(): Int = 1000
|
||||
|
||||
inline fun inlineFunctionChangedLineNumber(): Int = 0
|
||||
inline fun inlineFunctionChangedUnchanged(): Int = 0
|
||||
private inline fun privateInlineFunctionChangedSignature(): Long = 0
|
||||
}
|
||||
+2
@@ -14,6 +14,8 @@ class SomeClass {
|
||||
|
||||
inline fun inlineFunctionChangedSignature(): Int = 0
|
||||
inline fun inlineFunctionChangedImplementation(): Int = 0
|
||||
inline fun inlineFunctionChangedLineNumber(): 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.
+79
@@ -0,0 +1,79 @@
|
||||
package com.example
|
||||
|
||||
@Suppress("RedundantGetter", "RedundantSetter")
|
||||
class SomeClass {
|
||||
|
||||
var property_ChangedType: Long = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_ChangedGetterImpl: Int = 0
|
||||
get() {
|
||||
println("Getter implementation has changed!")
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_ChangedSetterImpl: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
println("Setter implementation has changed!")
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_Unchanged: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
private var privateProperty_ChangedType: Long = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
var inlineProperty_ChangedType_BackingField: Long = 0
|
||||
var inlineProperty_ChangedGetterImpl_BackingField: Int = 0
|
||||
var inlineProperty_ChangedSetterImpl_BackingField: Int = 0
|
||||
var inlineProperty_Unchanged_BackingField: Int = 0
|
||||
private var privateInlineProperty_ChangedType_BackingField: Long = 0
|
||||
|
||||
inline var inlineProperty_ChangedType: Long
|
||||
get() = inlineProperty_ChangedType_BackingField
|
||||
set(value) {
|
||||
inlineProperty_ChangedType_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_ChangedGetterImpl: Int
|
||||
get() {
|
||||
println("Getter implementation has changed!")
|
||||
return inlineProperty_ChangedGetterImpl_BackingField
|
||||
}
|
||||
set(value) {
|
||||
inlineProperty_ChangedGetterImpl_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_ChangedSetterImpl: Int
|
||||
get() = inlineProperty_ChangedSetterImpl_BackingField
|
||||
set(value) {
|
||||
println("Setter implementation has changed!")
|
||||
inlineProperty_ChangedSetterImpl_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_Unchanged: Int
|
||||
get() = inlineProperty_Unchanged_BackingField
|
||||
set(value) {
|
||||
inlineProperty_Unchanged_BackingField = value
|
||||
}
|
||||
|
||||
private inline var privateInlineProperty_ChangedType: Long
|
||||
get() = privateInlineProperty_ChangedType_BackingField
|
||||
set(value) {
|
||||
privateInlineProperty_ChangedType_BackingField = value
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package com.example
|
||||
|
||||
@Suppress("RedundantGetter", "RedundantSetter")
|
||||
class SomeClass {
|
||||
|
||||
var property_ChangedType: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_ChangedGetterImpl: Int = 0
|
||||
get() {
|
||||
println("Getter implementation")
|
||||
return field
|
||||
}
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_ChangedSetterImpl: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
println("Setter implementation")
|
||||
field = value
|
||||
}
|
||||
|
||||
var property_Unchanged: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
private var privateProperty_ChangedType: Int = 0
|
||||
get() = field
|
||||
set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
var inlineProperty_ChangedType_BackingField: Int = 0
|
||||
var inlineProperty_ChangedGetterImpl_BackingField: Int = 0
|
||||
var inlineProperty_ChangedSetterImpl_BackingField: Int = 0
|
||||
var inlineProperty_Unchanged_BackingField: Int = 0
|
||||
private var privateInlineProperty_ChangedType_BackingField: Int = 0
|
||||
|
||||
inline var inlineProperty_ChangedType: Int
|
||||
get() = inlineProperty_ChangedType_BackingField
|
||||
set(value) {
|
||||
inlineProperty_ChangedType_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_ChangedGetterImpl: Int
|
||||
get() {
|
||||
println("Getter implementation")
|
||||
return inlineProperty_ChangedGetterImpl_BackingField
|
||||
}
|
||||
set(value) {
|
||||
inlineProperty_ChangedGetterImpl_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_ChangedSetterImpl: Int
|
||||
get() = inlineProperty_ChangedSetterImpl_BackingField
|
||||
set(value) {
|
||||
println("Setter implementation")
|
||||
inlineProperty_ChangedSetterImpl_BackingField = value
|
||||
}
|
||||
|
||||
inline var inlineProperty_Unchanged: Int
|
||||
get() = inlineProperty_Unchanged_BackingField
|
||||
set(value) {
|
||||
inlineProperty_Unchanged_BackingField = value
|
||||
}
|
||||
|
||||
private inline var privateInlineProperty_ChangedType: Int
|
||||
get() = privateInlineProperty_ChangedType_BackingField
|
||||
set(value) {
|
||||
privateInlineProperty_ChangedType_BackingField = value
|
||||
}
|
||||
+1
-1
@@ -44,7 +44,7 @@
|
||||
"publicFunction"
|
||||
],
|
||||
"constantsMap": {},
|
||||
"inlineFunctionsMap": {},
|
||||
"inlineFunctionsAndAccessorsMap": {},
|
||||
"className$delegate": {
|
||||
"initializer": {},
|
||||
"_value": {}
|
||||
|
||||
Reference in New Issue
Block a user