Move top level properties from package class to package$src
This commit is contained in:
@@ -314,7 +314,7 @@ public class FunctionCodegen extends GenerationStateAware {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateStaticDelegateMethodBody(
|
||||
public static void generateStaticDelegateMethodBody(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@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";
|
||||
|
||||
if (hasNonConstantPropertyInitializers()) {
|
||||
generateStaticInitializers();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
int countOfDeclarationsInSrcClass = 0;
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
|
||||
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
||||
countOfDeclarationsInSrcClass++;
|
||||
}
|
||||
else if (declaration instanceof JetClassOrObject) {
|
||||
@@ -154,7 +146,7 @@ public class NamespaceCodegen extends MemberCodegen {
|
||||
builder.visitSource(file.getName(), null);
|
||||
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetNamedFunction) {
|
||||
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
|
||||
{
|
||||
final CodegenContext context =
|
||||
CodegenContext.STATIC.intoNamespace(descriptor);
|
||||
@@ -168,6 +160,10 @@ public class NamespaceCodegen extends MemberCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNonConstantPropertyInitializers()) {
|
||||
generateStaticInitializers(builder, file);
|
||||
}
|
||||
|
||||
builder.done();
|
||||
}
|
||||
}
|
||||
@@ -210,41 +206,32 @@ public class NamespaceCodegen extends MemberCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateStaticInitializers() {
|
||||
final JetFile namespace = files.iterator().next(); // @todo: hack
|
||||
private void generateStaticInitializers(@NotNull ClassBuilder builder, @NotNull JetFile file) {
|
||||
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() {
|
||||
@Override
|
||||
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();
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContext.STATIC, state);
|
||||
|
||||
for (JetFile file : files) {
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
final PropertyDescriptor descriptor =
|
||||
(PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||
assert descriptor != null;
|
||||
codegen.genToJVMStack(initializer);
|
||||
StackValue.Property propValue = codegen.intermediateValueForProperty(descriptor, true, null);
|
||||
propValue.store(propValue.type, new InstructionAdapter(mv));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
final PropertyDescriptor descriptor =
|
||||
(PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||
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() {
|
||||
|
||||
@@ -66,10 +66,10 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
throw new UnsupportedOperationException("expect a property to have a property 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;
|
||||
|
||||
if (kind != OwnerKind.TRAIT_IMPL) {
|
||||
if (kind != OwnerKind.TRAIT_IMPL && !(kind instanceof OwnerKind.StaticDelegateKind)) {
|
||||
generateBackingField(p, propertyDescriptor);
|
||||
}
|
||||
generateGetter(p, propertyDescriptor);
|
||||
@@ -166,7 +166,7 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
return;
|
||||
}
|
||||
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
if (kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) {
|
||||
flags |= ACC_STATIC;
|
||||
}
|
||||
|
||||
@@ -200,6 +200,9 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
genStubThrow(mv);
|
||||
}
|
||||
else if (kind instanceof OwnerKind.StaticDelegateKind) {
|
||||
FunctionCodegen.generateStaticDelegateMethodBody(mv, jvmMethodSignature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind);
|
||||
}
|
||||
else {
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
@@ -246,7 +249,7 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
return;
|
||||
}
|
||||
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
if (kind == OwnerKind.NAMESPACE || kind instanceof OwnerKind.StaticDelegateKind) {
|
||||
flags |= ACC_STATIC;
|
||||
}
|
||||
|
||||
@@ -276,6 +279,9 @@ public class PropertyCodegen extends GenerationStateAware {
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.STUBS) {
|
||||
genStubThrow(mv);
|
||||
}
|
||||
else if (kind instanceof OwnerKind.StaticDelegateKind) {
|
||||
FunctionCodegen.generateStaticDelegateMethodBody(mv, jvmMethodSignature.getAsmMethod(), (OwnerKind.StaticDelegateKind) kind);
|
||||
}
|
||||
else {
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
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.psi.JetDelegatorToSuperCall;
|
||||
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.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
@@ -66,7 +67,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
if (containingDeclaration instanceof NamespaceDescriptor) {
|
||||
return jvmClassNameForNamespace((NamespaceDescriptor) containingDeclaration);
|
||||
return jvmClassNameForNamespace((NamespaceDescriptor) containingDeclaration, descriptor);
|
||||
}
|
||||
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||
@@ -121,7 +122,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JvmClassName jvmClassNameForNamespace(@NotNull NamespaceDescriptor namespace) {
|
||||
private JvmClassName jvmClassNameForNamespace(@NotNull NamespaceDescriptor namespace, @NotNull DeclarationDescriptor descriptor) {
|
||||
|
||||
StringBuilder r = new StringBuilder();
|
||||
|
||||
@@ -145,7 +146,20 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
if (r.length() > 0) {
|
||||
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) {
|
||||
@@ -450,7 +464,7 @@ public class JetTypeMapper extends BindingTraceAware {
|
||||
JvmClassName thisClass;
|
||||
if (functionParent instanceof NamespaceDescriptor) {
|
||||
assert !superCall;
|
||||
owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent);
|
||||
owner = jvmClassNameForNamespace((NamespaceDescriptor) functionParent, functionDescriptor);
|
||||
ownerForDefaultImpl = ownerForDefaultParam = owner;
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
thisClass = null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
deprecated("") val test: Int = 0
|
||||
|
||||
// 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
|
||||
|
||||
@@ -76,7 +76,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
||||
|
||||
public void testPrivatePropertyInNamespace() throws Exception {
|
||||
loadText("private val x = 239");
|
||||
final Class nsClass = generateNamespaceClass();
|
||||
final Class nsClass = generateNamespaceSrcClass();
|
||||
final Field[] fields = nsClass.getDeclaredFields();
|
||||
assertEquals(1, fields.length);
|
||||
final Field field = fields[0];
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.InTextDirectivesUtils.findListWithPrefix;
|
||||
import static org.jetbrains.jet.InTextDirectivesUtils.findStringWithPrefix;
|
||||
|
||||
/*
|
||||
* Test correctness of written flags in class file
|
||||
@@ -69,22 +70,26 @@ public abstract class AbstractWriteFlagsTest extends UsefulTestCase {
|
||||
|
||||
TestedObject testedObject = parseExpectedTestedObject(fileText);
|
||||
|
||||
boolean isClassFound = false;
|
||||
String className = null;
|
||||
for (String filename : factory.files()) {
|
||||
if (filename.equals(testedObject.containingClass + ".class")) {
|
||||
isClassFound = true;
|
||||
ClassReader cr = new ClassReader(factory.asBytes(filename));
|
||||
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(filename), expectedAccess, classVisitor.getAccess());
|
||||
if (testedObject.isFullContainingClassName && filename.equals(testedObject.containingClass + ".class")) {
|
||||
className = filename;
|
||||
}
|
||||
else if (!testedObject.isFullContainingClassName && filename.startsWith(testedObject.containingClass)) {
|
||||
className = filename;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isClassFound) {
|
||||
if (className == null) {
|
||||
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) {
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
List<String> testedObjectKinds = findListWithPrefix("// TESTED_OBJECT_KIND: ", fileText);
|
||||
assertTrue("TESTED_OBJECT_KIND instruction must contains exactly one value. Actual value is " + testedObjectKinds.size(),
|
||||
testedObjectKinds.size() == 1);
|
||||
result.kind = testedObjectKinds.get(0);
|
||||
result.kind = findStringWithPrefix("// TESTED_OBJECT_KIND: ", fileText);
|
||||
List<String> isFullName = findListWithPrefix("// IS_FULL_CONTAINING_CLASS_NAME: ", fileText);
|
||||
if (isFullName.size() == 1) {
|
||||
result.isFullContainingClassName = Boolean.parseBoolean(isFullName.get(0));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class TestedObject {
|
||||
public String name;
|
||||
public String containingClass = "";
|
||||
public boolean isFullContainingClassName = true;
|
||||
public String kind;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user