diff --git a/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt b/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt index 564042f283b..d28e0ce336b 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/ChangesCollector.kt @@ -36,32 +36,6 @@ class ChangesCollector { fun protoDataChanges(): Map = storage fun protoDataRemoved(): List = removed - companion object { - fun T.getNonPrivateNames(nameResolver: NameResolver, vararg members: T.() -> List) = - members.flatMap { this.it().filterNot { it.isPrivate }.names(nameResolver) }.toSet() - - fun ClassProtoData.getNonPrivateMemberNames(): Set { - return proto.getNonPrivateNames( - nameResolver, - // The types below should match the logic at `DifferenceCalculatorForClass.difference` - ProtoBuf.Class::getConstructorList, - ProtoBuf.Class::getFunctionList, - ProtoBuf.Class::getPropertyList, - ProtoBuf.Class::getTypeAliasList - ) + proto.enumEntryList.map { nameResolver.getString(it.name) } - } - - fun PackagePartProtoData.getNonPrivateMemberNames(): Set { - return proto.getNonPrivateNames( - nameResolver, - // The types below should match the logic at `DifferenceCalculatorForPackageFacade.difference` - ProtoBuf.Package::getFunctionList, - ProtoBuf.Package::getPropertyList, - ProtoBuf.Package::getTypeAliasList - ) - } - } - fun changes(): List { val changes = arrayListOf() @@ -192,7 +166,7 @@ class ChangesCollector { } private fun PackagePartProtoData.collectAllFromPackage(isRemoved: Boolean) { - val memberNames = getNonPrivateMemberNames() + val memberNames = getNonPrivateMemberNames(includeInlineAccessors = true) if (isRemoved) { collectRemovedMembers(packageFqName, memberNames) } else { @@ -204,14 +178,14 @@ class ChangesCollector { val classFqName = nameResolver.getClassId(proto.fqName).asSingleFqName() if (proto.isCompanionObject) { - val memberNames = getNonPrivateMemberNames() + val memberNames = getNonPrivateMemberNames(includeInlineAccessors = true) val collectMember = if (isRemoved) this@ChangesCollector::collectRemovedMember else this@ChangesCollector::collectChangedMember collectMember(classFqName.parent(), classFqName.shortName().asString()) memberNames.forEach { collectMember(classFqName, it) } } else { if (!isRemoved && collectAllMembersForNewClass) { - val memberNames = getNonPrivateMemberNames() + val memberNames = getNonPrivateMemberNames(includeInlineAccessors = true) memberNames.forEach { this@ChangesCollector.collectChangedMember(classFqName, it) } } diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt index ef7abb55439..41248f93b7e 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalJvmCache.kt @@ -23,8 +23,11 @@ import com.intellij.util.io.EnumeratorStringDescriptor import gnu.trove.THashSet import org.jetbrains.annotations.TestOnly import org.jetbrains.kotlin.build.GeneratedJvmClass +import org.jetbrains.kotlin.incremental.DifferenceCalculatorForClass.Companion.getNonPrivateMembers +import org.jetbrains.kotlin.incremental.DifferenceCalculatorForPackageFacade.Companion.getNonPrivateMembers import org.jetbrains.kotlin.incremental.storage.* -import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames +import org.jetbrains.kotlin.inline.inlineAccessors +import org.jetbrains.kotlin.inline.inlineFunctionsAndAccessors import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto @@ -39,7 +42,8 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.org.objectweb.asm.* -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 java.io.File import java.security.MessageDigest @@ -570,19 +574,26 @@ open class IncrementalJvmCache( val key = kotlinClassInfo.className.internalName val oldMap = storage[key] ?: emptyMap() - val newMap = kotlinClassInfo.inlineFunctionsMap + val newMap = kotlinClassInfo.inlineFunctionsAndAccessorsMap if (newMap.isNotEmpty()) { storage[key] = newMap } else { storage.remove(key) } - for (fn in oldMap.keys + newMap.keys) { + for (methodSignature in oldMap.keys + newMap.keys) { + val inlineFunctionOrAccessorName = functionNameBySignature(methodSignature) + // Note: If we detect a change in an inline property accessor (e.g., `getFoo`), we have two options: + // 1. Report that property `foo` has changed (and ignore `getFoo`) + // 2. Report that property accessor `getFoo` has changed (and ignore `foo`) + // Both options are possible (the compiler generates `LookupSymbol`s for both `foo` and `getFoo` when `getFoo` is inlined). + // Currently, we choose option 2 as it is simpler (i.e., even though inline property accessors are not immediate members of + // a class/package, we treat them like immediate members). changesCollector.collectMemberIfValueWasChanged( kotlinClassInfo.scopeFqName(), - functionNameBySignature(fn), - oldMap[fn], - newMap[fn] + inlineFunctionOrAccessorName, + oldMap[methodSignature], + newMap[methodSignature] ) } } @@ -659,6 +670,28 @@ fun , V> Map.dumpMap(dumpValue: (V) -> String): String = fun > Collection.dumpCollection(): String = "[${sorted().joinToString(", ", transform = Any::toString)}]" +/** + * @param includeInlineAccessors If `true`, also include inline property accessors in the returned list. This is necessary because property + * accessors are not immediate members of a class/package, and in some cases we treat them like immediate members (see + * [org.jetbrains.kotlin.incremental.IncrementalJvmCache.InlineFunctionsMap.process]). Note that here we deal with *inline* property + * accessors only as [org.jetbrains.kotlin.incremental.IncrementalJvmCache.InlineFunctionsMap.process] is written only to handle *inline* + * property accessors (and functions). + */ +fun ProtoData.getNonPrivateMemberNames(includeInlineAccessors: Boolean): List { + return when (this) { + is ClassProtoData -> { + getNonPrivateMembers() + (if (includeInlineAccessors) { + inlineAccessors(proto.propertyList, nameResolver, excludePrivateAccessors = true).map { it.name } + } else emptyList()) + } + is PackagePartProtoData -> { + getNonPrivateMembers() + (if (includeInlineAccessors) { + inlineAccessors(proto.propertyList, nameResolver, excludePrivateAccessors = true).map { it.name } + } else emptyList()) + } + } +} + /** * Minimal information about a Kotlin class to compute recompilation-triggering changes during an incremental run of the `KotlinCompile` * task (see [IncrementalJvmCache.saveClassToCache]). @@ -674,7 +707,7 @@ class KotlinClassInfo constructor( val classHeaderStrings: Array, // Can be empty val multifileClassName: String?, // Not null iff classKind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART val constantsMap: LinkedHashMap, - val inlineFunctionsMap: LinkedHashMap + val inlineFunctionsAndAccessorsMap: LinkedHashMap ) { val className: JvmClassName by lazy { JvmClassName.byClassId(classId) } @@ -726,48 +759,55 @@ class KotlinClassInfo constructor( } fun createFrom(classId: ClassId, classHeader: KotlinClassHeader, classContents: ByteArray): KotlinClassInfo { - val constantsAndInlineFunctions = getConstantsAndInlineFunctions(classHeader, classContents) + val (constants, inlineFunctionsAndAccessors) = getConstantsAndInlineFunctionsOrAccessors(classHeader, classContents) return KotlinClassInfo( classId, classHeader.kind, - classHeader.data ?: classHeader.incompatibleData ?: emptyArray(), + classHeader.data ?: emptyArray(), classHeader.strings ?: emptyArray(), classHeader.multifileClassName, - constantsMap = constantsAndInlineFunctions.first, - inlineFunctionsMap = constantsAndInlineFunctions.second + constants.mapKeysTo(LinkedHashMap()) { it.key.name }, + inlineFunctionsAndAccessors.mapKeysTo(LinkedHashMap()) { it.key.asString() }, ) } } } -/** Parses the class file only once to get both constants and inline functions. */ -private fun getConstantsAndInlineFunctions( +/** + * Parses the class file only once to get both constants and inline functions/property accessors. This is faster than getting them + * separately in two passes. + */ +private fun getConstantsAndInlineFunctionsOrAccessors( classHeader: KotlinClassHeader, classContents: ByteArray -): Pair, LinkedHashMap> { +): Pair, Map> { val constantsClassVisitor = ConstantsClassVisitor() - val inlineFunctionSignatures = inlineFunctionsJvmNames(classHeader) + val inlineFunctionsAndAccessors = inlineFunctionsAndAccessors(classHeader) - return if (inlineFunctionSignatures.isEmpty()) { - ClassReader(classContents).accept(constantsClassVisitor, SKIP_CODE or SKIP_DEBUG or SKIP_FRAMES) - Pair(constantsClassVisitor.getResult(), LinkedHashMap()) + return if (inlineFunctionsAndAccessors.isEmpty()) { + // parsingOptions = (SKIP_CODE, SKIP_DEBUG) as method bodies and debug info are not important for constants + ClassReader(classContents).accept(constantsClassVisitor, SKIP_CODE or SKIP_DEBUG) + Pair(constantsClassVisitor.getResult(), emptyMap()) } else { - val inlineFunctionsClassVisitor = InlineFunctionsClassVisitor(inlineFunctionSignatures, constantsClassVisitor) - ClassReader(classContents).accept(inlineFunctionsClassVisitor, 0) - Pair(constantsClassVisitor.getResult(), inlineFunctionsClassVisitor.getResult()) + val inlineFunctionsAndAccessorsClassVisitor = + InlineFunctionsAndAccessorsClassVisitor(inlineFunctionsAndAccessors.toSet(), constantsClassVisitor) + // parsingOptions must not include (SKIP_CODE, SKIP_DEBUG) as method bodies and debug info (e.g., line numbers) are important for + // inline functions/accessors + ClassReader(classContents).accept(inlineFunctionsAndAccessorsClassVisitor, 0) + Pair(constantsClassVisitor.getResult(), inlineFunctionsAndAccessorsClassVisitor.getResult()) } } private class ConstantsClassVisitor : ClassVisitor(Opcodes.API_VERSION) { - private val result = LinkedHashMap() + private val result = mutableMapOf() override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? { 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 + result[JvmMemberSignature.Field(name, desc)] = value } return null } @@ -775,12 +815,12 @@ private class ConstantsClassVisitor : ClassVisitor(Opcodes.API_VERSION) { fun getResult() = result } -private class InlineFunctionsClassVisitor( - private val inlineFunctionSignatures: Set, - cv: ConstantsClassVisitor // Note: cv must not override the visitMethod (it will not be called with the current implementation below) +private class InlineFunctionsAndAccessorsClassVisitor( + private val inlineFunctionsAndAccessors: Set, + cv: ConstantsClassVisitor // Note: cv must not override `visitMethod` (it will not be called with the current implementation below) ) : ClassVisitor(Opcodes.API_VERSION, cv) { - private val result = LinkedHashMap() + private val result = mutableMapOf() private var classVersion: Int? = null override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array?) { @@ -791,11 +831,8 @@ private class InlineFunctionsClassVisitor( override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { if (access and Opcodes.ACC_PRIVATE == Opcodes.ACC_PRIVATE) return null - // Note: Here, functionSignature = name + descriptor. - // It is different from the `signature` parameter above, which is essentially a more detailed descriptor when generics are used - // (or null otherwise). - val functionSignature = JvmMemberSignature.Method(name, desc).asString() - if (functionSignature !in inlineFunctionSignatures) return null + val method = JvmMemberSignature.Method(name, desc) + if (method !in inlineFunctionsAndAccessors) return null val classWriter = ClassWriter(0) @@ -804,7 +841,7 @@ private class InlineFunctionsClassVisitor( return object : MethodVisitor(Opcodes.API_VERSION, classWriter.visitMethod(access, name, desc, signature, exceptions)) { override fun visitEnd() { - result[functionSignature] = classWriter.toByteArray().md5() + result[method] = classWriter.toByteArray().md5() } } } diff --git a/build-common/src/org/jetbrains/kotlin/incremental/protoDifferenceUtils.kt b/build-common/src/org/jetbrains/kotlin/incremental/protoDifferenceUtils.kt index 53c7c83a450..6e817a3a0ec 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/protoDifferenceUtils.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/protoDifferenceUtils.kt @@ -51,17 +51,17 @@ fun ProtoMapValue.toProtoData(packageFqName: FqName): ProtoData = } internal val MessageLite.isPrivate: Boolean - get() = DescriptorVisibilities.isPrivate( - ProtoEnumFlags.descriptorVisibility( - when (this) { - is ProtoBuf.Constructor -> Flags.VISIBILITY.get(flags) - is ProtoBuf.Function -> Flags.VISIBILITY.get(flags) - is ProtoBuf.Property -> Flags.VISIBILITY.get(flags) - is ProtoBuf.TypeAlias -> Flags.VISIBILITY.get(flags) - else -> error("Unknown message: $this") - } - ) - ) + get() { + val visibility = when (this) { + is ProtoBuf.Constructor -> Flags.VISIBILITY.get(flags) + is ProtoBuf.Function -> Flags.VISIBILITY.get(flags) + is ProtoBuf.Property -> Flags.VISIBILITY.get(flags) + is ProtoBuf.TypeAlias -> Flags.VISIBILITY.get(flags) + is ProtoBuf.EnumEntry -> return false // EnumEntry doesn't have a visibility flag + else -> error("Unknown message: $this") + } + return DescriptorVisibilities.isPrivate(ProtoEnumFlags.descriptorVisibility(visibility)) + } private fun MessageLite.name(nameResolver: NameResolver): String { return when (this) { @@ -69,6 +69,7 @@ private fun MessageLite.name(nameResolver: NameResolver): String { is ProtoBuf.Function -> nameResolver.getString(name) is ProtoBuf.Property -> nameResolver.getString(name) is ProtoBuf.TypeAlias -> nameResolver.getString(name) + is ProtoBuf.EnumEntry -> nameResolver.getString(name) else -> error("Unknown message: $this") } } @@ -307,6 +308,25 @@ class DifferenceCalculatorForClass( return Difference(isClassAffected, areSubclassesAffected, names, changedSupertypes) } + + companion object { + + fun ClassProtoData.getNonPrivateMembers(): List { + val membersResolvers: List<(ProtoBuf.Class) -> List> = listOf( + // This list must match the logic in `DifferenceCalculatorForClass.difference` + // TODO: Consider adding COMPANION_OBJECT_NAME and NESTED_CLASS_NAME_LIST as they are also members of a class (see + // `DifferenceCalculatorForClass.difference`) + ProtoBuf.Class::getConstructorList, + ProtoBuf.Class::getFunctionList, + ProtoBuf.Class::getPropertyList, + ProtoBuf.Class::getTypeAliasList, + ProtoBuf.Class::getEnumEntryList + ) + return membersResolvers.flatMap { membersResolver -> + membersResolver(proto).filterNot { it.isPrivate }.names(nameResolver) + } + } + } } class DifferenceCalculatorForPackageFacade( @@ -362,6 +382,21 @@ class DifferenceCalculatorForPackageFacade( return Difference(changedMembersNames = names) } + + companion object { + + fun PackagePartProtoData.getNonPrivateMembers(): List { + val membersResolvers: List<(ProtoBuf.Package) -> List> = listOf( + // This list must match the logic in `DifferenceCalculatorForPackageFacade.difference` + ProtoBuf.Package::getFunctionList, + ProtoBuf.Package::getPropertyList, + ProtoBuf.Package::getTypeAliasList + ) + return membersResolvers.flatMap { membersResolver -> + membersResolver(proto).filterNot { it.isPrivate }.names(nameResolver) + } + } + } } private val ProtoBuf.Class.isSealed: Boolean diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt index 237aefd25e6..edd4e01c5cc 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/inline/inlineUtil.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.inline +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.Flags @@ -24,57 +25,68 @@ import org.jetbrains.kotlin.metadata.deserialization.TypeTable import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf.JvmMethodSignature +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil +import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags +import org.jetbrains.kotlin.serialization.deserialization.descriptorVisibility -fun inlineFunctionsJvmNames(header: KotlinClassHeader): Set { - val annotationData = header.data ?: return emptySet() - val strings = header.strings ?: return emptySet() +fun inlineFunctionsAndAccessors(header: KotlinClassHeader): List { + val data = header.data ?: return emptyList() + val strings = header.strings ?: return emptyList() return when (header.kind) { KotlinClassHeader.Kind.CLASS -> { - val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(annotationData, strings) - inlineFunctionsJvmNames(classProto.functionList, nameResolver, classProto.typeTable) + - inlineAccessorsJvmNames(classProto.propertyList, nameResolver) + val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(data, strings) + inlineFunctions(classProto.functionList, nameResolver, classProto.typeTable) + + inlineAccessors(classProto.propertyList, nameResolver) } KotlinClassHeader.Kind.FILE_FACADE, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> { - val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(annotationData, strings) - inlineFunctionsJvmNames(packageProto.functionList, nameResolver, packageProto.typeTable) + - inlineAccessorsJvmNames(packageProto.propertyList, nameResolver) + val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(data, strings) + inlineFunctions(packageProto.functionList, nameResolver, packageProto.typeTable) + + inlineAccessors(packageProto.propertyList, nameResolver) } - else -> emptySet() + else -> emptyList() } } -private fun inlineFunctionsJvmNames(functions: List, nameResolver: NameResolver, protoTypeTable: ProtoBuf.TypeTable): Set { +private fun inlineFunctions( + functions: List, + nameResolver: NameResolver, + protoTypeTable: ProtoBuf.TypeTable +): List { val typeTable = TypeTable(protoTypeTable) - val inlineFunctions = functions.filter { Flags.IS_INLINE.get(it.flags) } - val jvmNames = inlineFunctions.mapNotNull { - JvmProtoBufUtil.getJvmMethodSignature(it, nameResolver, typeTable)?.asString() + return functions.filter { Flags.IS_INLINE.get(it.flags) }.mapNotNull { + JvmProtoBufUtil.getJvmMethodSignature(it, nameResolver, typeTable) } - return jvmNames.toSet() } -private fun inlineAccessorsJvmNames(properties: List, nameResolver: NameResolver): Set { - val propertiesWithInlineAccessors = properties.filter { proto -> - proto.hasGetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.getterFlags) || - proto.hasSetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.setterFlags) - } - val inlineAccessors = arrayListOf() - propertiesWithInlineAccessors.forEach { proto -> - val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature) - if (signature != null) { - if (proto.hasGetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.getterFlags)) { - inlineAccessors.add(signature.getter) - } +fun inlineAccessors( + properties: List, + nameResolver: NameResolver, + excludePrivateAccessors: Boolean = false +): List { + val inlineAccessors = mutableListOf() - if (proto.hasSetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.setterFlags)) { - inlineAccessors.add(signature.setter) + fun isInline(flags: Int) = Flags.IS_INLINE_ACCESSOR.get(flags) + fun isPrivate(flags: Int) = DescriptorVisibilities.isPrivate(ProtoEnumFlags.descriptorVisibility(Flags.VISIBILITY.get(flags))) + + properties.forEach { property -> + val propertySignature = property.getExtensionOrNull(JvmProtoBuf.propertySignature) ?: return@forEach + + if (property.hasGetterFlags() && isInline(property.getterFlags)) { + if (!(excludePrivateAccessors && isPrivate(property.getterFlags))) { + inlineAccessors.add(propertySignature.getter) + } + } + if (property.hasSetterFlags() && isInline(property.setterFlags)) { + if (!(excludePrivateAccessors && isPrivate(property.setterFlags))) { + inlineAccessors.add(propertySignature.setter) } } } return inlineAccessors.map { - nameResolver.getString(it.name) + nameResolver.getString(it.desc) - }.toSet() + JvmMemberSignature.Method(name = nameResolver.getString(it.name), desc = nameResolver.getString(it.desc)) + } } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/AbiSnapshotDiffService.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/AbiSnapshotDiffService.kt index 43fdca1f403..59ed70b99bc 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/AbiSnapshotDiffService.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/AbiSnapshotDiffService.kt @@ -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( diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt index 8872ab3230f..41403653717 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/BasicClassInfo.kt @@ -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() diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotSerializer.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotSerializer.kt index 4a9d8a51f5e..f41bfbb8e21 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotSerializer.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotSerializer.kt @@ -186,7 +186,7 @@ internal object KotlinClassInfoExternalizer : DataExternalizer 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 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) ) } } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotter.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotter.kt index cbdd5cb00d4..90e1a2d5f28 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotter.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotter.kt @@ -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, diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/Impact.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/Impact.kt index 5d3819a7c40..27976540cc5 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/Impact.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/Impact.kt @@ -183,7 +183,10 @@ private object ConstantsInCompanionObjectsImpact : Impact { } else null } }.toMap() - val classToCompanionObject: Map = companionObjectToConstants.keys.associateBy { it.parentClassId!! } + val classToCompanionObject: Map = 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 { @@ -211,6 +214,7 @@ private object ConstantsInCompanionObjectsImpact : Impact { return object : ImpactingClassesResolver { override fun getImpactingClasses(classId: ClassId): Set { return if (classId in companionObjects) { + // classId.parentClassId should be present in `allClasses` as this is a companion object setOf(classId.parentClassId!!) } else emptySet() } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/JavaClassSnapshotter.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/JavaClassSnapshotter.kt index dc32d38e46f..f28e3356ac2 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/JavaClassSnapshotter.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/classpathDiff/JavaClassSnapshotter.kt @@ -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) diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest.kt index d7efbb3ea8f..61cf45b6358 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest.kt @@ -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() { diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/current-classpath/com/example/SomeClass.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/current-classpath/com/example/SomeClass.class index b7d405bb17c..5e264cba77a 100644 Binary files a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/current-classpath/com/example/SomeClass.class and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/current-classpath/com/example/SomeClass.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/previous-classpath/com/example/SomeClass.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/previous-classpath/com/example/SomeClass.class index 27c5ceb2556..548cf4ebaa2 100644 Binary files a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/previous-classpath/com/example/SomeClass.class and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/classes/previous-classpath/com/example/SomeClass.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/current-classpath/com/example/SomeClass.kt b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/current-classpath/com/example/SomeClass.kt index 660aeb42721..c3676ce9f7a 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/current-classpath/com/example/SomeClass.kt +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/current-classpath/com/example/SomeClass.kt @@ -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 } \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/previous-classpath/com/example/SomeClass.kt b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/previous-classpath/com/example/SomeClass.kt index c75bad71253..0f4c228bd36 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/previous-classpath/com/example/SomeClass.kt +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testConstantsAndInlineFunctions/src/previous-classpath/com/example/SomeClass.kt @@ -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 } \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClass.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClass.class new file mode 100644 index 00000000000..6b9a84a265b Binary files /dev/null and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClass.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClassKt.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClassKt.class new file mode 100644 index 00000000000..fdf143c4ddb Binary files /dev/null and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/current-classpath/com/example/SomeClassKt.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClass.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClass.class new file mode 100644 index 00000000000..3fd854545a7 Binary files /dev/null and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClass.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClassKt.class b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClassKt.class new file mode 100644 index 00000000000..f995dcc3ed4 Binary files /dev/null and b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/classes/previous-classpath/com/example/SomeClassKt.class differ diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/current-classpath/com/example/SomeClass.kt b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/current-classpath/com/example/SomeClass.kt new file mode 100644 index 00000000000..c56aeca601f --- /dev/null +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/current-classpath/com/example/SomeClass.kt @@ -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 + } diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/previous-classpath/com/example/SomeClass.kt b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/previous-classpath/com/example/SomeClass.kt new file mode 100644 index 00000000000..139820c572d --- /dev/null +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathChangesComputerTest/KotlinOnly/testPropertyAccessors/src/previous-classpath/com/example/SomeClass.kt @@ -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 + } diff --git a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json index 88e67fc50cb..29ab0f2dbbf 100644 --- a/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json +++ b/compiler/incremental-compilation-impl/testData/org/jetbrains/kotlin/incremental/classpathDiff/ClasspathSnapshotterTest/kotlin/testSimpleClass/expected-snapshot/com/example/SimpleClass.json @@ -44,7 +44,7 @@ "publicFunction" ], "constantsMap": {}, - "inlineFunctionsMap": {}, + "inlineFunctionsAndAccessorsMap": {}, "className$delegate": { "initializer": {}, "_value": {} diff --git a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt index b44fc10faf8..3bcc2b79c9f 100644 --- a/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt +++ b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/codegen/InlineTestUtil.kt @@ -18,15 +18,15 @@ package org.jetbrains.kotlin.codegen import org.jetbrains.kotlin.backend.common.output.OutputFile import org.jetbrains.kotlin.codegen.coroutines.INVOKE_SUSPEND_METHOD_NAME -import org.jetbrains.kotlin.inline.inlineFunctionsJvmNames +import org.jetbrains.kotlin.inline.inlineFunctionsAndAccessors import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMemberSignature import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.tree.MethodNode -import java.util.* object InlineTestUtil { fun checkNoCallsToInline( @@ -57,13 +57,13 @@ object InlineTestUtil { val binaryClasses = hashMapOf() for (file in files) { val binaryClass = loadBinaryClass(file) - val inlineFunctions = inlineFunctionsJvmNames(binaryClass.classHeader) + val inlineFunctionsAndAccessors = inlineFunctionsAndAccessors(binaryClass.classHeader) val classVisitor = object : ClassVisitorWithName() { override fun visitMethod( access: Int, name: String, desc: String, signature: String?, exceptions: Array? ): MethodVisitor? { - if (name + desc in inlineFunctions) { + if (JvmMemberSignature.Method(name, desc) in inlineFunctionsAndAccessors) { inlineMethods.add(MethodInfo(className, name, desc)) } return null @@ -81,14 +81,14 @@ object InlineTestUtil { var doLambdaInliningCheck = true for (file in files) { val binaryClass = loadBinaryClass(file) - val inlineFunctions = inlineFunctionsJvmNames(binaryClass.classHeader) + val inlineFunctionsAndAccessors = inlineFunctionsAndAccessors(binaryClass.classHeader) //if inline function creates anonymous object then do not try to check that all lambdas are inlined val classVisitor = object : ClassVisitorWithName() { override fun visitMethod( access: Int, name: String, desc: String, signature: String?, exceptions: Array? ): MethodVisitor? { - if (name + desc in inlineFunctions) { + if (JvmMemberSignature.Method(name, desc) in inlineFunctionsAndAccessors) { return object : MethodNodeWithAnonymousObjectCheck(inlineInfo, access, name, desc, signature, exceptions) { override fun onAnonymousConstructorCallOrSingletonAccess(owner: String) { doLambdaInliningCheck = false