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 }