Properly generate inner classes when compiling source for inline
KT-19175: Compiler generates different bytecode when classes are compiled separately or together #KT-19175 Fixed
This commit is contained in:
@@ -192,6 +192,6 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtPureClassOrObject
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
protected ClassDescriptor classForInnerClassRecord() {
|
protected ClassDescriptor classForInnerClassRecord() {
|
||||||
return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
|
return InnerClassConsumer.Companion.classForInnerClassRecord(descriptor, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,35 @@
|
|||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
interface InnerClassConsumer {
|
interface InnerClassConsumer {
|
||||||
fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor)
|
fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun classForInnerClassRecord(descriptor: ClassDescriptor, defaultImpls: Boolean): ClassDescriptor? {
|
||||||
|
if (defaultImpls) {
|
||||||
|
if (DescriptorUtils.isLocal(descriptor)) return null
|
||||||
|
val classDescriptorImpl = ClassDescriptorImpl(
|
||||||
|
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
||||||
|
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
||||||
|
/* isExternal = */ false)
|
||||||
|
|
||||||
|
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
||||||
|
return classDescriptorImpl
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return if (DescriptorUtils.isTopLevelDeclaration(descriptor)) null else descriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -60,14 +60,7 @@ class InterfaceImplBodyCodegen(
|
|||||||
|
|
||||||
override fun classForInnerClassRecord(): ClassDescriptor? {
|
override fun classForInnerClassRecord(): ClassDescriptor? {
|
||||||
if (!isAnythingGenerated) return null
|
if (!isAnythingGenerated) return null
|
||||||
if (DescriptorUtils.isLocal(descriptor)) return null
|
return InnerClassConsumer.classForInnerClassRecord(descriptor, true)
|
||||||
val classDescriptorImpl = ClassDescriptorImpl(
|
|
||||||
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
|
|
||||||
Modality.FINAL, ClassKind.CLASS, Collections.emptyList(), SourceElement.NO_SOURCE,
|
|
||||||
/* isExternal = */ false)
|
|
||||||
|
|
||||||
classDescriptorImpl.initialize(MemberScope.Empty, emptySet(), null)
|
|
||||||
return classDescriptorImpl
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun generateSyntheticPartsAfterBody() {
|
override fun generateSyntheticPartsAfterBody() {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
|||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||||
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
import org.jetbrains.kotlin.fileClasses.FileClasses;
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
|
||||||
@@ -50,7 +49,6 @@ import org.jetbrains.kotlin.psi.*;
|
|||||||
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
|
import org.jetbrains.kotlin.psi.synthetics.SyntheticClassOrObjectDescriptor;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||||
@@ -344,12 +342,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
parentCodegen.innerClasses.add(classDescriptor);
|
parentCodegen.innerClasses.add(classDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
|
addParentsToInnerClassesIfNeeded(innerClasses);
|
||||||
ClassDescriptor outerClass = codegen.classForInnerClassRecord();
|
|
||||||
if (outerClass != null) {
|
|
||||||
innerClasses.add(outerClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ClassDescriptor innerClass : innerClasses) {
|
for (ClassDescriptor innerClass : innerClasses) {
|
||||||
@@ -357,6 +350,18 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void addParentsToInnerClassesIfNeeded(@NotNull Collection<ClassDescriptor> innerClasses) {
|
||||||
|
ClassDescriptor outerClass = classForInnerClassRecord();
|
||||||
|
if (outerClass != null) {
|
||||||
|
innerClasses.add(outerClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemberCodegen<?> parentCodegen = getParentCodegen();
|
||||||
|
if (parentCodegen != null) {
|
||||||
|
parentCodegen.addParentsToInnerClassesIfNeeded(innerClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
|||||||
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
|
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
|
||||||
val classId = classId
|
val classId = classId
|
||||||
val bytes = state.inlineCache.classBytes.getOrPut(classId) { bytecode }
|
val bytes = state.inlineCache.classBytes.getOrPut(classId) { bytecode }
|
||||||
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, classId.asString())
|
return getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, AsmUtil.asmTypeByClassId(classId))
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(callableDescriptor is DeserializedCallableMemberDescriptor) { "Not a deserialized function or proper: " + callableDescriptor }
|
assert(callableDescriptor is DeserializedCallableMemberDescriptor) { "Not a deserialized function or proper: " + callableDescriptor }
|
||||||
@@ -474,7 +474,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
|||||||
throw IllegalStateException("Couldn't find declaration file for " + containerId)
|
throw IllegalStateException("Couldn't find declaration file for " + containerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, containerId.asString()) ?: return null
|
val methodNode = getMethodNode(bytes, asmMethod.name, asmMethod.descriptor, AsmUtil.asmTypeByClassId(containerId)) ?: return null
|
||||||
|
|
||||||
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
// KLUDGE: Inline suspend function built with compiler version less than 1.1.4/1.2-M1 did not contain proper
|
||||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ class DefaultLambda(
|
|||||||
classReader.b,
|
classReader.b,
|
||||||
"<init>",
|
"<init>",
|
||||||
descriptor,
|
descriptor,
|
||||||
lambdaClassType.internalName)?.node
|
lambdaClassType)?.node
|
||||||
|
|
||||||
assert(constructor != null || capturedArgs.isEmpty()) {
|
assert(constructor != null || capturedArgs.isEmpty()) {
|
||||||
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
|
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
|
||||||
@@ -164,7 +164,7 @@ class DefaultLambda(
|
|||||||
classReader.b,
|
classReader.b,
|
||||||
invokeMethod.name,
|
invokeMethod.name,
|
||||||
invokeMethod.descriptor,
|
invokeMethod.descriptor,
|
||||||
lambdaClassType.internalName)!!
|
lambdaClassType)!!
|
||||||
|
|
||||||
if (needReification) {
|
if (needReification) {
|
||||||
//nested classes could also require reification
|
//nested classes could also require reification
|
||||||
|
|||||||
+34
-7
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
@@ -94,6 +95,8 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
|
|
||||||
private var context by Delegates.notNull<CodegenContext<*>>()
|
private var context by Delegates.notNull<CodegenContext<*>>()
|
||||||
|
|
||||||
|
private var additionalInnerClasses = mutableListOf<ClassDescriptor>()
|
||||||
|
|
||||||
override val lookupLocation = KotlinLookupLocation(callElement)
|
override val lookupLocation = KotlinLookupLocation(callElement)
|
||||||
|
|
||||||
|
|
||||||
@@ -164,7 +167,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
if (isLambda)
|
if (isLambda)
|
||||||
codegen.parentCodegen.className
|
codegen.parentCodegen.className
|
||||||
else
|
else
|
||||||
state.typeMapper.mapImplementationOwner(descriptor).internalName
|
state.typeMapper.mapImplementationOwner(descriptor).internalName,
|
||||||
|
if (isLambda) emptyList() else additionalInnerClasses,
|
||||||
|
isLambda
|
||||||
)
|
)
|
||||||
|
|
||||||
val strategy = when (expression) {
|
val strategy = when (expression) {
|
||||||
@@ -222,7 +227,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
internal val delegate: MemberCodegen<*>,
|
internal val delegate: MemberCodegen<*>,
|
||||||
declaration: KtElement,
|
declaration: KtElement,
|
||||||
codegenContext: FieldOwnerContext<*>,
|
codegenContext: FieldOwnerContext<*>,
|
||||||
private val className: String
|
private val className: String,
|
||||||
|
private val parentAsInnerClasses: List<ClassDescriptor>,
|
||||||
|
private val isInlineLambdaCodegen: Boolean
|
||||||
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
|
) : MemberCodegen<KtPureElement>(delegate as MemberCodegen<KtPureElement>, declaration, codegenContext) {
|
||||||
|
|
||||||
override fun generateDeclaration() {
|
override fun generateDeclaration() {
|
||||||
@@ -246,6 +253,14 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
return className
|
return className
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
|
||||||
|
if (isInlineLambdaCodegen) {
|
||||||
|
super.addParentsToInnerClassesIfNeeded(innerClasses)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
innerClasses.addAll(parentAsInnerClasses)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateMethodNodeFromSource(
|
override fun doCreateMethodNodeFromSource(
|
||||||
@@ -278,7 +293,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
||||||
val parentCodegen = FakeMemberCodegen(
|
val parentCodegen = FakeMemberCodegen(
|
||||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||||
implementationOwner.internalName
|
implementationOwner.internalName,
|
||||||
|
additionalInnerClasses,
|
||||||
|
false
|
||||||
)
|
)
|
||||||
if (element !is KtNamedFunction) {
|
if (element !is KtNamedFunction) {
|
||||||
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
|
throw IllegalStateException("Property accessors with default parameters not supported " + callableDescriptor)
|
||||||
@@ -389,22 +406,25 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
|
override fun initializeInlineFunctionContext(functionDescriptor: FunctionDescriptor) {
|
||||||
context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile)
|
context = getContext(functionDescriptor, functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile, additionalInnerClasses)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun getContext(
|
fun getContext(
|
||||||
descriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?
|
descriptor: DeclarationDescriptor, innerDescriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?, additionalInners: MutableList<ClassDescriptor>
|
||||||
): CodegenContext<*> {
|
): CodegenContext<*> {
|
||||||
if (descriptor is PackageFragmentDescriptor) {
|
if (descriptor is PackageFragmentDescriptor) {
|
||||||
|
//no inners
|
||||||
return PackageContext(descriptor, state.rootContext, null, sourceFile)
|
return PackageContext(descriptor, state.rootContext, null, sourceFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
||||||
val parent = getContext(
|
val parent = getContext(
|
||||||
container,
|
container,
|
||||||
|
descriptor,
|
||||||
state,
|
state,
|
||||||
sourceFile
|
sourceFile,
|
||||||
|
additionalInners
|
||||||
)
|
)
|
||||||
|
|
||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
@@ -417,7 +437,14 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
is ClassDescriptor -> {
|
is ClassDescriptor -> {
|
||||||
val kind = if (DescriptorUtils.isInterface(descriptor)) OwnerKind.DEFAULT_IMPLS else OwnerKind.IMPLEMENTATION
|
val kind =
|
||||||
|
if (DescriptorUtils.isInterface(descriptor) && innerDescriptor !is ClassDescriptor)
|
||||||
|
OwnerKind.DEFAULT_IMPLS
|
||||||
|
else OwnerKind.IMPLEMENTATION
|
||||||
|
|
||||||
|
additionalInners.addIfNotNull(
|
||||||
|
InnerClassConsumer.classForInnerClassRecord(descriptor, kind == OwnerKind.DEFAULT_IMPLS)
|
||||||
|
)
|
||||||
parent.intoClass(descriptor, kind, state)
|
parent.intoClass(descriptor, kind, state)
|
||||||
}
|
}
|
||||||
is FunctionDescriptor -> {
|
is FunctionDescriptor -> {
|
||||||
|
|||||||
@@ -89,12 +89,13 @@ private const val INLINE_MARKER_FINALLY_START = "finallyStart"
|
|||||||
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
|
private const val INLINE_MARKER_FINALLY_END = "finallyEnd"
|
||||||
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
|
private const val INLINE_MARKER_BEFORE_SUSPEND_ID = 0
|
||||||
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
||||||
|
private val INTRINSIC_ARRAY_CONSTRUCTOR_TYPE = AsmUtil.asmTypeByClassId(classId)
|
||||||
|
|
||||||
internal fun getMethodNode(
|
internal fun getMethodNode(
|
||||||
classData: ByteArray,
|
classData: ByteArray,
|
||||||
methodName: String,
|
methodName: String,
|
||||||
methodDescriptor: String,
|
methodDescriptor: String,
|
||||||
classInternalName: String
|
classType: Type
|
||||||
): SMAPAndMethodNode? {
|
): SMAPAndMethodNode? {
|
||||||
val cr = ClassReader(classData)
|
val cr = ClassReader(classData)
|
||||||
var node: MethodNode? = null
|
var node: MethodNode? = null
|
||||||
@@ -136,12 +137,12 @@ internal fun getMethodNode(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classId.asString() == classInternalName) {
|
if (INTRINSIC_ARRAY_CONSTRUCTOR_TYPE == classType) {
|
||||||
// Don't load source map for intrinsic array constructors
|
// Don't load source map for intrinsic array constructors
|
||||||
debugInfo[0] = null
|
debugInfo[0] = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classInternalName, lines[0], lines[1])
|
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, lines[0], lines[1])
|
||||||
return SMAPAndMethodNode(node!!, smap)
|
return SMAPAndMethodNode(node!!, smap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
package test
|
||||||
|
|
||||||
|
abstract class Introspector {
|
||||||
|
abstract inner class SchemaRetriever(val transaction: String) {
|
||||||
|
inline fun inSchema(crossinline modifier: (String) -> Unit) =
|
||||||
|
{ modifier.invoke(transaction) }()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
var result = "fail"
|
||||||
|
|
||||||
|
class IntrospectorImpl() : Introspector() {
|
||||||
|
inner class SchemaRetriever(transaction: String) : Introspector.SchemaRetriever(transaction) {
|
||||||
|
internal fun retrieve() {
|
||||||
|
inSchema { schema -> result = schema }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
IntrospectorImpl().SchemaRetriever("OK").retrieve()
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: 1.smap
|
||||||
|
|
||||||
|
SMAP
|
||||||
|
1.kt
|
||||||
|
Kotlin
|
||||||
|
*S Kotlin
|
||||||
|
*F
|
||||||
|
+ 1 1.kt
|
||||||
|
test/Introspector$SchemaRetriever$inSchema$1
|
||||||
|
*L
|
||||||
|
1#1,11:1
|
||||||
|
*E
|
||||||
|
|
||||||
|
// FILE: 2.smap
|
||||||
|
|
||||||
|
SMAP
|
||||||
|
2.kt
|
||||||
|
Kotlin
|
||||||
|
*S Kotlin
|
||||||
|
*F
|
||||||
|
+ 1 2.kt
|
||||||
|
IntrospectorImpl$SchemaRetriever
|
||||||
|
+ 2 1.kt
|
||||||
|
test/Introspector$SchemaRetriever
|
||||||
|
*L
|
||||||
|
1#1,21:1
|
||||||
|
7#2:22
|
||||||
|
*E
|
||||||
|
*S KotlinDebug
|
||||||
|
*F
|
||||||
|
+ 1 2.kt
|
||||||
|
IntrospectorImpl$SchemaRetriever
|
||||||
|
*L
|
||||||
|
9#1:22
|
||||||
|
*E
|
||||||
|
|
||||||
|
SMAP
|
||||||
|
1.kt
|
||||||
|
Kotlin
|
||||||
|
*S Kotlin
|
||||||
|
*F
|
||||||
|
+ 1 1.kt
|
||||||
|
test/Introspector$SchemaRetriever$inSchema$1
|
||||||
|
+ 2 2.kt
|
||||||
|
IntrospectorImpl$SchemaRetriever
|
||||||
|
*L
|
||||||
|
1#1,11:1
|
||||||
|
9#2:12
|
||||||
|
*E
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class Introspector {
|
||||||
|
inner class SchemaRetriever(val transaction: String) {
|
||||||
|
inline fun inSchema(crossinline modifier: (String) -> Unit) =
|
||||||
|
{ modifier(transaction) }()
|
||||||
|
|
||||||
|
internal fun retrieve() {
|
||||||
|
inSchema { schema -> "OK" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TESTED_OBJECT_KIND: innerClass
|
||||||
|
// TESTED_OBJECTS: Introspector$SchemaRetriever$inSchema$1, SchemaRetriever
|
||||||
|
// FLAGS: ACC_FINAL, ACC_PUBLIC
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
interface Introspector {
|
||||||
|
|
||||||
|
class SchemaRetriever(val transaction: String) {
|
||||||
|
inline fun inSchema(crossinline modifier: (String) -> Unit) =
|
||||||
|
{ modifier(transaction) }()
|
||||||
|
|
||||||
|
internal fun retrieve() {
|
||||||
|
inSchema { schema -> "OK" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TESTED_OBJECT_KIND: innerClass
|
||||||
|
// TESTED_OBJECTS: Introspector$SchemaRetriever$inSchema$1, SchemaRetriever
|
||||||
|
// FLAGS: ACC_FINAL, ACC_PUBLIC, ACC_STATIC
|
||||||
|
|
||||||
|
// TESTED_OBJECT_KIND: innerClass
|
||||||
|
// TESTED_OBJECTS: Introspector$SchemaRetriever$inSchema$1, DefaultImpls
|
||||||
|
// ABSENT: true
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
interface Introspector {
|
||||||
|
fun test() {
|
||||||
|
class SchemaRetriever(val transaction: String) {
|
||||||
|
inline fun inSchema(crossinline modifier: (String) -> Unit) =
|
||||||
|
{ modifier(transaction) }()
|
||||||
|
|
||||||
|
internal fun retrieve() {
|
||||||
|
inSchema { schema -> "OK" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TESTED_OBJECT_KIND: innerClass
|
||||||
|
// TESTED_OBJECTS: Introspector$test$SchemaRetriever, SchemaRetriever
|
||||||
|
// FLAGS: ACC_FINAL, ACC_PUBLIC, ACC_STATIC
|
||||||
|
|
||||||
|
// TESTED_OBJECT_KIND: innerClass
|
||||||
|
// TESTED_OBJECTS: Introspector$test$SchemaRetriever, DefaultImpls
|
||||||
|
// FLAGS: ACC_FINAL, ACC_PUBLIC, ACC_STATIC
|
||||||
+1
-1
@@ -261,7 +261,7 @@ public abstract class AbstractWriteFlagsTest extends CodegenTestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitInnerClass(@NotNull String innerClassInternalName, String outerClassInternalName, String name, int access) {
|
public void visitInnerClass(@NotNull String innerClassInternalName, String outerClassInternalName, String name, int access) {
|
||||||
if (name.equals(innerClassName)) {
|
if (innerClassName.equals(name)) {
|
||||||
this.access = access;
|
this.access = access;
|
||||||
isExists = true;
|
isExists = true;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -2755,6 +2755,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt19175.kt")
|
||||||
|
public void testKt19175() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/kt19175.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
||||||
|
|||||||
+6
@@ -2755,6 +2755,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt19175.kt")
|
||||||
|
public void testKt19175() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/kt19175.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
||||||
|
|||||||
@@ -2755,6 +2755,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt19175.kt")
|
||||||
|
public void testKt19175() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/kt19175.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
||||||
|
|||||||
+6
@@ -2755,6 +2755,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/smap/anonymous"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt19175.kt")
|
||||||
|
public void testKt19175() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/kt19175.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambda.kt")
|
@TestMetadata("lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/smap/anonymous/lambda.kt");
|
||||||
|
|||||||
@@ -609,6 +609,33 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/writeFlags/inline")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Inline extends AbstractWriteFlagsTest {
|
||||||
|
public void testAllFilesPresentInInline() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/inline"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lostInnerClass.kt")
|
||||||
|
public void testLostInnerClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/inline/lostInnerClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lostInnerClass2.kt")
|
||||||
|
public void testLostInnerClass2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/inline/lostInnerClass2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("lostInnerClass3.kt")
|
||||||
|
public void testLostInnerClass3() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/inline/lostInnerClass3.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/writeFlags/innerClass")
|
@TestMetadata("compiler/testData/writeFlags/innerClass")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+6
@@ -1466,6 +1466,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("innerClassNotGeneratedWhenRebuilding")
|
||||||
|
public void testInnerClassNotGeneratedWhenRebuilding() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/innerClassNotGeneratedWhenRebuilding/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmNameChanged")
|
@TestMetadata("jvmNameChanged")
|
||||||
public void testJvmNameChanged() throws Exception {
|
public void testJvmNameChanged() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/jvmNameChanged/");
|
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/jvmNameChanged/");
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
abstract class Introspector<M : Model>(protected val model: Model) {
|
||||||
|
protected abstract inner class Retriever(protected val transaction: Any) {
|
||||||
|
protected var model: Model = this@Introspector.model
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract inner class SchemaRetriever(transaction: Any): Retriever(transaction) {
|
||||||
|
protected inline fun inSchema(crossinline modifier: (Any) -> Unit) =
|
||||||
|
model.modify { schema -> modifier.invoke(schema) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
class IntrospectorImpl(model: ModuleImpl) : Introspector<ModuleImpl>(model) {
|
||||||
|
private inner class SchemaRetriever(transaction: Any) : Introspector<ModuleImpl>.SchemaRetriever(transaction) {
|
||||||
|
internal fun retrieve() {
|
||||||
|
inSchema { schema -> println(schema) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModuleImpl : Model {
|
||||||
|
override fun modify(modifier: ModelModifier) {}
|
||||||
|
}
|
||||||
|
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
public interface Model {
|
||||||
|
void modify(ModelModifier modifier);
|
||||||
|
}
|
||||||
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public interface ModelModifier {
|
||||||
|
void perform(Object element);
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
================ Step #1 =================
|
||||||
|
|
||||||
|
Compiling files:
|
||||||
|
src/IntrospectorImpl.kt
|
||||||
|
End of files
|
||||||
|
Exit code: OK
|
||||||
|
------------------------------------------
|
||||||
Reference in New Issue
Block a user