Light class codegen: all objects are considered static

Simplify code handling access flag computation
Fix a problem where kotlin nested object wasn't producing a nested light class
This commit is contained in:
Pavel V. Talanov
2017-03-03 16:27:35 +03:00
parent d94da5af40
commit d34b73befb
20 changed files with 114 additions and 52 deletions
@@ -128,43 +128,35 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
boolean isAbstract = false; boolean isAbstract = false;
boolean isInterface = false; boolean isInterface = false;
boolean isFinal = false; boolean isFinal = false;
boolean isStatic;
boolean isAnnotation = false; boolean isAnnotation = false;
boolean isEnum = false; boolean isEnum = false;
ClassKind kind = descriptor.getKind(); ClassKind kind = descriptor.getKind();
if (kind == ClassKind.OBJECT) { Modality modality = descriptor.getModality();
isStatic = isCompanionObject(descriptor);
isFinal = true; if (modality == Modality.ABSTRACT || modality == Modality.SEALED) {
isAbstract = true;
} }
else {
Modality modality = descriptor.getModality();
if (modality == Modality.ABSTRACT || modality == Modality.SEALED) { if (kind == ClassKind.INTERFACE) {
isAbstract = true; isAbstract = true;
} isInterface = true;
}
else if (kind == ClassKind.ANNOTATION_CLASS) {
isAbstract = true;
isInterface = true;
isAnnotation = true;
}
else if (kind == ClassKind.ENUM_CLASS) {
isAbstract = hasAbstractMembers(descriptor);
isEnum = true;
}
if (kind == ClassKind.INTERFACE) { if (modality != Modality.OPEN && !isAbstract) {
isAbstract = true; isFinal = kind == ClassKind.OBJECT ||
isInterface = true; // Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
} !(kind == ClassKind.ENUM_CLASS && !state.getClassBuilderMode().generateBodies);
else if (kind == ClassKind.ANNOTATION_CLASS) {
isAbstract = true;
isInterface = true;
isAnnotation = true;
}
else if (kind == ClassKind.ENUM_CLASS) {
isAbstract = hasAbstractMembers(descriptor);
isEnum = true;
}
if (modality != Modality.OPEN && !isAbstract) {
// Light-class mode: Do not make enum classes final since PsiClass corresponding to enum is expected to be inheritable from
isFinal = !(kind == ClassKind.ENUM_CLASS && !state.getClassBuilderMode().generateBodies);
}
isStatic = !descriptor.isInner();
} }
int access = 0; int access = 0;
@@ -176,7 +168,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
// Thus we must write full accessibility flags on inner classes in this mode // Thus we must write full accessibility flags on inner classes in this mode
access |= getVisibilityAccessFlag(descriptor); access |= getVisibilityAccessFlag(descriptor);
// Same for STATIC // Same for STATIC
if (isStatic) { if (!descriptor.isInner()) {
access |= ACC_STATIC; access |= ACC_STATIC;
} }
} }
@@ -0,0 +1,37 @@
public final class A {
public A() { /* compiled code */ }
public static final class B {
public B() { /* compiled code */ }
public static final class I {
public static final A.B.I INSTANCE;
private I() { /* compiled code */ }
}
public static final class II {
public static final A.B.II INSTANCE;
private II() { /* compiled code */ }
}
}
public static final class C {
public static final A.C INSTANCE;
private C() { /* compiled code */ }
public static final class D {
public static final A.C.D INSTANCE;
private D() { /* compiled code */ }
public static final class G {
public static final A.C.D.G INSTANCE;
private G() { /* compiled code */ }
}
}
}
}
+15
View File
@@ -0,0 +1,15 @@
// A
class A {
class B {
object I
object II
}
object C {
object D {
object G
}
}
}
@@ -11,7 +11,7 @@ public enum class E {
} }
@kotlin.Metadata @kotlin.Metadata
public final class E/O { public final static class E/O {
public final static field INSTANCE: E.O public final static field INSTANCE: E.O
inner class E/O inner class E/O
private method <init>(): void private method <init>(): void
@@ -27,7 +27,7 @@ final static class E/SUBCLASS {
} }
@kotlin.Metadata @kotlin.Metadata
public final class E/SUBCLASS/O { public final static class E/SUBCLASS/O {
public final static field INSTANCE: E.SUBCLASS.O public final static field INSTANCE: E.SUBCLASS.O
inner class E/SUBCLASS inner class E/SUBCLASS
inner class E/SUBCLASS/O inner class E/SUBCLASS/O
@@ -6,7 +6,7 @@ public final class A {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/B { public final static class A/B {
public final static field INSTANCE: A.B public final static field INSTANCE: A.B
inner class A/B inner class A/B
inner class A/B/C inner class A/B/C
@@ -14,7 +14,7 @@ public final class A/B {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/B/C { public final static class A/B/C {
public final static field INSTANCE: A.B.C public final static field INSTANCE: A.B.C
private final static @org.jetbrains.annotations.NotNull field ok: java.lang.String private final static @org.jetbrains.annotations.NotNull field ok: java.lang.String
inner class A/B inner class A/B
@@ -7,7 +7,7 @@ public final class A {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/Z { public final static class A/Z {
public final static field INSTANCE: A.Z public final static field INSTANCE: A.Z
private final static @org.jetbrains.annotations.NotNull field p: java.lang.String private final static @org.jetbrains.annotations.NotNull field p: java.lang.String
inner class A/Z inner class A/Z
@@ -5,7 +5,7 @@ public final class C {
} }
@kotlin.Metadata @kotlin.Metadata
public final class C/Obj { public final static class C/Obj {
public final static field INSTANCE: C.Obj public final static field INSTANCE: C.Obj
private final static @org.jetbrains.annotations.NotNull field o: java.lang.String private final static @org.jetbrains.annotations.NotNull field o: java.lang.String
inner class C/Obj inner class C/Obj
@@ -25,7 +25,7 @@ public final static class C/Obj/D {
} }
@kotlin.Metadata @kotlin.Metadata
public final class C/Obj/InnerObj { public final static class C/Obj/InnerObj {
public final static field INSTANCE: C.Obj.InnerObj public final static field INSTANCE: C.Obj.InnerObj
inner class C/Obj inner class C/Obj
inner class C/Obj/InnerObj inner class C/Obj/InnerObj
@@ -6,7 +6,7 @@ public final class A {
} }
@kotlin.Metadata @kotlin.Metadata
private final class A/Foo { private final static class A/Foo {
public final static field INSTANCE: A.Foo public final static field INSTANCE: A.Foo
private final static @org.jetbrains.annotations.NotNull field foov: java.lang.String private final static @org.jetbrains.annotations.NotNull field foov: java.lang.String
inner class A/Foo inner class A/Foo
@@ -17,7 +17,7 @@ private final class A/Foo {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/Foo/Bar { public final static class A/Foo/Bar {
public final static field INSTANCE: A.Foo.Bar public final static field INSTANCE: A.Foo.Bar
private final static @org.jetbrains.annotations.NotNull field barv: java.lang.String private final static @org.jetbrains.annotations.NotNull field barv: java.lang.String
inner class A/Foo inner class A/Foo
@@ -19,7 +19,7 @@ public final class Outer {
} }
@kotlin.Metadata @kotlin.Metadata
public final class Outer/O { public final static class Outer/O {
public final static field INSTANCE: Outer.O public final static field INSTANCE: Outer.O
inner class Outer/O inner class Outer/O
private method <init>(): void private method <init>(): void
@@ -10,7 +10,7 @@ public final class Foo {
} }
@kotlin.Metadata @kotlin.Metadata
private final class Foo/O { private final static class Foo/O {
public final static field INSTANCE: Foo.O public final static field INSTANCE: Foo.O
inner class Foo/O inner class Foo/O
private method <init>(): void private method <init>(): void
@@ -8,7 +8,7 @@ public class Outer {
} }
@kotlin.Metadata @kotlin.Metadata
public final class Outer/First { public final static class Outer/First {
public final static field INSTANCE: Outer.First public final static field INSTANCE: Outer.First
inner class Outer/First inner class Outer/First
private method <init>(): void private method <init>(): void
@@ -9,21 +9,21 @@ public class Outer {
} }
@kotlin.Metadata @kotlin.Metadata
public final class Outer/Another { public final static class Outer/Another {
public final static field INSTANCE: Outer.Another public final static field INSTANCE: Outer.Another
inner class Outer/Another inner class Outer/Another
private method <init>(): void private method <init>(): void
} }
@kotlin.Metadata @kotlin.Metadata
public final class Outer/Inner { public final static class Outer/Inner {
public final static field INSTANCE: Outer.Inner public final static field INSTANCE: Outer.Inner
inner class Outer/Inner inner class Outer/Inner
private method <init>(): void private method <init>(): void
} }
@kotlin.Metadata @kotlin.Metadata
public final class Outer/Other { public final static class Outer/Other {
public final static field INSTANCE: Outer.Other public final static field INSTANCE: Outer.Other
inner class Outer/Other inner class Outer/Other
private method <init>(): void private method <init>(): void
@@ -41,7 +41,7 @@ public final class S/InnerClass {
} }
@kotlin.Metadata @kotlin.Metadata
public final class S/NonCompanionObject { public final static class S/NonCompanionObject {
public final static field INSTANCE: S.NonCompanionObject public final static field INSTANCE: S.NonCompanionObject
inner class S/NonCompanionObject inner class S/NonCompanionObject
private method <init>(): void private method <init>(): void
@@ -12,14 +12,14 @@ public abstract class Season {
} }
@kotlin.Metadata @kotlin.Metadata
public final class Season/Cold { public final static class Season/Cold {
public final static field INSTANCE: Season.Cold public final static field INSTANCE: Season.Cold
inner class Season/Cold inner class Season/Cold
private method <init>(): void private method <init>(): void
} }
@kotlin.Metadata @kotlin.Metadata
public final class Season/Warm { public final static class Season/Warm {
public final static field INSTANCE: Season.Warm public final static field INSTANCE: Season.Warm
inner class Season/Warm inner class Season/Warm
private method <init>(): void private method <init>(): void
@@ -9,7 +9,7 @@ public final class A {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/B { public final static class A/B {
public final static field INSTANCE: A.B public final static field INSTANCE: A.B
private final static field prop: int private final static field prop: int
inner class A/B inner class A/B
@@ -19,7 +19,7 @@ public final class A/B {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/C { public final static class A/C {
public final static field INSTANCE: A.C public final static field INSTANCE: A.C
inner class A/C inner class A/C
private method <init>(): void private method <init>(): void
@@ -7,7 +7,7 @@ public final class A {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/B { public final static class A/B {
public final static field INSTANCE: A.B public final static field INSTANCE: A.B
private final static @org.jetbrains.annotations.NotNull field z: java.lang.String private final static @org.jetbrains.annotations.NotNull field z: java.lang.String
inner class A/B inner class A/B
@@ -6,7 +6,7 @@ public abstract class A {
} }
@kotlin.Metadata @kotlin.Metadata
public final class A/B { public final static class A/B {
public final static field INSTANCE: A.B public final static field INSTANCE: A.B
inner class A/B inner class A/B
private method <init>(): void private method <init>(): void
@@ -72,6 +72,12 @@ public class CompilerLightClassTestGenerated extends AbstractCompilerLightClassT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("NestedObjects.kt")
public void testNestedObjects() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/NestedObjects.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors") @TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -72,6 +72,12 @@ public class IdeCompiledLightClassTestGenerated extends AbstractIdeCompiledLight
doTest(fileName); doTest(fileName);
} }
@TestMetadata("NestedObjects.kt")
public void testNestedObjects() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/NestedObjects.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/asJava/lightClasses/delegation") @TestMetadata("compiler/testData/asJava/lightClasses/delegation")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -72,6 +72,12 @@ public class IdeLightClassTestGenerated extends AbstractIdeLightClassTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("NestedObjects.kt")
public void testNestedObjects() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/asJava/lightClasses/NestedObjects.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors") @TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)