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 com.intellij.psi.PsiElement;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.kotlin.codegen.inline.FileMapping;
023 import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
024 import org.jetbrains.kotlin.codegen.inline.SMAPBuilder;
025 import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
026 import org.jetbrains.org.objectweb.asm.*;
027
028 import java.util.ArrayList;
029 import java.util.List;
030
031 public abstract class AbstractClassBuilder implements ClassBuilder {
032 protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.ASM5) {};
033 protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.ASM5) {};
034
035 private String thisName;
036
037 private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
038
039 private final List<FileMapping> fileMappings = new ArrayList<FileMapping>();
040
041 private String sourceName;
042
043 private String debugInfo;
044
045 public static class Concrete extends AbstractClassBuilder {
046 private final ClassVisitor v;
047
048 public Concrete(@NotNull ClassVisitor v) {
049 this.v = v;
050 }
051
052 @Override
053 @NotNull
054 public ClassVisitor getVisitor() {
055 return v;
056 }
057 }
058
059 @Override
060 @NotNull
061 public FieldVisitor newField(
062 @NotNull JvmDeclarationOrigin origin,
063 int access,
064 @NotNull String name,
065 @NotNull String desc,
066 @Nullable String signature,
067 @Nullable Object value
068 ) {
069 FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
070 if (visitor == null) {
071 return EMPTY_FIELD_VISITOR;
072 }
073 return visitor;
074 }
075
076 @Override
077 @NotNull
078 public MethodVisitor newMethod(
079 @NotNull JvmDeclarationOrigin origin,
080 int access,
081 @NotNull String name,
082 @NotNull String desc,
083 @Nullable String signature,
084 @Nullable String[] exceptions
085 ) {
086 MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
087 if (visitor == null) {
088 return EMPTY_METHOD_VISITOR;
089 }
090 return visitor;
091 }
092
093 @Override
094 @NotNull
095 public JvmSerializationBindings getSerializationBindings() {
096 return serializationBindings;
097 }
098
099 @Override
100 @NotNull
101 public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
102 return getVisitor().visitAnnotation(desc, visible);
103 }
104
105 @Override
106 public void done() {
107 if (!fileMappings.isEmpty() && InlineCodegenUtil.GENERATE_SMAP) {
108 FileMapping origin = fileMappings.get(0);
109 assert sourceName == null || origin.getName().equals(sourceName) : "Error " + origin.getName() + " != " + sourceName;
110 getVisitor().visitSource(origin.getName(), new SMAPBuilder(origin.getName(), origin.getPath(), fileMappings).build());
111 }
112 else {
113 getVisitor().visitSource(sourceName, debugInfo);
114 }
115
116 getVisitor().visitEnd();
117 }
118
119 @Override
120 public void defineClass(
121 @Nullable PsiElement origin,
122 int version,
123 int access,
124 @NotNull String name,
125 @Nullable String signature,
126 @NotNull String superName,
127 @NotNull String[] interfaces
128 ) {
129 thisName = name;
130 getVisitor().visit(version, access, name, signature, superName, interfaces);
131 }
132
133 @Override
134 public void visitSource(@NotNull String name, @Nullable String debug) {
135 sourceName = name;
136 debugInfo = debug;
137 }
138
139 @Override
140 public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
141 getVisitor().visitOuterClass(owner, name, desc);
142 }
143
144 @Override
145 public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
146 getVisitor().visitInnerClass(name, outerName, innerName, access);
147 }
148
149 @Override
150 @NotNull
151 public String getThisName() {
152 assert thisName != null : "This name isn't set";
153 return thisName;
154 }
155
156 @Override
157 public void addSMAP(FileMapping mapping) {
158 fileMappings.add(mapping);
159 }
160 }