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.lang.resolve.java.resolver;
018
019 import com.intellij.psi.PsiEllipsisType;
020 import com.intellij.psi.PsiType;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
024 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
025 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
026 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
027 import org.jetbrains.jet.lang.resolve.java.*;
028 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiParameterWrapper;
029 import org.jetbrains.jet.lang.resolve.name.Name;
030 import org.jetbrains.jet.lang.types.JetType;
031 import org.jetbrains.jet.lang.types.TypeUtils;
032 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
033
034 import javax.inject.Inject;
035 import java.util.ArrayList;
036 import java.util.Collections;
037 import java.util.List;
038
039 public final class JavaValueParameterResolver {
040
041 private JavaTypeTransformer typeTransformer;
042
043 public JavaValueParameterResolver() {
044 }
045
046 @NotNull
047 private JvmMethodParameterMeaning resolveParameterDescriptor(
048 DeclarationDescriptor containingDeclaration, int i,
049 PsiParameterWrapper parameter, TypeVariableResolver typeVariableResolver
050 ) {
051
052 if (parameter.getJetTypeParameter().isDefined()) {
053 return JvmMethodParameterMeaning.typeInfo();
054 }
055
056 PsiType psiType = parameter.getPsiParameter().getType();
057
058 // TODO: must be very slow, make it lazy?
059 Name name = Name.identifier(getParameterName(i, parameter));
060
061 if (parameter.getJetValueParameter().name().length() > 0) {
062 name = Name.identifier(parameter.getJetValueParameter().name());
063 }
064
065 String typeFromAnnotation = parameter.getJetValueParameter().type();
066 boolean receiver = parameter.getJetValueParameter().receiver();
067 boolean hasDefaultValue = parameter.getJetValueParameter().hasDefaultValue();
068
069 JetType outType;
070 if (typeFromAnnotation.length() > 0) {
071 outType = getTypeTransformer().transformToType(typeFromAnnotation, typeVariableResolver);
072 }
073 else {
074 TypeUsage typeUsage = JavaTypeTransformer.adjustTypeUsageWithMutabilityAnnotations(parameter.getPsiParameter(), TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT);
075 outType = getTypeTransformer().transformToType(psiType, typeUsage, typeVariableResolver);
076 }
077
078 JetType varargElementType;
079 if (psiType instanceof PsiEllipsisType || parameter.getJetValueParameter().vararg()) {
080 varargElementType = KotlinBuiltIns.getInstance().getArrayElementType(TypeUtils.makeNotNullable(outType));
081 outType = TypeUtils.makeNotNullable(outType);
082 }
083 else {
084 varargElementType = null;
085 }
086
087 if (receiver) {
088 return JvmMethodParameterMeaning.receiver(outType);
089 }
090 else {
091
092 JetType transformedType;
093 if (JavaAnnotationResolver.findAnnotationWithExternal(parameter.getPsiParameter(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().asString()) !=
094 null) {
095 transformedType = TypeUtils.makeNullableAsSpecified(outType, false);
096 }
097 else {
098 transformedType = outType;
099 }
100 return JvmMethodParameterMeaning.regular(new ValueParameterDescriptorImpl(
101 containingDeclaration,
102 i,
103 Collections.<AnnotationDescriptor>emptyList(), // TODO
104 name,
105 transformedType,
106 hasDefaultValue,
107 varargElementType
108 ));
109 }
110 }
111
112 @NotNull
113 private JavaTypeTransformer getTypeTransformer() {
114 return typeTransformer;
115 }
116
117 @Inject
118 public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
119 this.typeTransformer = typeTransformer;
120 }
121
122 @NotNull
123 private static String getParameterName(int number, @NotNull PsiParameterWrapper parameter) {
124 String psiParameterName = parameter.getPsiParameter().getName();
125 return psiParameterName != null ? psiParameterName : "p" + number;
126 }
127
128 public JavaDescriptorResolver.ValueParameterDescriptors resolveParameterDescriptors(
129 DeclarationDescriptor containingDeclaration,
130 List<PsiParameterWrapper> parameters, TypeVariableResolver typeVariableResolver
131 ) {
132 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
133 JetType receiverType = null;
134 int indexDelta = 0;
135 for (int i = 0, parametersLength = parameters.size(); i < parametersLength; i++) {
136 PsiParameterWrapper parameter = parameters.get(i);
137 JvmMethodParameterMeaning meaning =
138 resolveParameterDescriptor(containingDeclaration, i + indexDelta, parameter, typeVariableResolver);
139 if (meaning.kind == JvmMethodParameterKind.TYPE_INFO) {
140 // TODO
141 --indexDelta;
142 }
143 else if (meaning.kind == JvmMethodParameterKind.REGULAR) {
144 result.add(meaning.valueParameterDescriptor);
145 }
146 else if (meaning.kind == JvmMethodParameterKind.RECEIVER) {
147 if (receiverType != null) {
148 throw new IllegalStateException("more than one receiver");
149 }
150 --indexDelta;
151 receiverType = meaning.receiverType;
152 }
153 }
154 return new JavaDescriptorResolver.ValueParameterDescriptors(receiverType, result);
155 }
156
157 public enum JvmMethodParameterKind {
158 REGULAR,
159 RECEIVER,
160 TYPE_INFO,
161 }
162
163 public static class JvmMethodParameterMeaning {
164 public final JvmMethodParameterKind kind;
165 private final JetType receiverType;
166 private final ValueParameterDescriptor valueParameterDescriptor;
167
168 private JvmMethodParameterMeaning(
169 JvmMethodParameterKind kind,
170 @Nullable JetType receiverType,
171 @Nullable ValueParameterDescriptor valueParameterDescriptor
172 ) {
173 this.kind = kind;
174 this.receiverType = receiverType;
175 this.valueParameterDescriptor = valueParameterDescriptor;
176 }
177
178 public static JvmMethodParameterMeaning receiver(@NotNull JetType receiverType) {
179 return new JvmMethodParameterMeaning(JvmMethodParameterKind.RECEIVER, receiverType, null);
180 }
181
182 public static JvmMethodParameterMeaning regular(@NotNull ValueParameterDescriptor valueParameterDescriptor) {
183 return new JvmMethodParameterMeaning(JvmMethodParameterKind.REGULAR, null, valueParameterDescriptor);
184 }
185
186 public static JvmMethodParameterMeaning typeInfo() {
187 return new JvmMethodParameterMeaning(JvmMethodParameterKind.TYPE_INFO, null, null);
188 }
189 }
190 }