001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.codegen;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.asm4.ClassWriter;
021 import org.jetbrains.asm4.util.TraceClassVisitor;
022
023 import java.io.PrintWriter;
024 import java.io.StringWriter;
025
026 @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
027 public class ClassBuilderFactories {
028
029 public static ClassBuilderFactory TEST = new ClassBuilderFactory() {
030 @NotNull
031 @Override
032 public ClassBuilderMode getClassBuilderMode() {
033 return ClassBuilderMode.FULL;
034 }
035
036 @Override
037 public ClassBuilder newClassBuilder() {
038 return new TraceBuilder(new BinaryClassWriter());
039 }
040
041 @Override
042 public String asText(ClassBuilder builder) {
043 TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();
044
045 StringWriter writer = new StringWriter();
046 visitor.p.print(new PrintWriter(writer));
047
048 return writer.toString();
049 }
050
051 @Override
052 public byte[] asBytes(ClassBuilder builder) {
053 return ((TraceBuilder) builder).binary.toByteArray();
054 }
055 };
056
057 public static ClassBuilderFactory TEXT = new ClassBuilderFactory() {
058 @NotNull
059 @Override
060 public ClassBuilderMode getClassBuilderMode() {
061 return ClassBuilderMode.FULL;
062 }
063
064 @Override
065 public ClassBuilder newClassBuilder() {
066 return new ClassBuilder.Concrete(new TraceClassVisitor(new PrintWriter(new StringWriter())));
067 }
068
069 @Override
070 public String asText(ClassBuilder builder) {
071 TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();
072
073 StringWriter writer = new StringWriter();
074 visitor.p.print(new PrintWriter(writer));
075
076 return writer.toString();
077 }
078
079 @Override
080 public byte[] asBytes(ClassBuilder builder) {
081 throw new UnsupportedOperationException("TEXT generator asked for bytes");
082 }
083 };
084
085 private ClassBuilderFactories() {
086 }
087
088 public static ClassBuilderFactory binaries(final boolean stubs) {
089 return new ClassBuilderFactory() {
090 @NotNull
091 @Override
092 public ClassBuilderMode getClassBuilderMode() {
093 return stubs ? ClassBuilderMode.STUBS : ClassBuilderMode.FULL;
094 }
095
096 @Override
097 public ClassBuilder newClassBuilder() {
098 return new ClassBuilder.Concrete(new BinaryClassWriter());
099 }
100
101 @Override
102 public String asText(ClassBuilder builder) {
103 throw new UnsupportedOperationException("BINARIES generator asked for text");
104 }
105
106 @Override
107 public byte[] asBytes(ClassBuilder builder) {
108 ClassWriter visitor = (ClassWriter) builder.getVisitor();
109 return visitor.toByteArray();
110 }
111 };
112 }
113
114 private static class BinaryClassWriter extends ClassWriter {
115 public BinaryClassWriter() {
116 super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
117 }
118
119 @Override
120 protected String getCommonSuperClass(String type1, String type2) {
121 try {
122 return super.getCommonSuperClass(type1, type2);
123 }
124 catch (Throwable t) {
125 // @todo we might need at some point do more sophisticated handling
126 return "java/lang/Object";
127 }
128 }
129 }
130
131 private static class TraceBuilder extends ClassBuilder.Concrete {
132 public final BinaryClassWriter binary;
133
134 public TraceBuilder(BinaryClassWriter binary) {
135 super(new TraceClassVisitor(binary, new PrintWriter(new StringWriter())));
136 this.binary = binary;
137 }
138 }
139 }