one more step to multi-file compilation
This commit is contained in:
@@ -61,13 +61,12 @@ public class ClassFileFactory {
|
||||
return newVisitor(className.getInternalName() + ".class");
|
||||
}
|
||||
|
||||
NamespaceCodegen forNamespace(JetFile file) {
|
||||
NamespaceCodegen forNamespace(FqName fqName, Collection<JetFile> files) {
|
||||
assert !isDone : "Already done!";
|
||||
FqName fqName = JetPsiUtil.getFQName(file);
|
||||
NamespaceCodegen codegen = ns2codegen.get(fqName);
|
||||
if (codegen == null) {
|
||||
final ClassBuilder builder = newVisitor(NamespaceCodegen.getJVMClassNameForKotlinNs(fqName).getInternalName() + ".class");
|
||||
codegen = new NamespaceCodegen(builder, fqName, state, file.getContainingFile());
|
||||
codegen = new NamespaceCodegen(builder, fqName, state, files);
|
||||
ns2codegen.put(fqName, codegen);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,42 +119,25 @@ public class GenerationState {
|
||||
return Pair.create(className, getFactory().forAnonymousSubclass(className));
|
||||
}
|
||||
|
||||
public NamespaceCodegen forNamespace(JetFile namespace) {
|
||||
return getFactory().forNamespace(namespace);
|
||||
public NamespaceCodegen forNamespace(FqName fqName, Collection<JetFile> namespace) {
|
||||
return getFactory().forNamespace(fqName, namespace);
|
||||
}
|
||||
|
||||
public void compileCorrectFiles(@NotNull CompilationErrorHandler errorHandler) {
|
||||
MultiMap<String, JetFile> namespaceGrouping = new MultiMap<String, JetFile>();
|
||||
MultiMap<FqName, JetFile> namespaceGrouping = new MultiMap<FqName, JetFile>();
|
||||
for (JetFile file : this.files) {
|
||||
if (file == null) throw new IllegalArgumentException("A null file given for compilation");
|
||||
namespaceGrouping.putValue(JetPsiUtil.getFQName(file).getFqName(), file);
|
||||
namespaceGrouping.putValue(JetPsiUtil.getFQName(file), file);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Collection<JetFile>> entry : namespaceGrouping.entrySet()) {
|
||||
for (JetFile file : entry.getValue()) {
|
||||
VirtualFile vFile = file.getVirtualFile();
|
||||
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
|
||||
progress.log("For source: " + path + "\tFor namespace: " + entry.getKey());
|
||||
try {
|
||||
generateNamespace(file);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<FqName, Collection<JetFile>> entry : namespaceGrouping.entrySet()) {
|
||||
generateNamespace(entry.getKey(), entry.getValue(), errorHandler, progress);
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateNamespace(JetFile namespace) {
|
||||
NamespaceCodegen codegen = forNamespace(namespace);
|
||||
codegen.generate(namespace);
|
||||
protected void generateNamespace(FqName fqName, Collection<JetFile> namespace, CompilationErrorHandler errorHandler, Progress progress) {
|
||||
NamespaceCodegen codegen = forNamespace(fqName, namespace);
|
||||
codegen.generate(errorHandler, progress);
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ObjectOrClosureCodegen closure) {
|
||||
|
||||
@@ -16,19 +16,26 @@
|
||||
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.utils.Progress;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
@@ -36,12 +43,17 @@ import static org.objectweb.asm.Opcodes.*;
|
||||
*/
|
||||
public class NamespaceCodegen {
|
||||
private final ClassBuilder v;
|
||||
@NotNull private final FqName name;
|
||||
private final GenerationState state;
|
||||
private final Collection<JetFile> files;
|
||||
|
||||
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, PsiFile sourceFile) {
|
||||
public NamespaceCodegen(ClassBuilder v, @NotNull FqName fqName, GenerationState state, Collection<JetFile> files) {
|
||||
this.v = v;
|
||||
name = fqName;
|
||||
this.state = state;
|
||||
this.files = files;
|
||||
|
||||
PsiFile sourceFile = files.iterator().next().getContainingFile();
|
||||
v.defineClass(sourceFile, V1_6,
|
||||
ACC_PUBLIC/*|ACC_SUPER*/,
|
||||
getJVMClassNameForKotlinNs(fqName).getInternalName(),
|
||||
@@ -54,8 +66,32 @@ public class NamespaceCodegen {
|
||||
v.visitSource(sourceFile.getName(), null);
|
||||
}
|
||||
|
||||
public void generate(JetFile file) {
|
||||
public void generate(CompilationErrorHandler errorHandler, Progress progress) {
|
||||
for (JetFile file : files) {
|
||||
VirtualFile vFile = file.getVirtualFile();
|
||||
try {
|
||||
String path = vFile != null ? vFile.getPath() : "no_virtual_file/" + file.getName();
|
||||
if(progress != null) progress.log("For source: " + path);
|
||||
generate(file);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
if(errorHandler != null) errorHandler.reportException(e, vFile == null ? "no file" : vFile.getUrl());
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNonConstantPropertyInitializers()) {
|
||||
generateStaticInitializers();
|
||||
}
|
||||
}
|
||||
|
||||
private void generate(JetFile file) {
|
||||
for (JetDeclaration declaration : file.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
|
||||
NamespaceDescriptor descriptor = state.getBindingContext().get(BindingContext.FILE_TO_NAMESPACE, file);
|
||||
@@ -71,54 +107,54 @@ public class NamespaceCodegen {
|
||||
else if (declaration instanceof JetScript) {
|
||||
state.getInjector().getScriptCodegen().generate((JetScript) declaration);
|
||||
}
|
||||
// else if (declaration instanceof JetFile) {
|
||||
// JetFile childNamespace = (JetFile) declaration;
|
||||
// state.forNamespace(childNamespace).generate(childNamespace);
|
||||
// }
|
||||
}
|
||||
|
||||
if (hasNonConstantPropertyInitializers(file)) {
|
||||
generateStaticInitializers(file);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateStaticInitializers(JetFile namespace) {
|
||||
private void generateStaticInitializers() {
|
||||
JetFile namespace = files.iterator().next(); // @todo: hack
|
||||
|
||||
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
for (JetFile file : files) {
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitCode();
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
|
||||
FrameMap frameMap = new FrameMap();
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, CodegenContexts.STATIC, state);
|
||||
|
||||
for (JetDeclaration declaration : namespace.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;
|
||||
if(descriptor.getReceiverParameter().exists()) {
|
||||
continue;
|
||||
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;
|
||||
if(descriptor.getReceiverParameter().exists()) {
|
||||
continue;
|
||||
}
|
||||
codegen.genToJVMStack(initializer);
|
||||
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
||||
}
|
||||
codegen.genToJVMStack(initializer);
|
||||
codegen.intermediateValueForProperty(descriptor, true, null).store(new InstructionAdapter(mv));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
|
||||
mv.visitInsn(RETURN);
|
||||
FunctionCodegen.endVisit(mv, "static initializer for namespace", namespace);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNonConstantPropertyInitializers(JetFile namespace) {
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
return true;
|
||||
}
|
||||
private boolean hasNonConstantPropertyInitializers() {
|
||||
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)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -52,8 +52,10 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
import org.jetbrains.jet.util.QualifiedNamesUtil;
|
||||
import org.jetbrains.jet.utils.Progress;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMarker {
|
||||
@@ -178,7 +180,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
|
||||
|
||||
final GenerationState state = new GenerationState(project, builderFactory, context, Collections.singletonList(file)) {
|
||||
@Override
|
||||
protected void generateNamespace(JetFile namespace) {
|
||||
protected void generateNamespace(FqName fqName, Collection<JetFile> namespace, CompilationErrorHandler errorHandler, Progress progress) {
|
||||
PsiManager manager = PsiManager.getInstance(project);
|
||||
stubStack.push(answer);
|
||||
|
||||
@@ -195,7 +197,7 @@ public class JetLightClass extends AbstractLightClass implements JetJavaMirrorMa
|
||||
fakeFile.setPhysical(false);
|
||||
answer.setPsi(fakeFile);
|
||||
|
||||
super.generateNamespace(namespace);
|
||||
super.generateNamespace(fqName, namespace, errorHandler, progress);
|
||||
final StubElement pop = stubStack.pop();
|
||||
if (pop != answer) {
|
||||
LOG.error("Unbalanced stack operations: " + pop);
|
||||
|
||||
@@ -78,7 +78,7 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
|
||||
public void testIntGenerics () throws Exception {
|
||||
loadText("class L<T>(var a : T) {} fun foo() = L<Int>(5).a");
|
||||
// System.out.println(generateToText());
|
||||
System.out.println(generateToText());
|
||||
Method foo = generateFunction();
|
||||
Object invoke = foo.invoke(null);
|
||||
System.out.println(invoke.getClass());
|
||||
|
||||
Reference in New Issue
Block a user