001 /* 002 * Copyright 2010-2015 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.kotlin.codegen; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; 021 import org.jetbrains.org.objectweb.asm.ClassWriter; 022 import org.jetbrains.org.objectweb.asm.util.TraceClassVisitor; 023 024 import java.io.PrintWriter; 025 import java.io.StringWriter; 026 027 @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") 028 public class ClassBuilderFactories { 029 @NotNull 030 public static ClassBuilderFactory THROW_EXCEPTION = new ClassBuilderFactory() { 031 @NotNull 032 @Override 033 public ClassBuilderMode getClassBuilderMode() { 034 return ClassBuilderMode.FULL; 035 } 036 037 @NotNull 038 @Override 039 public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) { 040 throw new IllegalStateException(); 041 } 042 043 @Override 044 public String asText(ClassBuilder builder) { 045 throw new IllegalStateException(); 046 } 047 048 @Override 049 public byte[] asBytes(ClassBuilder builder) { 050 throw new IllegalStateException(); 051 } 052 }; 053 054 @NotNull 055 public static ClassBuilderFactory TEST = new ClassBuilderFactory() { 056 @NotNull 057 @Override 058 public ClassBuilderMode getClassBuilderMode() { 059 return ClassBuilderMode.FULL; 060 } 061 062 @NotNull 063 @Override 064 public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) { 065 return new TraceBuilder(new BinaryClassWriter()); 066 } 067 068 @Override 069 public String asText(ClassBuilder builder) { 070 TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor(); 071 072 StringWriter writer = new StringWriter(); 073 visitor.p.print(new PrintWriter(writer)); 074 075 return writer.toString(); 076 } 077 078 @Override 079 public byte[] asBytes(ClassBuilder builder) { 080 return ((TraceBuilder) builder).binary.toByteArray(); 081 } 082 }; 083 084 @NotNull 085 public static ClassBuilderFactory BINARIES = new ClassBuilderFactory() { 086 @NotNull 087 @Override 088 public ClassBuilderMode getClassBuilderMode() { 089 return ClassBuilderMode.FULL; 090 } 091 092 @NotNull 093 @Override 094 public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) { 095 return new AbstractClassBuilder.Concrete(new BinaryClassWriter()); 096 } 097 098 @Override 099 public String asText(ClassBuilder builder) { 100 throw new UnsupportedOperationException("BINARIES generator asked for text"); 101 } 102 103 @Override 104 public byte[] asBytes(ClassBuilder builder) { 105 ClassWriter visitor = (ClassWriter) builder.getVisitor(); 106 return visitor.toByteArray(); 107 } 108 }; 109 110 private ClassBuilderFactories() { 111 } 112 113 private static class BinaryClassWriter extends ClassWriter { 114 public BinaryClassWriter() { 115 super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 116 } 117 118 @Override 119 protected String getCommonSuperClass(@NotNull String type1, @NotNull String type2) { 120 try { 121 return super.getCommonSuperClass(type1, type2); 122 } 123 catch (Throwable t) { 124 // @todo we might need at some point do more sophisticated handling 125 return "java/lang/Object"; 126 } 127 } 128 } 129 130 private static class TraceBuilder extends AbstractClassBuilder.Concrete { 131 public final BinaryClassWriter binary; 132 133 public TraceBuilder(BinaryClassWriter binary) { 134 super(new TraceClassVisitor(binary, new PrintWriter(new StringWriter()))); 135 this.binary = binary; 136 } 137 } 138 }