NamespaceCodegen refactoring

This commit is contained in:
Mikhael Bogdanov
2013-10-10 13:44:32 +04:00
parent d4b84a8809
commit bcc14effb5
4 changed files with 191 additions and 79 deletions
@@ -16,7 +16,6 @@
package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.io.FileUtil;
@@ -26,7 +25,6 @@ import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.FieldOwnerContext;
@@ -35,9 +33,7 @@ import org.jetbrains.jet.descriptors.serialization.BitEncoding;
import org.jetbrains.jet.descriptors.serialization.DescriptorSerializer;
import org.jetbrains.jet.descriptors.serialization.PackageData;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
@@ -49,7 +45,6 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
@@ -61,15 +56,19 @@ import static org.jetbrains.jet.lang.resolve.java.PackageClassUtils.getPackageCl
public class NamespaceCodegen extends MemberCodegen {
@NotNull
private final ClassBuilderOnDemand v;
@NotNull private final FqName name;
@NotNull
private final FqName name;
@NotNull
private final Collection<JetFile> files;
private final NamespaceDescriptor descriptor;
public NamespaceCodegen(
@NotNull ClassBuilderOnDemand v,
@NotNull final FqName fqName,
GenerationState state,
Collection<JetFile> namespaceFiles
@NotNull GenerationState state,
@NotNull Collection<JetFile> namespaceFiles
) {
super(state, null);
checkAllFilesHaveSameNamespace(namespaceFiles);
@@ -165,9 +164,12 @@ public class NamespaceCodegen extends MemberCodegen {
av.visitEnd();
}
@Nullable
private ClassBuilder generate(@NotNull JetFile file) {
boolean generateSrcClass = false;
FieldOwnerContext namespaceImpl = CodegenContext.STATIC.intoNamespace(descriptor);
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
generateSrcClass = true;
@@ -178,7 +180,7 @@ public class NamespaceCodegen extends MemberCodegen {
}
}
else if (declaration instanceof JetScript) {
ScriptCodegen.createScriptCodegen((JetScript) declaration, state, CodegenContext.STATIC.intoNamespace(descriptor)).generate();
ScriptCodegen.createScriptCodegen((JetScript) declaration, state, namespaceImpl).generate();
}
}
@@ -187,42 +189,20 @@ public class NamespaceCodegen extends MemberCodegen {
Type namespacePartType = getNamespacePartType(getPackageClassFqName(name), file);
ClassBuilder builder = state.getFactory().forNamespacePart(namespacePartType, file);
builder.defineClass(file, V1_6,
ACC_PUBLIC | ACC_FINAL,
namespacePartType.getInternalName(),
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
builder.visitSource(file.getName(), null);
NamespacePartCodegen namespacePartCodegen = new NamespacePartCodegen(builder, file, namespacePartType, namespaceImpl, state);
namespacePartCodegen.generate();
writeKotlinPackageFragmentAnnotation(builder);
FieldOwnerContext nameSpaceContext = CodegenContext.STATIC.intoNamespace(descriptor);
FieldOwnerContext nameSpacePart = CodegenContext.STATIC.intoNamespacePart(namespacePartType, descriptor);
FieldOwnerContext nameSpacePart = CodegenContext.STATIC.intoNamespaceFacade(namespacePartType, descriptor);
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
genFunctionOrProperty(nameSpaceContext, (JetTypeParameterListOwner) declaration, builder);
genFunctionOrProperty(nameSpacePart, (JetTypeParameterListOwner) declaration, v.getClassBuilder());
}
}
generateStaticInitializers(builder, file, nameSpaceContext);
builder.done();
return builder;
}
private static void writeKotlinPackageFragmentAnnotation(@NotNull ClassBuilder builder) {
AnnotationVisitor av = builder.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), true);
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
av.visitEnd();
}
public void generateClassOrObject(@NotNull JetClassOrObject classOrObject) {
CodegenContext context = CodegenContext.STATIC.intoNamespace(descriptor);
genClassOrObject(context, classOrObject);
@@ -263,48 +243,6 @@ public class NamespaceCodegen extends MemberCodegen {
}
}
private void generateStaticInitializers(@NotNull ClassBuilder builder, @NotNull JetFile file, @NotNull FieldOwnerContext context) {
List<JetProperty> properties = collectPropertiesToInitialize(file);
if (properties.isEmpty()) return;
MethodVisitor mv = builder.newMethod(file, ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
SimpleFunctionDescriptorImpl clInit =
new SimpleFunctionDescriptorImpl(descriptor, Collections.<AnnotationDescriptor>emptyList(),
Name.special("<clinit>"),
CallableMemberDescriptor.Kind.SYNTHESIZED);
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context.intoFunction(clInit), state, this);
for (JetDeclaration declaration : properties) {
ImplementationBodyCodegen.
initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
}
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for namespace", file);
mv.visitEnd();
}
}
@NotNull
private List<JetProperty> collectPropertiesToInitialize(@NotNull JetFile file) {
List<JetProperty> result = Lists.newArrayList();
for (JetDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof JetProperty &&
ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
result.add((JetProperty) declaration);
}
}
return result;
}
public void done() {
v.done();
}
@@ -0,0 +1,141 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.asm4.AnnotationVisitor;
import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Type;
import org.jetbrains.jet.codegen.context.FieldOwnerContext;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses;
public class NamespacePartCodegen extends MemberCodegen {
private final ClassBuilder v;
private final NamespaceDescriptor descriptor;
private final JetFile jetFile;
private final Type namespacePartName;
private final FieldOwnerContext context;
public NamespacePartCodegen(
@NotNull ClassBuilder v,
@NotNull JetFile jetFile,
@NotNull Type namespacePartName,
@NotNull FieldOwnerContext context,
@NotNull GenerationState state
) {
super(state, null);
this.v = v;
this.jetFile = jetFile;
this.namespacePartName = namespacePartName;
this.context = context;
descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, jetFile);
assert descriptor != null : "No namespace found for jetFile " + jetFile + " declared package: " + jetFile.getPackageName();
}
public void generate() {
v.defineClass(jetFile, V1_6,
ACC_PUBLIC | ACC_FINAL,
namespacePartName.getInternalName(),
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
v.visitSource(jetFile.getName(), null);
writeKotlinPackageFragmentAnnotation();
for (JetDeclaration declaration : jetFile.getDeclarations()) {
if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) {
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
}
}
generateStaticInitializers();
v.done();
}
private void writeKotlinPackageFragmentAnnotation() {
AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_FRAGMENT), true);
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION);
av.visitEnd();
}
private void generateStaticInitializers() {
List<JetProperty> properties = collectPropertiesToInitialize();
if (properties.isEmpty()) return;
MethodVisitor mv = v.newMethod(jetFile, ACC_STATIC, "<clinit>", "()V", null, null);
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
mv.visitCode();
FrameMap frameMap = new FrameMap();
SimpleFunctionDescriptorImpl clInit =
new SimpleFunctionDescriptorImpl(this.descriptor, Collections.<AnnotationDescriptor>emptyList(),
Name.special("<clinit>"),
CallableMemberDescriptor.Kind.SYNTHESIZED);
clInit.initialize(null, null, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), null, null, Visibilities.PRIVATE, false);
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, this.context.intoFunction(clInit), state, this);
for (JetDeclaration declaration : properties) {
ImplementationBodyCodegen.
initializeProperty(codegen, state.getBindingContext(), (JetProperty) declaration);
}
mv.visitInsn(RETURN);
FunctionCodegen.endVisit(mv, "static initializer for namespace", jetFile);
mv.visitEnd();
}
}
@NotNull
private List<JetProperty> collectPropertiesToInitialize() {
List<JetProperty> result = Lists.newArrayList();
for (JetDeclaration declaration : jetFile.getDeclarations()) {
if (declaration instanceof JetProperty &&
ImplementationBodyCodegen.shouldInitializeProperty((JetProperty) declaration, typeMapper)) {
result.add((JetProperty) declaration);
}
}
return result;
}
}
@@ -152,8 +152,8 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
@NotNull
public FieldOwnerContext intoNamespacePart(@NotNull Type delegateTo, @NotNull NamespaceDescriptor descriptor) {
return new NamespaceContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
public FieldOwnerContext intoNamespaceFacade(@NotNull Type delegateTo, @NotNull NamespaceDescriptor descriptor) {
return new NamespaceFacadeContext(descriptor, this, new OwnerKind.StaticDelegateKind(delegateTo));
}
@NotNull
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.OwnerKind;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
public class NamespaceFacadeContext extends NamespaceContext {
public NamespaceFacadeContext(
@NotNull NamespaceDescriptor contextDescriptor,
@Nullable CodegenContext parent,
@NotNull OwnerKind kind
) {
super(contextDescriptor, parent, kind);
}
}