diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 4e89fd8a237..6a247f9e0f5 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -232,7 +232,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; - DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings())); + DescriptorSerializer serializer = + DescriptorSerializer.create(descriptor, new JavaSerializerExtension(v.getSerializationBindings())); ProtoBuf.Class classProto = serializer.classProto(descriptor).build(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java index 2bf00a45bb9..8901aab9ac3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PackageCodegen.java @@ -272,7 +272,7 @@ public class PackageCodegen { if (file.isScript()) return; } - DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(bindings)); + DescriptorSerializer serializer = DescriptorSerializer.createTopLevel(new JavaSerializerExtension(bindings)); Collection packageFragments = Lists.newArrayList(); ContainerUtil.addIfNotNull(packageFragments, packageFragment); ContainerUtil.addIfNotNull(packageFragments, compiledPackageFragment); diff --git a/compiler/builtins-serializer/src/BuiltInsSerializer.kt b/compiler/builtins-serializer/src/BuiltInsSerializer.kt index 58101d4913d..fc9ff4e457c 100644 --- a/compiler/builtins-serializer/src/BuiltInsSerializer.kt +++ b/compiler/builtins-serializer/src/BuiltInsSerializer.kt @@ -110,7 +110,7 @@ public class BuiltInsSerializer(val out: PrintStream?) { // TODO: perform some kind of validation? At the moment not possible because DescriptorValidator is in compiler-tests // DescriptorValidator.validate(packageView) - val serializer = DescriptorSerializer(SerializerExtension.DEFAULT) + val serializer = DescriptorSerializer.createTopLevel(SerializerExtension.DEFAULT) val classNames = ArrayList() val classifierDescriptors = DescriptorSerializer.sort(packageView.getMemberScope().getDescriptors(DescriptorKindFilter.CLASSIFIERS)) diff --git a/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt b/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt new file mode 100644 index 00000000000..0b500e848bb --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt @@ -0,0 +1,13 @@ +package test + +class A { + inner class B { + inner class C { + inner class D { + fun foo(p1: P1, p2: P2, p3: P3, p4: P4): Nothing = null!! + + fun bar(ta: TA, tb: TB, tc: TC, td: TD): A.B.C.D = foo(ta, tb, tc, td) + } + } + } +} diff --git a/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.txt b/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.txt new file mode 100644 index 00000000000..8bbc3efedc3 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.txt @@ -0,0 +1,19 @@ +package test + +internal final class A { + /*primary*/ public constructor A() + + internal final inner class B { + /*primary*/ public constructor B() + + internal final inner class C { + /*primary*/ public constructor C() + + internal final inner class D { + /*primary*/ public constructor D() + internal final fun bar(/*0*/ ta: TA, /*1*/ tb: TB, /*2*/ tc: TC, /*3*/ td: TD): test.A.B.C.D + internal final fun foo(/*0*/ p1: P1, /*1*/ p2: P2, /*2*/ p3: P3, /*3*/ p4: P4): kotlin.Nothing + } + } + } +} diff --git a/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt b/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt new file mode 100644 index 00000000000..16302eae5b2 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt @@ -0,0 +1,5 @@ +package test + +class InnerClassReferencesOuterTP

{ + inner class Inner +} diff --git a/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.txt b/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.txt new file mode 100644 index 00000000000..f34e98a745e --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.txt @@ -0,0 +1,9 @@ +package test + +internal final class InnerClassReferencesOuterTP { + /*primary*/ public constructor InnerClassReferencesOuterTP() + + internal final inner class Inner { + /*primary*/ public constructor Inner() + } +} diff --git a/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt b/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt new file mode 100644 index 00000000000..21e77b5c055 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt @@ -0,0 +1,11 @@ +package test + +class MembersReferenceOuterTP

{ + inner class Inner { + fun f() {} + fun g(p: P): P = null!! + + val v: P = null!! + val w: Q = null!! + } +} diff --git a/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.txt b/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.txt new file mode 100644 index 00000000000..1d2cfea1d61 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.txt @@ -0,0 +1,15 @@ +package test + +internal final class MembersReferenceOuterTP { + /*primary*/ public constructor MembersReferenceOuterTP() + + internal final inner class Inner { + /*primary*/ public constructor Inner() + internal final val v: P + internal final fun (): P + internal final val w: Q + internal final fun (): Q + internal final fun f(): kotlin.Unit + internal final fun g(/*0*/ p: P): P + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 66a86ad5ed3..f6c8ee545cc 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -1801,7 +1801,7 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { @TestMetadata("compiler/testData/loadJava/compiledKotlin") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({CompiledKotlin.Annotations.class, CompiledKotlin.Class.class, CompiledKotlin.ClassFun.class, CompiledKotlin.ClassObject.class, CompiledKotlin.Constructor.class, CompiledKotlin.DataClass.class, CompiledKotlin.Enum.class, CompiledKotlin.FromLoadJava.class, CompiledKotlin.Fun.class, CompiledKotlin.Inline.class, CompiledKotlin.MemberOrder.class, CompiledKotlin.PlatformTypes.class, CompiledKotlin.Prop.class, CompiledKotlin.Type.class, CompiledKotlin.Visibility.class}) + @InnerTestClasses({CompiledKotlin.Annotations.class, CompiledKotlin.Class.class, CompiledKotlin.ClassFun.class, CompiledKotlin.ClassObject.class, CompiledKotlin.Constructor.class, CompiledKotlin.DataClass.class, CompiledKotlin.Enum.class, CompiledKotlin.FromLoadJava.class, CompiledKotlin.Fun.class, CompiledKotlin.Inline.class, CompiledKotlin.MemberOrder.class, CompiledKotlin.Nested.class, CompiledKotlin.PlatformTypes.class, CompiledKotlin.Prop.class, CompiledKotlin.Type.class, CompiledKotlin.Visibility.class}) @RunWith(JUnit3RunnerWithInners.class) public static class CompiledKotlin extends AbstractLoadJavaTest { public void testAllFilesPresentInCompiledKotlin() throws Exception { @@ -4176,6 +4176,33 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { } } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/nested") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Nested extends AbstractLoadJavaTest { + public void testAllFilesPresentInNested() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/nested"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("deepInnerGeneric.kt") + public void testDeepInnerGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt"); + doTestCompiledKotlin(fileName); + } + + @TestMetadata("innerClassReferencesOuterTP.kt") + public void testInnerClassReferencesOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt"); + doTestCompiledKotlin(fileName); + } + + @TestMetadata("membersReferenceOuterTP.kt") + public void testMembersReferenceOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt"); + doTestCompiledKotlin(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/platformTypes") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java index 16e552d84f2..ea6fb239fa1 100644 --- a/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/lang/resolve/lazy/LazyResolveRecursiveComparingTestGenerated.java @@ -33,7 +33,7 @@ import java.util.regex.Pattern; public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyResolveRecursiveComparingTest { @TestMetadata("compiler/testData/loadJava/compiledKotlin") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({CompiledKotlin.Annotations.class, CompiledKotlin.Class.class, CompiledKotlin.ClassFun.class, CompiledKotlin.ClassObject.class, CompiledKotlin.Constructor.class, CompiledKotlin.DataClass.class, CompiledKotlin.Enum.class, CompiledKotlin.FromLoadJava.class, CompiledKotlin.Fun.class, CompiledKotlin.Inline.class, CompiledKotlin.MemberOrder.class, CompiledKotlin.PlatformTypes.class, CompiledKotlin.Prop.class, CompiledKotlin.Type.class, CompiledKotlin.Visibility.class}) + @InnerTestClasses({CompiledKotlin.Annotations.class, CompiledKotlin.Class.class, CompiledKotlin.ClassFun.class, CompiledKotlin.ClassObject.class, CompiledKotlin.Constructor.class, CompiledKotlin.DataClass.class, CompiledKotlin.Enum.class, CompiledKotlin.FromLoadJava.class, CompiledKotlin.Fun.class, CompiledKotlin.Inline.class, CompiledKotlin.MemberOrder.class, CompiledKotlin.Nested.class, CompiledKotlin.PlatformTypes.class, CompiledKotlin.Prop.class, CompiledKotlin.Type.class, CompiledKotlin.Visibility.class}) @RunWith(JUnit3RunnerWithInners.class) public static class CompiledKotlin extends AbstractLazyResolveRecursiveComparingTest { public void testAllFilesPresentInCompiledKotlin() throws Exception { @@ -2408,6 +2408,33 @@ public class LazyResolveRecursiveComparingTestGenerated extends AbstractLazyReso } } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/nested") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Nested extends AbstractLazyResolveRecursiveComparingTest { + public void testAllFilesPresentInNested() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/nested"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("deepInnerGeneric.kt") + public void testDeepInnerGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt"); + doTest(fileName); + } + + @TestMetadata("innerClassReferencesOuterTP.kt") + public void testInnerClassReferencesOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt"); + doTest(fileName); + } + + @TestMetadata("membersReferenceOuterTP.kt") + public void testMembersReferenceOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/platformTypes") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java index f55ba817c84..cde64312347 100644 --- a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java +++ b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/DescriptorSerializer.java @@ -37,16 +37,35 @@ public class DescriptorSerializer { private final Interner typeParameters; private final SerializerExtension extension; - public DescriptorSerializer(@NotNull SerializerExtension extension) { - this(new NameTable(), new Interner(), extension); - } - private DescriptorSerializer(NameTable nameTable, Interner typeParameters, SerializerExtension extension) { this.nameTable = nameTable; this.typeParameters = typeParameters; this.extension = extension; } + @NotNull + public static DescriptorSerializer createTopLevel(@NotNull SerializerExtension extension) { + return new DescriptorSerializer(new NameTable(), new Interner(), extension); + } + + @NotNull + public static DescriptorSerializer create(@NotNull ClassDescriptor descriptor, @NotNull SerializerExtension extension) { + DeclarationDescriptor container = descriptor.getContainingDeclaration(); + DescriptorSerializer parentSerializer = + container instanceof ClassDescriptor + ? create((ClassDescriptor) container, extension) + : createTopLevel(extension); + + // Calculate type parameter ids for the outer class beforehand, as it would've had happened if we were always + // serializing outer classes before nested classes. + // Otherwise our interner can get wrong ids because we may serialize classes in any order. + DescriptorSerializer serializer = parentSerializer.createChildSerializer(); + for (TypeParameterDescriptor typeParameter : descriptor.getTypeConstructor().getParameters()) { + serializer.typeParameters.intern(typeParameter); + } + return serializer; + } + private DescriptorSerializer createChildSerializer() { return new DescriptorSerializer(nameTable, new Interner(typeParameters), extension); } @@ -68,16 +87,14 @@ public class DescriptorSerializer { builder.setFqName(getClassId(classDescriptor)); - DescriptorSerializer local = createChildSerializer(); - for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) { - builder.addTypeParameter(local.typeParameter(typeParameterDescriptor)); + builder.addTypeParameter(typeParameter(typeParameterDescriptor)); } if (!KotlinBuiltIns.getInstance().isSpecialClassWithNoSupertypes(classDescriptor)) { // Special classes (Any, Nothing) have no supertypes for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - builder.addSupertype(local.type(supertype)); + builder.addSupertype(type(supertype)); } } @@ -88,7 +105,7 @@ public class DescriptorSerializer { } else { ProtoBuf.Class.PrimaryConstructor.Builder constructorBuilder = ProtoBuf.Class.PrimaryConstructor.newBuilder(); - constructorBuilder.setData(local.callableProto(primaryConstructor)); + constructorBuilder.setData(callableProto(primaryConstructor)); builder.setPrimaryConstructor(constructorBuilder); } } @@ -99,7 +116,7 @@ public class DescriptorSerializer { if (descriptor instanceof CallableMemberDescriptor) { CallableMemberDescriptor member = (CallableMemberDescriptor) descriptor; if (member.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) continue; - builder.addMember(local.callableProto(member)); + builder.addMember(callableProto(member)); } } diff --git a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/Interner.java b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/Interner.java index b50a560aeb2..2cf1d493786 100644 --- a/core/serialization/src/org/jetbrains/jet/descriptors/serialization/Interner.java +++ b/core/serialization/src/org/jetbrains/jet/descriptors/serialization/Interner.java @@ -32,7 +32,7 @@ public final class Interner { public Interner(Interner parent, @NotNull TObjectHashingStrategy hashing) { this.parent = parent; - this.firstIndex = parent == null ? 0 : parent.all.size(); + this.firstIndex = parent != null ? parent.all.size() + parent.firstIndex : 0; this.interned = new TObjectIntHashMap(hashing); } @@ -40,30 +40,39 @@ public final class Interner { this(null, hashing); } + @SuppressWarnings("unchecked") public Interner(@Nullable Interner parent) { - //noinspection unchecked this(parent, TObjectHashingStrategy.CANONICAL); } public Interner() { - //noinspection unchecked - this((Interner) null); + this((Interner) null); } - public int intern(@NotNull T obj) { - assert parent == null || parent.all.size() == firstIndex : "Parent changed in parallel with child: indexes will be wrong"; - if (parent != null && parent.interned.contains(obj)) { - return parent.intern(obj); + private int find(@NotNull T obj) { + assert parent == null || parent.all.size() + parent.firstIndex == firstIndex : + "Parent changed in parallel with child: indexes will be wrong"; + if (parent != null) { + int index = parent.find(obj); + if (index >= 0) return index; } if (interned.contains(obj)) { return interned.get(obj); } - int index = firstIndex + interned.size(); + return -1; + } + + public int intern(@NotNull T obj) { + int index = find(obj); + if (index >= 0) return index; + + index = firstIndex + interned.size(); interned.put(obj, index); all.add(obj); return index; } + @NotNull public List getAllInternedObjects() { return all; } diff --git a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java index 924feac8159..d7ade1f4286 100644 --- a/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/stubs/LazyResolveByStubTestGenerated.java @@ -30,7 +30,7 @@ import java.util.regex.Pattern; @SuppressWarnings("all") @TestMetadata("compiler/testData/loadJava/compiledKotlin") @TestDataPath("$PROJECT_ROOT") -@InnerTestClasses({LazyResolveByStubTestGenerated.Annotations.class, LazyResolveByStubTestGenerated.Class.class, LazyResolveByStubTestGenerated.ClassFun.class, LazyResolveByStubTestGenerated.ClassObject.class, LazyResolveByStubTestGenerated.Constructor.class, LazyResolveByStubTestGenerated.DataClass.class, LazyResolveByStubTestGenerated.Enum.class, LazyResolveByStubTestGenerated.FromLoadJava.class, LazyResolveByStubTestGenerated.Fun.class, LazyResolveByStubTestGenerated.Inline.class, LazyResolveByStubTestGenerated.MemberOrder.class, LazyResolveByStubTestGenerated.PlatformTypes.class, LazyResolveByStubTestGenerated.Prop.class, LazyResolveByStubTestGenerated.Type.class, LazyResolveByStubTestGenerated.Visibility.class}) +@InnerTestClasses({LazyResolveByStubTestGenerated.Annotations.class, LazyResolveByStubTestGenerated.Class.class, LazyResolveByStubTestGenerated.ClassFun.class, LazyResolveByStubTestGenerated.ClassObject.class, LazyResolveByStubTestGenerated.Constructor.class, LazyResolveByStubTestGenerated.DataClass.class, LazyResolveByStubTestGenerated.Enum.class, LazyResolveByStubTestGenerated.FromLoadJava.class, LazyResolveByStubTestGenerated.Fun.class, LazyResolveByStubTestGenerated.Inline.class, LazyResolveByStubTestGenerated.MemberOrder.class, LazyResolveByStubTestGenerated.Nested.class, LazyResolveByStubTestGenerated.PlatformTypes.class, LazyResolveByStubTestGenerated.Prop.class, LazyResolveByStubTestGenerated.Type.class, LazyResolveByStubTestGenerated.Visibility.class}) @RunWith(JUnit3RunnerWithInners.class) public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTest { public void testAllFilesPresentInCompiledKotlin() throws Exception { @@ -2405,6 +2405,33 @@ public class LazyResolveByStubTestGenerated extends AbstractLazyResolveByStubTes } } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/nested") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Nested extends AbstractLazyResolveByStubTest { + public void testAllFilesPresentInNested() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/loadJava/compiledKotlin/nested"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("deepInnerGeneric.kt") + public void testDeepInnerGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/deepInnerGeneric.kt"); + doTest(fileName); + } + + @TestMetadata("innerClassReferencesOuterTP.kt") + public void testInnerClassReferencesOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/innerClassReferencesOuterTP.kt"); + doTest(fileName); + } + + @TestMetadata("membersReferenceOuterTP.kt") + public void testMembersReferenceOuterTP() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/nested/membersReferenceOuterTP.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/loadJava/compiledKotlin/platformTypes") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)