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.signature;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.kotlin.name.Name;
022    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature;
023    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
024    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
025    import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
026    import org.jetbrains.kotlin.types.Variance;
027    import org.jetbrains.org.objectweb.asm.Type;
028    import org.jetbrains.org.objectweb.asm.commons.Method;
029    
030    import java.util.ArrayList;
031    import java.util.List;
032    
033    public class JvmSignatureWriter {
034    
035        private final List<JvmMethodParameterSignature> kotlinParameterTypes = new ArrayList<JvmMethodParameterSignature>();
036    
037        private int jvmCurrentTypeArrayLevel;
038        private Type jvmCurrentType;
039        private Type jvmReturnType;
040    
041        private JvmMethodParameterKind currentParameterKind;
042    
043        private int currentSignatureSize = 0;
044    
045        /**
046         * Shortcut
047         */
048        public void writeAsmType(Type asmType) {
049            switch (asmType.getSort()) {
050                case Type.OBJECT:
051                    writeClassBegin(asmType);
052                    writeClassEnd();
053                    return;
054                case Type.ARRAY:
055                    writeArrayType();
056                    writeAsmType(asmType.getElementType());
057                    writeArrayEnd();
058                    return;
059                default:
060                    writeAsmType0(asmType);
061            }
062        }
063    
064        private String makeArrayPrefix() {
065            StringBuilder sb = new StringBuilder();
066            for (int i = 0; i < jvmCurrentTypeArrayLevel; ++i) {
067                sb.append('[');
068            }
069            return sb.toString();
070        }
071    
072        protected void writeAsmType0(Type type) {
073            if (jvmCurrentType == null) {
074                jvmCurrentType = Type.getType(makeArrayPrefix() + type.getDescriptor());
075            }
076        }
077    
078        public void writeClassBegin(Type asmType) {
079            writeAsmType0(asmType);
080        }
081    
082        public void writeOuterClassBegin(Type resultingAsmType, String outerInternalName) {
083            writeAsmType0(resultingAsmType);
084        }
085    
086        public void writeInnerClass(String name) {
087        }
088    
089        public void writeClassEnd() {
090        }
091    
092        public void writeArrayType() {
093            if (jvmCurrentType == null) {
094                ++jvmCurrentTypeArrayLevel;
095            }
096        }
097    
098        public void writeArrayEnd() {
099        }
100    
101        public void writeTypeArgument(@NotNull Variance projectionKind) {
102        }
103    
104        public void writeUnboundedWildcard() {
105        }
106    
107        public void writeTypeArgumentEnd() {
108        }
109    
110        public void writeTypeVariable(Name name, Type asmType) {
111            writeAsmType0(asmType);
112        }
113    
114        public void writeFormalTypeParameter(String name) {
115        }
116    
117        public void writeClassBound() {
118        }
119    
120        public void writeClassBoundEnd() {
121        }
122    
123        public void writeInterfaceBound() {
124        }
125    
126        public void writeInterfaceBoundEnd() {
127        }
128    
129        public void writeParametersStart() {
130            // hacks
131            jvmCurrentType = null;
132            jvmCurrentTypeArrayLevel = 0;
133        }
134    
135        public void writeParameterType(JvmMethodParameterKind parameterKind) {
136            currentParameterKind = parameterKind;
137        }
138    
139        public void writeParameterTypeEnd() {
140            kotlinParameterTypes.add(new JvmMethodParameterSignature(jvmCurrentType, currentParameterKind));
141            currentSignatureSize += jvmCurrentType.getSize();
142    
143            currentParameterKind = null;
144            jvmCurrentType = null;
145            jvmCurrentTypeArrayLevel = 0;
146        }
147    
148        public void writeReturnType() {
149        }
150    
151        public void writeReturnTypeEnd() {
152            jvmReturnType = jvmCurrentType;
153            jvmCurrentType = null;
154            jvmCurrentTypeArrayLevel = 0;
155        }
156    
157        public void writeSuperclass() {
158        }
159    
160        public void writeSuperclassEnd() {
161        }
162    
163        public void writeInterface() {
164        }
165    
166        public void writeInterfaceEnd() {
167        }
168    
169        @Nullable
170        public String makeJavaGenericSignature() {
171            return null;
172        }
173    
174        @NotNull
175        public JvmMethodGenericSignature makeJvmMethodSignature(@NotNull String name) {
176            List<Type> types = new ArrayList<Type>(kotlinParameterTypes.size());
177            for (JvmMethodParameterSignature parameter : kotlinParameterTypes) {
178                types.add(parameter.getAsmType());
179            }
180            Method asmMethod = new Method(name, jvmReturnType, types.toArray(new Type[types.size()]));
181            return new JvmMethodGenericSignature(asmMethod, kotlinParameterTypes, makeJavaGenericSignature());
182        }
183    
184        public int getCurrentSignatureSize() {
185            return currentSignatureSize;
186        }
187    
188        public boolean skipGenericSignature() {
189            return true;
190        }
191    
192        @Override
193        public String toString() {
194            return "empty";
195        }
196    }
197