Plugable asm visitors strategy

This commit is contained in:
Maxim Shafirov
2011-11-04 06:05:34 +03:00
parent 98774400ce
commit 498797b013
7 changed files with 74 additions and 41 deletions
+3 -1
View File
@@ -4,6 +4,8 @@
<root url="jar://$PROJECT_DIR$/lib/asm-util-3.3.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
<SOURCES>
<root url="file://$USER_HOME$/libs/asm-3.3.1/src" />
</SOURCES>
</library>
</component>
@@ -0,0 +1,57 @@
package org.jetbrains.jet.codegen;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author max
*/
public interface ClassBuilderFactory {
ClassBuilder newClassBuilder();
String asText(ClassBuilder builder);
byte[] asBytes(ClassBuilder builder);
ClassBuilderFactory TEXT = new ClassBuilderFactory() {
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder(new TraceClassVisitor(new PrintWriter(new StringWriter())));
}
@Override
public String asText(ClassBuilder builder) {
TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();
StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer));
return writer.toString();
}
@Override
public byte[] asBytes(ClassBuilder builder) {
throw new UnsupportedOperationException("TEXT generator asked for bytes");
}
};
ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
}
@Override
public String asText(ClassBuilder builder) {
throw new UnsupportedOperationException("BINARIES generator asked for text");
}
@Override
public byte[] asBytes(ClassBuilder builder) {
ClassWriter visitor = (ClassWriter) builder.getVisitor();
return visitor.toByteArray();
}
};
}
@@ -1,42 +1,26 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
/**
* @author max
*/
public class ClassFileFactory {
private final Project project;
private final boolean isText;
private final ClassBuilderFactory builderFactory;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassBuilder> generators = new LinkedHashMap<String, ClassBuilder>();
private boolean isDone = false;
public final GenerationState state;
public ClassFileFactory(Project project, boolean text, GenerationState state) {
this.project = project;
isText = text;
public ClassFileFactory(ClassBuilderFactory builderFactory, GenerationState state) {
this.builderFactory = builderFactory;
this.state = state;
}
ClassBuilder newVisitor(String filePath) {
ClassVisitor visitor;
if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
}
else {
visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
final ClassBuilder answer = new ClassBuilder(visitor);
final ClassBuilder answer = builderFactory.newClassBuilder();
generators.put(filePath, answer);
return answer;
}
@@ -68,25 +52,13 @@ public class ClassFileFactory {
}
public String asText(String file) {
assert isText : "Need to create with text=true";
done();
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file).getVisitor();
StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer));
return writer.toString();
return builderFactory.asText(generators.get(file));
}
public byte[] asBytes(String file) {
assert !isText : "This is debug stuff, only produces texts.";
done();
ClassWriter visitor = (ClassWriter) generators.get(file).getVisitor();
return visitor.toByteArray();
return builderFactory.asBytes(generators.get(file));
}
public List<String> files() {
@@ -28,10 +28,10 @@ public class GenerationState {
private final JetStandardLibrary standardLibrary;
private final IntrinsicMethods intrinsics;
public GenerationState(Project project, boolean text) {
public GenerationState(Project project, ClassBuilderFactory builderFactory) {
this.project = project;
this.standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
this.factory = new ClassFileFactory(project, text, this);
this.factory = new ClassFileFactory(builderFactory, this);
this.intrinsics = new IntrinsicMethods(project, standardLibrary);
}
@@ -5,6 +5,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
@@ -93,7 +94,7 @@ public class CompileSession {
}
public ClassFileFactory generate() {
GenerationState generationState = new GenerationState(myEnvironment.getProject(), false);
GenerationState generationState = new GenerationState(myEnvironment.getProject(), ClassBuilderFactory.BINARIES);
generationState.compileCorrectNamespaces(myBindingContext, mySourceFileNamespaces);
return generationState.getFactory();
}
@@ -98,7 +98,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
}
protected String generateToText() {
GenerationState state = new GenerationState(getProject(), true);
GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.TEXT);
AnalyzingUtils.checkForSyntacticErrors(myFile);
state.compile(myFile);
@@ -152,7 +152,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
protected ClassFileFactory generateClassesInFile() {
try {
GenerationState state = new GenerationState(getProject(), false);
GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.BINARIES);
AnalyzingUtils.checkForSyntacticErrors(myFile);
state.compile(myFile);
@@ -16,6 +16,7 @@ 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.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
@@ -69,7 +70,7 @@ public class JetCompiler implements TranslatingCompiler {
public void run() {
VirtualFile[] allFiles = compileContext.getCompileScope().getFiles(null, true);
GenerationState generationState = new GenerationState(compileContext.getProject(), false);
GenerationState generationState = new GenerationState(compileContext.getProject(), ClassBuilderFactory.BINARIES);
List<JetNamespace> namespaces = Lists.newArrayList();
for (VirtualFile virtualFile : allFiles) {
PsiFile psiFile = PsiManager.getInstance(compileContext.getProject()).findFile(virtualFile);