001    /*
002     * Copyright 2010-2013 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.jet.codegen;
018    
019    import com.intellij.psi.PsiElement;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.asm4.*;
023    
024    public abstract class AbstractClassBuilder implements ClassBuilder {
025        protected static final MethodVisitor EMPTY_METHOD_VISITOR = new MethodVisitor(Opcodes.ASM4) {};
026        protected static final FieldVisitor EMPTY_FIELD_VISITOR = new FieldVisitor(Opcodes.ASM4) {};
027    
028        private String thisName;
029    
030        private final JvmSerializationBindings serializationBindings = new JvmSerializationBindings();
031    
032        public static class Concrete extends AbstractClassBuilder {
033            private final ClassVisitor v;
034    
035            public Concrete(@NotNull ClassVisitor v) {
036                this.v = v;
037            }
038    
039            @Override
040            @NotNull
041            public ClassVisitor getVisitor() {
042                return v;
043            }
044        }
045    
046        @Override
047        @NotNull
048        public FieldVisitor newField(
049                @Nullable PsiElement origin,
050                int access,
051                @NotNull String name,
052                @NotNull String desc,
053                @Nullable String signature,
054                @Nullable Object value
055        ) {
056            FieldVisitor visitor = getVisitor().visitField(access, name, desc, signature, value);
057            if (visitor == null) {
058                return EMPTY_FIELD_VISITOR;
059            }
060            return visitor;
061        }
062    
063        @Override
064        @NotNull
065        public MethodVisitor newMethod(
066                @Nullable PsiElement origin,
067                int access,
068                @NotNull String name,
069                @NotNull String desc,
070                @Nullable String signature,
071                @Nullable String[] exceptions
072        ) {
073            MethodVisitor visitor = getVisitor().visitMethod(access, name, desc, signature, exceptions);
074            if (visitor == null) {
075                return EMPTY_METHOD_VISITOR;
076            }
077            return visitor;
078        }
079    
080        @Override
081        @NotNull
082        public JvmSerializationBindings getSerializationBindings() {
083            return serializationBindings;
084        }
085    
086        @Override
087        @NotNull
088        public AnnotationVisitor newAnnotation(@NotNull String desc, boolean visible) {
089            return getVisitor().visitAnnotation(desc, visible);
090        }
091    
092        @Override
093        public void done() {
094            getVisitor().visitEnd();
095        }
096    
097        @Override
098        public void defineClass(
099                @Nullable PsiElement origin,
100                int version,
101                int access,
102                @NotNull String name,
103                @Nullable String signature,
104                @NotNull String superName,
105                @NotNull String[] interfaces
106        ) {
107            thisName = name;
108            getVisitor().visit(version, access, name, signature, superName, interfaces);
109        }
110    
111        @Override
112        public void visitSource(@NotNull String name, @Nullable String debug) {
113            getVisitor().visitSource(name, debug);
114        }
115    
116        @Override
117        public void visitOuterClass(@NotNull String owner, @Nullable String name, @Nullable String desc) {
118            getVisitor().visitOuterClass(owner, name, desc);
119        }
120    
121        @Override
122        public void visitInnerClass(@NotNull String name, @Nullable String outerName, @Nullable String innerName, int access) {
123            getVisitor().visitInnerClass(name, outerName, innerName, access);
124        }
125    
126        @Override
127        @NotNull
128        public String getThisName() {
129            assert thisName != null : "This name isn't set";
130            return thisName;
131        }
132    }