Base support of StackValue.Property inlining

This commit is contained in:
Mikhael Bogdanov
2016-06-21 11:18:40 +03:00
parent d524a34fc7
commit 5a2e00d2ad
12 changed files with 244 additions and 46 deletions
@@ -2264,7 +2264,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
receiver = StackValue.receiverWithoutReceiverArgument(receiver);
}
return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver);
return intermediateValueForProperty(propertyDescriptor, directToField, directToField, superCallTarget, false, receiver, resolvedCall);
}
if (descriptor instanceof ClassDescriptor) {
@@ -2411,7 +2411,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
@Nullable ClassDescriptor superCallTarget,
@NotNull StackValue receiver
) {
return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver);
return intermediateValueForProperty(propertyDescriptor, forceField, false, superCallTarget, false, receiver, null);
}
private CodegenContext getBackingFieldContext(
@@ -2434,7 +2434,8 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
boolean syntheticBackingField,
@Nullable ClassDescriptor superCallTarget,
boolean skipAccessorsForPrivateFieldInOuterClass,
StackValue receiver
@NotNull StackValue receiver,
@Nullable ResolvedCall resolvedCall
) {
if (propertyDescriptor instanceof SyntheticJavaPropertyDescriptor) {
return intermediateValueForSyntheticExtensionProperty((SyntheticJavaPropertyDescriptor) propertyDescriptor, receiver);
@@ -2530,13 +2531,13 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.property(propertyDescriptor, backingFieldOwner,
typeMapper.mapType(
isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver);
isStaticBackingField, fieldName, callableGetter, callableSetter, receiver, this, resolvedCall);
}
@NotNull
private StackValue.Property intermediateValueForSyntheticExtensionProperty(
@NotNull SyntheticJavaPropertyDescriptor propertyDescriptor,
StackValue receiver
@NotNull StackValue receiver
) {
Type type = typeMapper.mapType(propertyDescriptor.getOriginal().getType());
CallableMethod callableGetter =
@@ -2544,7 +2545,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
FunctionDescriptor setMethod = propertyDescriptor.getSetMethod();
CallableMethod callableSetter =
setMethod != null ? typeMapper.mapToCallableMethod(context.accessibleDescriptor(setMethod, null), false) : null;
return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, state, receiver);
return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, receiver, this, null);
}
@Override
@@ -2831,8 +2832,12 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return getOrCreateCallGenerator(descriptor, function, null, true);
}
@NotNull
CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall) {
return getOrCreateCallGenerator(resolvedCall, resolvedCall.getResultingDescriptor());
}
@NotNull
CallGenerator getOrCreateCallGenerator(@NotNull ResolvedCall<?> resolvedCall, @NotNull CallableDescriptor descriptor) {
Map<TypeParameterDescriptor, KotlinType> typeArguments = resolvedCall.getTypeArguments();
TypeParameterMappings mappings = new TypeParameterMappings();
for (Map.Entry<TypeParameterDescriptor, KotlinType> entry : typeArguments.entrySet()) {
@@ -2858,8 +2863,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
);
}
}
return getOrCreateCallGenerator(
resolvedCall.getResultingDescriptor(), resolvedCall.getCall().getCallElement(), mappings, false);
return getOrCreateCallGenerator(descriptor, resolvedCall.getCall().getCallElement(), mappings, false);
}
@@ -391,7 +391,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
KtExpression initializer = property.getDelegateExpressionOrInitializer();
assert initializer != null : "shouldInitializeProperty must return false if initializer is null";
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, false, null, true, StackValue.LOCAL_0);
StackValue.Property propValue = codegen.intermediateValueForProperty(propertyDescriptor, true, false, null, true, StackValue.LOCAL_0,
null);
propValue.store(codegen.gen(initializer), codegen.v);
}
@@ -611,7 +612,8 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
syntheticBackingField ||
original.getVisibility() == JavaVisibilities.PROTECTED_STATIC_VISIBILITY;
StackValue property = codegen.intermediateValueForProperty(
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(), forceFieldForCompanionProperty, StackValue.none()
original, forceField, syntheticBackingField, accessor.getSuperCallTarget(),
forceFieldForCompanionProperty, StackValue.none(), null
);
InstructionAdapter iv = codegen.v;
@@ -271,10 +271,11 @@ public abstract class StackValue {
@Nullable String fieldName,
@Nullable CallableMethod getter,
@Nullable CallableMethod setter,
GenerationState state,
@NotNull StackValue receiver
@NotNull StackValue receiver,
@NotNull ExpressionCodegen codegen,
@Nullable ResolvedCall resolvedCall
) {
return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, state, receiver);
return new Property(descriptor, backingFieldOwner, getter, setter, isStaticBackingField, fieldName, type, receiver, codegen, resolvedCall);
}
@NotNull
@@ -1170,23 +1171,27 @@ public abstract class StackValue {
private final Type backingFieldOwner;
private final PropertyDescriptor descriptor;
private final GenerationState state;
private final String fieldName;
@NotNull private final ExpressionCodegen codegen;
@Nullable private final ResolvedCall resolvedCall;
public Property(
@NotNull PropertyDescriptor descriptor, @Nullable Type backingFieldOwner,
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField,
@Nullable String fieldName, @NotNull Type type, @NotNull GenerationState state,
@NotNull StackValue receiver
@Nullable String fieldName, @NotNull Type type,
@NotNull StackValue receiver,
@NotNull ExpressionCodegen codegen,
@Nullable ResolvedCall resolvedCall
) {
super(type, isStatic(isStaticBackingField, getter), isStatic(isStaticBackingField, setter), receiver, true);
this.backingFieldOwner = backingFieldOwner;
this.getter = getter;
this.setter = setter;
this.descriptor = descriptor;
this.state = state;
this.fieldName = fieldName;
this.codegen = codegen;
this.resolvedCall = resolvedCall;
}
@Override
@@ -1202,8 +1207,16 @@ public abstract class StackValue {
coerceTo(type, v);
}
else {
getter.genInvokeInstruction(v);
coerce(getter.getReturnType(), type, v);
PropertyGetterDescriptor getter = descriptor.getGetter();
assert getter != null : "Getter descriptor should be not null for " + descriptor;
if (resolvedCall != null && getter.isInline()) {
CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, getter);
callGenerator.putHiddenParams();
callGenerator.genCall(this.getter, resolvedCall, false, codegen);
} else {
this.getter.genInvokeInstruction(v);
}
coerce(this.getter.getReturnType(), type, v);
KotlinType returnType = descriptor.getReturnType();
if (returnType != null && KotlinBuiltIns.isNothing(returnType)) {
@@ -1245,6 +1258,23 @@ public abstract class StackValue {
v.mark(ok);
}
@Override
public void store(@NotNull StackValue rightSide, @NotNull InstructionAdapter v, boolean skipReceiver) {
PropertySetterDescriptor setter = descriptor.getSetter();
if (resolvedCall != null && setter != null && setter.isInline()) {
assert this.setter != null : "Setter descriptor should be not null for " + descriptor;
CallGenerator callGenerator = codegen.getOrCreateCallGenerator(resolvedCall, setter);
if (!skipReceiver) {
putReceiver(v, false);
}
callGenerator.putHiddenParams();
callGenerator.putValueIfNeeded(rightSide.type, rightSide);
callGenerator.genCall(this.setter, resolvedCall, false, codegen);
} else {
super.store(rightSide, v, skipReceiver);
}
}
@Override
public void storeSelector(@NotNull Type topOfStackType, @NotNull InstructionAdapter v) {
if (setter == null) {
@@ -115,7 +115,7 @@ public class MethodContext extends CodegenContext<CallableMemberDescriptor> {
}
public boolean isInlineMethodContext() {
return InlineUtil.isInline(getContextDescriptor());
return InlineUtil.isInline(getFunctionDescriptor());
}
@NotNull
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor;
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
import org.jetbrains.kotlin.types.expressions.DoubleColonLHS;
import org.jetbrains.kotlin.types.expressions.LabelResolver;
import org.jetbrains.org.objectweb.asm.Label;
@@ -211,8 +211,8 @@ public class InlineCodegen extends CallGenerator {
: jvmSignature.getAsmMethod();
MethodId methodId = new MethodId(DescriptorUtils.getFqNameSafe(functionDescriptor.getContainingDeclaration()), asmMethod);
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !(functionDescriptor instanceof DeserializedSimpleFunctionDescriptor)) {
final CallableMemberDescriptor directMember = JvmCodegenUtil.getDirectMember(functionDescriptor);
if (!isBuiltInArrayIntrinsic(functionDescriptor) && !(directMember instanceof DeserializedCallableMemberDescriptor)) {
return doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, codegen, context, callDefault, state, asmMethod);
}
@@ -220,7 +220,7 @@ public class InlineCodegen extends CallGenerator {
state.getInlineCache().getMethodNodeById(), methodId, new Function0<SMAPAndMethodNode>() {
@Override
public SMAPAndMethodNode invoke() {
SMAPAndMethodNode result = doCreateMethodNodeFromCompiled(functionDescriptor, state, asmMethod);
SMAPAndMethodNode result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod);
if (result == null) {
throw new IllegalStateException("Couldn't obtain compiled function body for " + functionDescriptor);
}
@@ -245,13 +245,13 @@ public class InlineCodegen extends CallGenerator {
@Nullable
private static SMAPAndMethodNode doCreateMethodNodeFromCompiled(
@NotNull FunctionDescriptor functionDescriptor,
@NotNull CallableMemberDescriptor callableDescriptor,
@NotNull final GenerationState state,
@NotNull Method asmMethod
) {
KotlinTypeMapper typeMapper = state.getTypeMapper();
if (isBuiltInArrayIntrinsic(functionDescriptor)) {
if (isBuiltInArrayIntrinsic(callableDescriptor)) {
ClassId classId = IntrinsicArrayConstructorsKt.getClassId();
byte[] bytes = InlineCacheKt.getOrPut(state.getInlineCache().getClassBytes(), classId, new Function0<byte[]>() {
@Override
@@ -263,10 +263,10 @@ public class InlineCodegen extends CallGenerator {
return InlineCodegenUtil.getMethodNode(bytes, asmMethod.getName(), asmMethod.getDescriptor(), classId, state);
}
assert functionDescriptor instanceof DeserializedSimpleFunctionDescriptor : "Not a deserialized function: " + functionDescriptor;
assert callableDescriptor instanceof DeserializedCallableMemberDescriptor : "Not a deserialized function or proper: " + callableDescriptor;
KotlinTypeMapper.ContainingClassesInfo containingClasses =
typeMapper.getContainingClassesForDeserializedCallable((DeserializedSimpleFunctionDescriptor) functionDescriptor);
typeMapper.getContainingClassesForDeserializedCallable((DeserializedCallableMemberDescriptor) callableDescriptor);
final ClassId containerId = containingClasses.getImplClassId();
@@ -292,7 +292,7 @@ public class InlineCodegen extends CallGenerator {
@NotNull
private static SMAPAndMethodNode doCreateMethodNodeFromSource(
@NotNull FunctionDescriptor functionDescriptor,
@NotNull FunctionDescriptor callableDescriptor,
@NotNull JvmMethodSignature jvmSignature,
@NotNull ExpressionCodegen codegen,
@NotNull CodegenContext context,
@@ -300,16 +300,16 @@ public class InlineCodegen extends CallGenerator {
@NotNull GenerationState state,
@NotNull Method asmMethod
) {
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
if (!(element instanceof KtNamedFunction)) {
throw new IllegalStateException("Couldn't find declaration for function " + functionDescriptor);
if (!(element instanceof KtNamedFunction || element instanceof KtPropertyAccessor)) {
throw new IllegalStateException("Couldn't find declaration for function " + callableDescriptor);
}
KtNamedFunction inliningFunction = (KtNamedFunction) element;
KtDeclarationWithBody inliningFunction = (KtDeclarationWithBody) element;
MethodNode node = new MethodNode(
InlineCodegenUtil.API,
getMethodAsmFlags(functionDescriptor, context.getContextKind(), state) | (callDefault ? Opcodes.ACC_STATIC : 0),
getMethodAsmFlags(callableDescriptor, context.getContextKind(), state) | (callDefault ? Opcodes.ACC_STATIC : 0),
asmMethod.getName(),
asmMethod.getDescriptor(),
null, null
@@ -319,23 +319,26 @@ public class InlineCodegen extends CallGenerator {
MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
CodegenContext parentContext = context.getParentContext();
assert parentContext != null : "Context has no parent: " + context;
MethodContext methodContext = parentContext.intoFunction(functionDescriptor);
MethodContext methodContext = parentContext.intoFunction(callableDescriptor);
SMAP smap;
if (callDefault) {
Type implementationOwner = state.getTypeMapper().mapImplementationOwner(functionDescriptor);
Type implementationOwner = state.getTypeMapper().mapImplementationOwner(callableDescriptor);
FakeMemberCodegen parentCodegen = new FakeMemberCodegen(
codegen.getParentCodegen(), inliningFunction, (FieldOwnerContext) methodContext.getParentContext(),
implementationOwner.getInternalName()
);
if (!(element instanceof KtNamedFunction)) {
throw new IllegalStateException("Propertiy accessors with default parameters not supported " + callableDescriptor);
}
FunctionCodegen.generateDefaultImplBody(
methodContext, functionDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
inliningFunction, parentCodegen, asmMethod
methodContext, callableDescriptor, maxCalcAdapter, DefaultParameterValueLoader.DEFAULT,
(KtNamedFunction) inliningFunction, parentCodegen, asmMethod
);
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
}
else {
smap = generateMethodBody(maxCalcAdapter, functionDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen);
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen);
}
maxCalcAdapter.visitMaxs(-1, -1);
maxCalcAdapter.visitEnd();
@@ -343,11 +346,11 @@ public class InlineCodegen extends CallGenerator {
return new SMAPAndMethodNode(node, smap);
}
private static boolean isBuiltInArrayIntrinsic(@NotNull FunctionDescriptor functionDescriptor) {
if (functionDescriptor instanceof FictitiousArrayConstructor) return true;
String name = functionDescriptor.getName().asString();
private static boolean isBuiltInArrayIntrinsic(@NotNull CallableMemberDescriptor callableDescriptor) {
if (callableDescriptor instanceof FictitiousArrayConstructor) return true;
String name = callableDescriptor.getName().asString();
return (name.equals("arrayOf") || name.equals("emptyArray")) &&
functionDescriptor.getContainingDeclaration() instanceof BuiltInsPackageFragment;
callableDescriptor.getContainingDeclaration() instanceof BuiltInsPackageFragment;
}
@NotNull
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.serialization.ProtoBuf
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.JvmMethodSignature
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
fun inlineFunctionsJvmNames(header: KotlinClassHeader): Set<String> {
@@ -31,12 +33,14 @@ fun inlineFunctionsJvmNames(header: KotlinClassHeader): Set<String> {
return when (header.kind) {
KotlinClassHeader.Kind.CLASS -> {
val (nameResolver, classProto) = JvmProtoBufUtil.readClassDataFrom(BitEncoding.decodeBytes(annotationData), strings)
inlineFunctionsJvmNames(classProto.functionList, nameResolver, classProto.typeTable)
inlineFunctionsJvmNames(classProto.functionList, nameResolver, classProto.typeTable) +
inlineAccessorsJvmNames(classProto.propertyList, nameResolver)
}
KotlinClassHeader.Kind.FILE_FACADE,
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(BitEncoding.decodeBytes(annotationData), strings)
inlineFunctionsJvmNames(packageProto.functionList, nameResolver, packageProto.typeTable)
inlineFunctionsJvmNames(packageProto.functionList, nameResolver, packageProto.typeTable) +
inlineAccessorsJvmNames(packageProto.propertyList, nameResolver)
}
else -> emptySet()
}
@@ -50,3 +54,27 @@ private fun inlineFunctionsJvmNames(functions: List<ProtoBuf.Function>, nameReso
}
return jvmNames.toSet()
}
private fun inlineAccessorsJvmNames(properties: List<ProtoBuf.Property>, nameResolver: NameResolver): Set<String> {
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<JvmMethodSignature>()
propertiesWithInlineAccessors.forEach { proto ->
if (proto.hasExtension(JvmProtoBuf.propertySignature)) {
val signature = proto.getExtension(JvmProtoBuf.propertySignature)
if (proto.hasGetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.getterFlags)) {
inlineAccessors.add(signature.getter)
}
if (proto.hasSetterFlags() && Flags.IS_INLINE_ACCESSOR.get(proto.setterFlags)) {
inlineAccessors.add(signature.setter)
}
}
}
return inlineAccessors.mapNotNull {
nameResolver.getString(it.name) + nameResolver.getString(it.desc)
}.toSet()
}
+25
View File
@@ -0,0 +1,25 @@
// FILE: 1.kt
package test
var value: Int = 0
inline var z: Int
get() = ++value
set(p: Int) { value = p }
// FILE: 2.kt
import test.*
fun box(): String {
val v = z
if (value != 1) return "fail 1: $value"
z = v + 2
if (value != 3) return "fail 2: $value"
var p = z
if (value != 4) return "fail 3: $value"
return "OK"
}
@@ -0,0 +1,25 @@
// FILE: 1.kt
package test
var value: Int = 0
inline var Int.z: Int
get() = this + ++value
set(p: Int) { value = p + this}
// FILE: 2.kt
import test.*
fun box(): String {
val v = 11.z
if (v != 12) return "fail 1: $v"
11.z = v + 2
if (value != 25) return "fail 2: $value"
var p = 11.z
if (p != 37) return "fail 3: $p"
return "OK"
}
@@ -0,0 +1,24 @@
package test
var value: Int = 0
inline var z: Int
get() = ++value
set(p: Int) { value = p }
fun box(): String {
val v = z
if (value != 1) return "fail 1: $value"
z = v + 2
if (value != 3) return "fail 2: $value"
var p = z
if (value != 4) return "fail 3: $value"
return "OK1"
}
// 0 SimpleKt.getZ
// 0 SimpleKt.setZ
@@ -1514,6 +1514,27 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
}
}
@TestMetadata("compiler/testData/codegen/boxInline/property")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Property extends AbstractBlackBoxInlineCodegenTest {
public void testAllFilesPresentInProperty() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/property"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleExtension.kt")
public void testSimpleExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simpleExtension.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/reified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1008,6 +1008,21 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/whenMappingOnCallSite.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/codegen/bytecodeText/inline/property")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Property extends AbstractBytecodeTextTest {
public void testAllFilesPresentInProperty() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/inline/property"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/property/simple.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/interfaces")
@@ -1514,6 +1514,27 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
}
}
@TestMetadata("compiler/testData/codegen/boxInline/property")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Property extends AbstractCompileKotlinAgainstInlineKotlinTest {
public void testAllFilesPresentInProperty() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/property"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simple.kt");
doTest(fileName);
}
@TestMetadata("simpleExtension.kt")
public void testSimpleExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simpleExtension.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxInline/reified")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)