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 public static ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
086 @NotNull
087 @Override
088 public ClassBuilderMode getClassBuilderMode() {
089 return ClassBuilderMode.FULL;
090 }
091
092 @Override
093 public ClassBuilder newClassBuilder() {
094 return new ClassBuilder.Concrete(new BinaryClassWriter());
095 }
096
097 @Override
098 public String asText(ClassBuilder builder) {
099 throw new UnsupportedOperationException("BINARIES generator asked for text");
100 }
101
102 @Override
103 public byte[] asBytes(ClassBuilder builder) {
104 ClassWriter visitor = (ClassWriter) builder.getVisitor();
105 return visitor.toByteArray();
106 }
107 };
108
109 private ClassBuilderFactories() {
110 }
111
112 private static class BinaryClassWriter extends ClassWriter {
113 public BinaryClassWriter() {
114 super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
115 }
116
117 @Override
118 protected String getCommonSuperClass(String type1, String type2) {
119 try {
120 return super.getCommonSuperClass(type1, type2);
121 }
122 catch (Throwable t) {
123 // @todo we might need at some point do more sophisticated handling
124 return "java/lang/Object";
125 }
126 }
127 }
128
129 private static class TraceBuilder extends ClassBuilder.Concrete {
130 public final BinaryClassWriter binary;
131
132 public TraceBuilder(BinaryClassWriter binary) {
133 super(new TraceClassVisitor(binary, new PrintWriter(new StringWriter())));
134 this.binary = binary;
135 }
136 }
137 }