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