diff --git a/idea/META-INF/plugin.xml b/idea/META-INF/plugin.xml
index d06ca31e619..66c13c395b7 100644
--- a/idea/META-INF/plugin.xml
+++ b/idea/META-INF/plugin.xml
@@ -5,11 +5,12 @@
JetBrains
-
-
+
+ org.jetbrains.jet.compiler.JetCompilerManager
+
diff --git a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
index 15f6a76cad1..9cd32a6711c 100644
--- a/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
+++ b/idea/src/org/jetbrains/jet/codegen/NamespaceCodegen.java
@@ -16,22 +16,28 @@ import org.objectweb.asm.Opcodes;
* @author max
*/
public class NamespaceCodegen {
- public NamespaceCodegen() {
- }
+ private final Project project;
+ private final ClassVisitor v;
- public void generate(JetNamespace namespace, ClassVisitor v, Project project) {
- BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, ErrorHandler.THROW_EXCEPTION);
+ public NamespaceCodegen(Project project, ClassVisitor v, String fqName) {
+ this.project = project;
+ this.v = v;
- final PropertyCodegen propertyCodegen = new PropertyCodegen(v);
- final FunctionCodegen functionCodegen = new FunctionCodegen(v, JetStandardLibrary.getJetStandardLibrary(project), bindingContext);
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC,
- getJVMClassName(namespace),
+ getJVMClassName(fqName),
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
+ }
+
+ public void generate(JetNamespace namespace) {
+ BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, ErrorHandler.THROW_EXCEPTION);
+
+ final PropertyCodegen propertyCodegen = new PropertyCodegen(v);
+ final FunctionCodegen functionCodegen = new FunctionCodegen(v, JetStandardLibrary.getJetStandardLibrary(project), bindingContext);
for (JetDeclaration declaration : namespace.getDeclarations()) {
if (declaration instanceof JetProperty) {
@@ -41,12 +47,17 @@ public class NamespaceCodegen {
functionCodegen.gen((JetFunction) declaration, namespace);
}
}
+ }
-
+ public void done() {
v.visitEnd();
}
- public static String getJVMClassName(JetNamespace namespace) {
- return namespace.getFQName().replace('.', '/') + "/namespace";
+ public static String getJVMClassName(String fqName) {
+ return fqName.replace('.', '/') + "/namespace";
+ }
+
+ public ClassVisitor getVisitor() {
+ return v;
}
}
diff --git a/idea/src/org/jetbrains/jet/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/compiler/JetCompiler.java
new file mode 100644
index 00000000000..e5fa803f0e9
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/compiler/JetCompiler.java
@@ -0,0 +1,124 @@
+package org.jetbrains.jet.compiler;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileScope;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+import com.intellij.openapi.compiler.TranslatingCompiler;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.Chunk;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.codegen.NamespaceCodegen;
+import org.jetbrains.jet.lang.JetFileType;
+import org.jetbrains.jet.lang.psi.JetFile;
+import org.jetbrains.jet.lang.psi.JetNamespace;
+import org.objectweb.asm.ClassWriter;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author yole
+ */
+public class JetCompiler implements TranslatingCompiler {
+ @Override
+ public boolean isCompilableFile(VirtualFile virtualFile, CompileContext compileContext) {
+ return virtualFile.getFileType() instanceof JetFileType;
+ }
+
+ @NotNull
+ @Override
+ public String getDescription() {
+ return "Jet Language Compiler";
+ }
+
+ @Override
+ public boolean validateConfiguration(CompileScope compileScope) {
+ return true;
+ }
+
+ @Override
+ public void compile(CompileContext compileContext, Chunk moduleChunk, VirtualFile[] virtualFiles, OutputSink outputSink) {
+ Map moduleMap = new HashMap();
+
+ for (VirtualFile virtualFile : virtualFiles) {
+ Module module = compileContext.getModuleByFile(virtualFile);
+ ModuleCompileState state = moduleMap.get(module);
+ if (state == null) {
+ state = new ModuleCompileState(compileContext, module, outputSink);
+ moduleMap.put(module, state);
+ }
+ state.compile(virtualFile);
+ }
+
+ for (ModuleCompileState state : moduleMap.values()) {
+ state.done();
+ }
+
+ }
+
+ private static class ModuleCompileState {
+ private final Map ns2codegen = new HashMap();
+ private final CompileContext compileContext;
+ private final Module module;
+ private final OutputSink outputSink;
+
+ public ModuleCompileState(CompileContext compileContext, Module module, OutputSink outputSink) {
+ this.compileContext = compileContext;
+ this.module = module;
+ this.outputSink = outputSink;
+ }
+
+ public void compile(final VirtualFile virtualFile) {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(virtualFile);
+ if (psiFile instanceof JetFile) {
+ final JetNamespace namespace = ((JetFile) psiFile).getRootNamespace();
+ String fqName = namespace.getFQName();
+ NamespaceCodegen codegen = ns2codegen.get(fqName);
+ if (codegen == null) {
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+ codegen = new NamespaceCodegen(compileContext.getProject(), writer, fqName);
+ ns2codegen.put(fqName, codegen);
+ }
+ codegen.generate(namespace);
+ }
+ }
+ });
+ }
+
+ public void done() {
+ VirtualFile outputDir = compileContext.getModuleOutputDirectory(module);
+
+ for (Map.Entry entry : ns2codegen.entrySet()) {
+ NamespaceCodegen codegen = entry.getValue();
+ codegen.done();
+
+ try {
+ File nsOutputDir = dirForPackage(outputDir, entry.getKey());
+ ClassWriter writer = (ClassWriter) codegen.getVisitor();
+ File output = new File(nsOutputDir, "namespace.class");
+ FileUtil.writeToFile(output, writer.toByteArray());
+ } catch (IOException e) {
+ compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, 0, 0);
+ }
+ }
+ }
+
+ private static File dirForPackage(VirtualFile root, String fqName) throws IOException {
+ File result = new File(root.getPath(), fqName.replace(".", "/"));
+ if (!result.mkdirs()) {
+ throw new IOException("Failed to create directory for package");
+ }
+ return result;
+ }
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/compiler/JetCompilerManager.java b/idea/src/org/jetbrains/jet/compiler/JetCompilerManager.java
new file mode 100644
index 00000000000..26eff803644
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/compiler/JetCompilerManager.java
@@ -0,0 +1,19 @@
+package org.jetbrains.jet.compiler;
+
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import org.jetbrains.jet.lang.JetFileType;
+
+import java.util.Collections;
+
+/**
+ * @author yole
+ */
+public class JetCompilerManager {
+ public JetCompilerManager(CompilerManager manager) {
+ manager.addTranslatingCompiler(new JetCompiler(),
+ Collections.singleton(JetFileType.INSTANCE),
+ Collections.singleton(StdFileTypes.CLASS));
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java
index a46788c8562..4db4c157451 100644
--- a/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java
+++ b/idea/tests/org/jetbrains/jet/codegen/NamespaceGenTest.java
@@ -18,12 +18,9 @@ import java.lang.reflect.Method;
* @author yole
*/
public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
- private NamespaceCodegen codegen;
-
@Override
protected void setUp() throws Exception {
super.setUp();
- codegen = new NamespaceCodegen();
}
public void testPSVM() throws Exception {
@@ -114,7 +111,10 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
StringWriter writer = new StringWriter();
JetFile jetFile = (JetFile) myFixture.getFile();
JetNamespace namespace = jetFile.getRootNamespace();
- codegen.generate(namespace, new TraceClassVisitor(new PrintWriter(writer)), getProject());
+ NamespaceCodegen codegen = new NamespaceCodegen(getProject(),
+ new TraceClassVisitor(new PrintWriter(writer)),
+ namespace.getFQName());
+ codegen.generate(namespace);
return writer.toString();
}
@@ -122,10 +122,13 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
JetFile jetFile = (JetFile) myFixture.getFile();
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
final JetNamespace namespace = jetFile.getRootNamespace();
- codegen.generate(namespace, writer, getProject());
+ NamespaceCodegen codegen = new NamespaceCodegen(getProject(),
+ writer,
+ namespace.getFQName());
+ codegen.generate(namespace);
final byte[] data = writer.toByteArray();
MyClassLoader classLoader = new MyClassLoader(NamespaceGenTest.class.getClassLoader());
- final Class aClass = classLoader.doDefineClass(NamespaceCodegen.getJVMClassName(namespace).replace("/", "."), data);
+ final Class aClass = classLoader.doDefineClass(NamespaceCodegen.getJVMClassName(namespace.getFQName()).replace("/", "."), data);
return aClass;
}