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.lang.resolve.java.resolver; 018 019import com.intellij.psi.PsiEllipsisType; 020import com.intellij.psi.PsiType; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; 024import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; 025import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; 026import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 027import org.jetbrains.jet.lang.resolve.java.*; 028import org.jetbrains.jet.lang.resolve.java.wrapper.PsiParameterWrapper; 029import org.jetbrains.jet.lang.resolve.name.Name; 030import org.jetbrains.jet.lang.types.JetType; 031import org.jetbrains.jet.lang.types.TypeUtils; 032import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 033 034import javax.inject.Inject; 035import java.util.ArrayList; 036import java.util.Collections; 037import java.util.List; 038 039public 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}