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
|
||||
@Override
|
||||
protected ClassDescriptor classForInnerClassRecord() {
|
||||
return DescriptorUtils.isTopLevelDeclaration(descriptor) ? null : descriptor;
|
||||
return InnerClassConsumer.Companion.classForInnerClassRecord(descriptor, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,35 @@
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
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 {
|
||||
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? {
|
||||
if (!isAnythingGenerated) return null
|
||||
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
|
||||
return InnerClassConsumer.classForInnerClassRecord(descriptor, true)
|
||||
}
|
||||
|
||||
override fun generateSyntheticPartsAfterBody() {
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
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.fileClasses.FileClasses;
|
||||
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.resolve.BindingContext;
|
||||
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.constants.ConstantValue;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -344,12 +342,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
parentCodegen.innerClasses.add(classDescriptor);
|
||||
}
|
||||
|
||||
for (MemberCodegen<?> codegen = this; codegen != null; codegen = codegen.getParentCodegen()) {
|
||||
ClassDescriptor outerClass = codegen.classForInnerClassRecord();
|
||||
if (outerClass != null) {
|
||||
innerClasses.add(outerClass);
|
||||
}
|
||||
}
|
||||
addParentsToInnerClassesIfNeeded(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
|
||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||
@Override
|
||||
|
||||
@@ -460,7 +460,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
|
||||
val classId = classId
|
||||
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 }
|
||||
@@ -474,7 +474,7 @@ abstract class InlineCodegen<out T: BaseExpressionCodegen>(
|
||||
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
|
||||
// before/after suspension point marks, so we detect those functions here and insert the corresponding marks
|
||||
|
||||
@@ -135,7 +135,7 @@ class DefaultLambda(
|
||||
classReader.b,
|
||||
"<init>",
|
||||
descriptor,
|
||||
lambdaClassType.internalName)?.node
|
||||
lambdaClassType)?.node
|
||||
|
||||
assert(constructor != null || capturedArgs.isEmpty()) {
|
||||
"Can't find non-default constructor <init>$descriptor for default lambda $lambdaClassType"
|
||||
@@ -164,7 +164,7 @@ class DefaultLambda(
|
||||
classReader.b,
|
||||
invokeMethod.name,
|
||||
invokeMethod.descriptor,
|
||||
lambdaClassType.internalName)!!
|
||||
lambdaClassType)!!
|
||||
|
||||
if (needReification) {
|
||||
//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.calls.callUtil.getResolvedCallWithAssert
|
||||
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.MethodVisitor
|
||||
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 additionalInnerClasses = mutableListOf<ClassDescriptor>()
|
||||
|
||||
override val lookupLocation = KotlinLookupLocation(callElement)
|
||||
|
||||
|
||||
@@ -164,7 +167,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
if (isLambda)
|
||||
codegen.parentCodegen.className
|
||||
else
|
||||
state.typeMapper.mapImplementationOwner(descriptor).internalName
|
||||
state.typeMapper.mapImplementationOwner(descriptor).internalName,
|
||||
if (isLambda) emptyList() else additionalInnerClasses,
|
||||
isLambda
|
||||
)
|
||||
|
||||
val strategy = when (expression) {
|
||||
@@ -222,7 +227,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
internal val delegate: MemberCodegen<*>,
|
||||
declaration: KtElement,
|
||||
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) {
|
||||
|
||||
override fun generateDeclaration() {
|
||||
@@ -246,6 +253,14 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
return className
|
||||
}
|
||||
|
||||
override fun addParentsToInnerClassesIfNeeded(innerClasses: MutableCollection<ClassDescriptor>) {
|
||||
if (isInlineLambdaCodegen) {
|
||||
super.addParentsToInnerClassesIfNeeded(innerClasses)
|
||||
}
|
||||
else {
|
||||
innerClasses.addAll(parentAsInnerClasses)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun doCreateMethodNodeFromSource(
|
||||
@@ -278,7 +293,9 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val implementationOwner = state.typeMapper.mapImplementationOwner(callableDescriptor)
|
||||
val parentCodegen = FakeMemberCodegen(
|
||||
codegen.parentCodegen, inliningFunction!!, methodContext.parentContext as FieldOwnerContext<*>,
|
||||
implementationOwner.internalName
|
||||
implementationOwner.internalName,
|
||||
additionalInnerClasses,
|
||||
false
|
||||
)
|
||||
if (element !is KtNamedFunction) {
|
||||
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) {
|
||||
context = getContext(functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile)
|
||||
context = getContext(functionDescriptor, functionDescriptor, state, DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor)?.containingFile as? KtFile, additionalInnerClasses)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getContext(
|
||||
descriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?
|
||||
descriptor: DeclarationDescriptor, innerDescriptor: DeclarationDescriptor, state: GenerationState, sourceFile: KtFile?, additionalInners: MutableList<ClassDescriptor>
|
||||
): CodegenContext<*> {
|
||||
if (descriptor is PackageFragmentDescriptor) {
|
||||
//no inners
|
||||
return PackageContext(descriptor, state.rootContext, null, sourceFile)
|
||||
}
|
||||
|
||||
val container = descriptor.containingDeclaration ?: error("No container for descriptor: " + descriptor)
|
||||
val parent = getContext(
|
||||
container,
|
||||
descriptor,
|
||||
state,
|
||||
sourceFile
|
||||
sourceFile,
|
||||
additionalInners
|
||||
)
|
||||
|
||||
return when (descriptor) {
|
||||
@@ -417,7 +437,14 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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_BEFORE_SUSPEND_ID = 0
|
||||
private const val INLINE_MARKER_AFTER_SUSPEND_ID = 1
|
||||
private val INTRINSIC_ARRAY_CONSTRUCTOR_TYPE = AsmUtil.asmTypeByClassId(classId)
|
||||
|
||||
internal fun getMethodNode(
|
||||
classData: ByteArray,
|
||||
methodName: String,
|
||||
methodDescriptor: String,
|
||||
classInternalName: String
|
||||
classType: Type
|
||||
): SMAPAndMethodNode? {
|
||||
val cr = ClassReader(classData)
|
||||
var node: MethodNode? = null
|
||||
@@ -136,12 +137,12 @@ internal fun getMethodNode(
|
||||
return null
|
||||
}
|
||||
|
||||
if (classId.asString() == classInternalName) {
|
||||
if (INTRINSIC_ARRAY_CONSTRUCTOR_TYPE == classType) {
|
||||
// Don't load source map for intrinsic array constructors
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
public void visitInnerClass(@NotNull String innerClassInternalName, String outerClassInternalName, String name, int access) {
|
||||
if (name.equals(innerClassName)) {
|
||||
if (innerClassName.equals(name)) {
|
||||
this.access = access;
|
||||
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);
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testLambda() throws Exception {
|
||||
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);
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testLambda() throws Exception {
|
||||
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);
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testLambda() throws Exception {
|
||||
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);
|
||||
}
|
||||
|
||||
@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")
|
||||
public void testLambda() throws Exception {
|
||||
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")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+6
@@ -1466,6 +1466,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("innerClassNotGeneratedWhenRebuilding")
|
||||
public void testInnerClassNotGeneratedWhenRebuilding() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/innerClassNotGeneratedWhenRebuilding/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmNameChanged")
|
||||
public void testJvmNameChanged() throws Exception {
|
||||
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