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 }