Move top level properties from package class to package$src

This commit is contained in:
Natalia.Ukhorskaya
2013-02-28 18:25:46 +04:00
parent 4bfdeffd0b
commit d501e8821c
7 changed files with 80 additions and 65 deletions
@@ -314,7 +314,7 @@ public class FunctionCodegen extends GenerationStateAware {
} }
} }
private void generateStaticDelegateMethodBody( public static void generateStaticDelegateMethodBody(
@NotNull MethodVisitor mv, @NotNull MethodVisitor mv,
@NotNull Method asmMethod, @NotNull Method asmMethod,
@NotNull OwnerKind.StaticDelegateKind dk @NotNull OwnerKind.StaticDelegateKind dk
@@ -109,10 +109,6 @@ public class NamespaceCodegen extends MemberCodegen {
} }
assert v.isActivated() == shouldGenerateNSClass(files) : "Different algorithms for generating namespace class and for heuristics"; assert v.isActivated() == shouldGenerateNSClass(files) : "Different algorithms for generating namespace class and for heuristics";
if (hasNonConstantPropertyInitializers()) {
generateStaticInitializers();
}
} }
private void generate(JetFile file) { private void generate(JetFile file) {
@@ -120,11 +116,7 @@ public class NamespaceCodegen extends MemberCodegen {
assert descriptor != null : "No namespace found for file " + file + " declared package: " + file.getPackageName(); assert descriptor != null : "No namespace found for file " + file + " declared package: " + file.getPackageName();
int countOfDeclarationsInSrcClass = 0; int countOfDeclarationsInSrcClass = 0;
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty) { if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
else if (declaration instanceof JetNamedFunction) {
countOfDeclarationsInSrcClass++; countOfDeclarationsInSrcClass++;
} }
else if (declaration instanceof JetClassOrObject) { else if (declaration instanceof JetClassOrObject) {
@@ -154,7 +146,7 @@ public class NamespaceCodegen extends MemberCodegen {
builder.visitSource(file.getName(), null); builder.visitSource(file.getName(), null);
for (JetDeclaration declaration : file.getDeclarations()) { for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetNamedFunction) { if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
{ {
final CodegenContext context = final CodegenContext context =
CodegenContext.STATIC.intoNamespace(descriptor); CodegenContext.STATIC.intoNamespace(descriptor);
@@ -168,6 +160,10 @@ public class NamespaceCodegen extends MemberCodegen {
} }
} }
if (hasNonConstantPropertyInitializers()) {
generateStaticInitializers(builder, file);
}
builder.done(); builder.done();
} }
} }
@@ -210,41 +206,32 @@ public class NamespaceCodegen extends MemberCodegen {
} }
} }
private void generateStaticInitializers() { private void generateStaticInitializers(@NotNull ClassBuilder builder, @NotNull JetFile file) {
final JetFile namespace = files.iterator().next(); // @todo: hack MethodVisitor mv = builder.newMethod(file, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
v.addOptionalDeclaration(new ClassBuilderOnDemand.ClassBuilderCallback() { FrameMap frameMap = new FrameMap();
@Override ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
public void doSomething(@NotNull ClassBuilder v) {
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap(); for (JetDeclaration declaration : file.getDeclarations()) {
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state); if (declaration instanceof JetProperty) {
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
for (JetFile file : files) { if (initializer != null && !(initializer instanceof JetConstantExpression)) {
for (JetDeclaration declaration : file.getDeclarations()) { final PropertyDescriptor descriptor =
if (declaration instanceof JetProperty) { (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
final JetExpression initializer = ((JetProperty) declaration).getInitializer(); assert descriptor != null;
if (initializer != null && !(initializer instanceof JetConstantExpression)) { codegen.genToJVMStack(initializer);
final PropertyDescriptor descriptor = StackValue.Property propValue = codegen.intermediateValueForProperty(descriptor, true, null);
(PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration); propValue.store(propValue.type, new InstructionAdapter(mv));
assert descriptor != null;
codegen.genToJVMStack(initializer);
StackValue.Property propValue = codegen.intermediateValueForProperty(descriptor, true, null);
propValue.store(propValue.type, new InstructionAdapter(mv));
}
}
}
} }
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
mv.visitEnd();
} }
} }
});
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for namespace", file);
mv.visitEnd();
}
} }
private boolean hasNonConstantPropertyInitializers() { private boolean hasNonConstantPropertyInitializers() {
@@ -66,10 +66,10 @@ public class PropertyCodegen extends GenerationStateAware {
throw new UnsupportedOperationException("expect a property to have a property descriptor"); throw new UnsupportedOperationException("expect a property to have a property descriptor");
} }
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
assert kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL assert kind instanceof OwnerKind.StaticDelegateKind || kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL
: "Generating property with a wrong kind (" + kind + "): " + descriptor; : "Generating property with a wrong kind (" + kind + "): " + descriptor;
if (kind != OwnerKind.TRAIT_IMPL) { if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) {
generateBackingField(p, propertyDescriptor); generateBackingField(p, propertyDescriptor);
} }
generateGetter(p, propertyDescriptor); generateGetter(p, propertyDescriptor);
@@ -166,7 +166,7 @@ public class PropertyCodegen extends GenerationStateAware {
return; return;
} }
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) {
flags |= ACC_STATIC; flags |= ACC_STATIC;
} }
@@ -200,6 +200,9 @@ public class PropertyCodegen extends GenerationStateAware {
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubThrow(mv); genStubThrow(mv);
} }
else if (kind instanceof OwnerKind.StaticDelegateKind) {
FunctionCodegen.generateStaticDelegateMethodBody(mv, jvmMethodSignature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind);
}
else { else {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
if (kind != OwnerKind.NAMESPACE) { if (kind != OwnerKind.NAMESPACE) {
@@ -246,7 +249,7 @@ public class PropertyCodegen extends GenerationStateAware {
return; return;
} }
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) {
flags |= ACC_STATIC; flags |= ACC_STATIC;
} }
@@ -276,6 +279,9 @@ public class PropertyCodegen extends GenerationStateAware {
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) { if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
genStubThrow(mv); genStubThrow(mv);
} }
else if (kind instanceof OwnerKind.StaticDelegateKind) {
FunctionCodegen.generateStaticDelegateMethodBody(mv, jvmMethodSignature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind);
}
else { else {
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
final Type type = typeMapper.mapType(propertyDescriptor); final Type type = typeMapper.mapType(propertyDescriptor);
@@ -29,6 +29,7 @@ import org.jetbrains.jet.codegen.signature.*;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall; import org.jetbrains.jet.lang.psi.JetDelegatorToSuperCall;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -66,7 +67,7 @@ public class JetTypeMapper extends BindingTraceAware {
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
if (containingDeclaration instanceof NamespaceDescriptor) { if (containingDeclaration instanceof NamespaceDescriptor) {
return jvmClassNameForNamespace((NamespaceDescriptor) containingDeclaration); return jvmClassNameForNamespace((NamespaceDescriptor) containingDeclaration, descriptor);
} }
else if (containingDeclaration instanceof ClassDescriptor) { else if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
@@ -121,7 +122,7 @@ public class JetTypeMapper extends BindingTraceAware {
} }
@NotNull @NotNull
private JvmClassName jvmClassNameForNamespace(@NotNull NamespaceDescriptor namespace) { private JvmClassName jvmClassNameForNamespace(@NotNull NamespaceDescriptor namespace, @NotNull DeclarationDescriptor descriptor) {
StringBuilder r = new StringBuilder(); StringBuilder r = new StringBuilder();
@@ -145,7 +146,20 @@ public class JetTypeMapper extends BindingTraceAware {
if (r.length() > 0) { if (r.length() > 0) {
r.append("/"); r.append("/");
} }
r.append(PackageClassUtils.getPackageClassName(namespace.getFqName()));
if (descriptor instanceof PropertyDescriptor) {
JetFile file = BindingContextUtils.getContainingFile(bindingContext, descriptor);
if (file != null) {
String internalName = NamespaceCodegen.getNamespacePartInternalName(file);
r.append(internalName.substring(r.length()));
}
else {
r.append(PackageClassUtils.getPackageClassName(namespace.getFqName()));
}
}
else {
r.append(PackageClassUtils.getPackageClassName(namespace.getFqName()));
}
} }
if (r.length() == 0) { if (r.length() == 0) {
@@ -450,7 +464,7 @@ public class JetTypeMapper extends BindingTraceAware {
JvmClassName thisClass; JvmClassName thisClass;
if (functionParent instanceof NamespaceDescriptor) { if (functionParent instanceof NamespaceDescriptor) {
assert !superCall; assert !superCall;
owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent); owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor);
ownerForDefaultImpl = ownerForDefaultParam = owner; ownerForDefaultImpl = ownerForDefaultParam = owner;
invokeOpcode = INVOKESTATIC; invokeOpcode = INVOKESTATIC;
thisClass = null; thisClass = null;
@@ -1,5 +1,6 @@
deprecated("") val test: Int = 0 deprecated("") val test: Int = 0
// TESTED_OBJECT_KIND: property // TESTED_OBJECT_KIND: property
// TESTED_OBJECTS: _DefaultPackage, test // TESTED_OBJECTS: _DefaultPackage$src$topLevelProperty$, test
// IS_FULL_CONTAINING_CLASS_NAME: false
// FLAGS: ACC_DEPRECATED, ACC_FINAL, ACC_STATIC // FLAGS: ACC_DEPRECATED, ACC_FINAL, ACC_STATIC
@@ -76,7 +76,7 @@ public class PropertyGenTest extends CodegenTestCase {
public void testPrivatePropertyInNamespace() throws Exception { public void testPrivatePropertyInNamespace() throws Exception {
loadText("private val x = 239"); loadText("private val x = 239");
final Class nsClass = generateNamespaceClass(); final Class nsClass = generateNamespaceSrcClass();
final Field[] fields = nsClass.getDeclaredFields(); final Field[] fields = nsClass.getDeclaredFields();
assertEquals(1, fields.length); assertEquals(1, fields.length);
final Field field = fields[0]; final Field field = fields[0];
@@ -32,6 +32,7 @@ import java.lang.reflect.Field;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.InTextDirectivesUtils.findListWithPrefix; import static org.jetbrains.jet.InTextDirectivesUtils.findListWithPrefix;
import static org.jetbrains.jet.InTextDirectivesUtils.findStringWithPrefix;
/* /*
* Test correctness of written flags in class file * Test correctness of written flags in class file
@@ -69,22 +70,26 @@ public abstract class AbstractWriteFlagsTest extends UsefulTestCase {
TestedObject testedObject = parseExpectedTestedObject(fileText); TestedObject testedObject = parseExpectedTestedObject(fileText);
boolean isClassFound = false; String className = null;
for (String filename : factory.files()) { for (String filename : factory.files()) {
if (filename.equals(testedObject.containingClass + ".class")) { if (testedObject.isFullContainingClassName && filename.equals(testedObject.containingClass + ".class")) {
isClassFound = true; className = filename;
ClassReader cr = new ClassReader(factory.asBytes(filename)); }
TestClassVisitor classVisitor; else if (!testedObject.isFullContainingClassName && filename.startsWith(testedObject.containingClass)) {
classVisitor = getClassVisitor(testedObject.kind, testedObject.name); className = filename;
cr.accept(classVisitor, ClassReader.SKIP_CODE);
int expectedAccess = getExpectedFlags(fileText);
assertEquals("Wrong access flag \n" + factory.asText(filename), expectedAccess, classVisitor.getAccess());
} }
} }
if (!isClassFound) { if (className == null) {
throw new AssertionError("Couldn't find a class file with name " + testedObject.containingClass); throw new AssertionError("Couldn't find a class file with name " + testedObject.containingClass);
} }
ClassReader cr = new ClassReader(factory.asBytes(className));
TestClassVisitor classVisitor;
classVisitor = getClassVisitor(testedObject.kind, testedObject.name);
cr.accept(classVisitor, ClassReader.SKIP_CODE);
int expectedAccess = getExpectedFlags(fileText);
assertEquals("Wrong access flag \n" + factory.asText(className), expectedAccess, classVisitor.getAccess());
} }
private static TestedObject parseExpectedTestedObject(String fileText) { private static TestedObject parseExpectedTestedObject(String fileText) {
@@ -103,16 +108,18 @@ public abstract class AbstractWriteFlagsTest extends UsefulTestCase {
"TESTED_OBJECTS instruction must contains one (for class) or two (for function and property) values"); "TESTED_OBJECTS instruction must contains one (for class) or two (for function and property) values");
} }
List<String> testedObjectKinds = findListWithPrefix("// TESTED_OBJECT_KIND: ", fileText); result.kind = findStringWithPrefix("// TESTED_OBJECT_KIND: ", fileText);
assertTrue("TESTED_OBJECT_KIND instruction must contains exactly one value. Actual value is " + testedObjectKinds.size(), List<String> isFullName = findListWithPrefix("// IS_FULL_CONTAINING_CLASS_NAME: ", fileText);
testedObjectKinds.size() == 1); if (isFullName.size() == 1) {
result.kind = testedObjectKinds.get(0); result.isFullContainingClassName = Boolean.parseBoolean(isFullName.get(0));
}
return result; return result;
} }
private static class TestedObject { private static class TestedObject {
public String name; public String name;
public String containingClass = ""; public String containingClass = "";
public boolean isFullContainingClassName = true;
public String kind; public String kind;
} }