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
017package org.jetbrains.jet.codegen.signature;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.asm4.Type;
022import org.jetbrains.asm4.commons.Method;
023
024import java.util.ArrayList;
025import java.util.List;
026
027public class JvmMethodSignature {
028
029    @NotNull
030    private final Method asmMethod;
031    /**
032     * Null when we don't care about type parameters
033     */
034    private final String genericsSignature;
035    private final String kotlinTypeParameter;
036    @NotNull
037    private final List<JvmMethodParameterSignature> kotlinParameterTypes;
038    @NotNull
039    private final String kotlinReturnType;
040
041    /**
042     * Generics info is generated. However it can be trivial (e.g. fields are null).
043     */
044    private final boolean genericsAvailable;
045
046    protected JvmMethodSignature(
047            @NotNull Method asmMethod,
048            @Nullable String genericsSignature,
049            @Nullable String kotlinTypeParameters,
050            @NotNull List<JvmMethodParameterSignature> kotlinParameterTypes,
051            @NotNull String kotlinReturnType,
052            boolean genericsAvailable
053    ) {
054        this.asmMethod = asmMethod;
055        this.genericsSignature = genericsSignature;
056        this.kotlinTypeParameter = kotlinTypeParameters;
057        this.kotlinParameterTypes = kotlinParameterTypes;
058        this.kotlinReturnType = kotlinReturnType;
059        this.genericsAvailable = genericsAvailable;
060    }
061
062    @NotNull
063    private static List<Type> getTypes(@NotNull List<JvmMethodParameterSignature> signatures) {
064        List<Type> r = new ArrayList<Type>(signatures.size());
065        for (JvmMethodParameterSignature signature : signatures) {
066            r.add(signature.getAsmType());
067        }
068        return r;
069    }
070
071    private void checkGenericsAvailable() {
072        if (!genericsAvailable) {
073            // TODO: uncomment following line and fix all broken tests
074            //throw new IllegalStateException("incorrect call sequence");
075        }
076    }
077
078    @NotNull
079    public Method getAsmMethod() {
080        return asmMethod;
081    }
082
083    public String getGenericsSignature() {
084        checkGenericsAvailable();
085        return genericsSignature;
086    }
087
088    public String getKotlinTypeParameter() {
089        checkGenericsAvailable();
090        return kotlinTypeParameter;
091    }
092
093    @NotNull
094    public List<JvmMethodParameterSignature> getKotlinParameterTypes() {
095        checkGenericsAvailable();
096        return kotlinParameterTypes;
097    }
098
099    public int getParameterCount() {
100        // TODO: slow
101        return asmMethod.getArgumentTypes().length;
102    }
103
104    @NotNull
105    public String getKotlinParameterType(int i) {
106        checkGenericsAvailable();
107        return kotlinParameterTypes.get(i).getKotlinSignature();
108    }
109
110    @NotNull
111    public String getKotlinReturnType() {
112        checkGenericsAvailable();
113        return kotlinReturnType;
114    }
115
116    public List<Type> getValueParameterTypes() {
117        List<Type> r = new ArrayList<Type>(kotlinParameterTypes.size());
118        for (JvmMethodParameterSignature p : kotlinParameterTypes) {
119            if (p.getKind() == JvmMethodParameterKind.VALUE) {
120                r.add(p.getAsmType());
121            }
122        }
123        return r;
124    }
125
126    @NotNull
127    public String getName() {
128        return asmMethod.getName();
129    }
130
131    @Override
132    public String toString() {
133        return asmMethod.toString();
134    }
135}