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 org.jetbrains.annotations.NotNull;
020 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
021 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
022 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
023 import org.jetbrains.jet.lang.resolve.java.structure.JavaArrayType;
024 import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
025 import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
026 import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter;
027 import org.jetbrains.jet.lang.resolve.name.Name;
028 import org.jetbrains.jet.lang.types.JetType;
029 import org.jetbrains.jet.lang.types.TypeUtils;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031
032 import javax.inject.Inject;
033 import java.util.ArrayList;
034 import java.util.List;
035
036 public final class JavaValueParameterResolver {
037 private JavaAnnotationResolver annotationResolver;
038 private JavaTypeTransformer typeTransformer;
039
040 @Inject
041 public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
042 this.annotationResolver = annotationResolver;
043 }
044
045 @Inject
046 public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
047 this.typeTransformer = typeTransformer;
048 }
049
050 @NotNull
051 private ValueParameterDescriptor resolveValueParameter(
052 @NotNull DeclarationDescriptor containingDeclaration,
053 int i,
054 @NotNull JavaValueParameter parameter,
055 @NotNull TypeVariableResolver typeVariableResolver
056 ) {
057 TypeUsage typeUsage = annotationResolver.hasMutableAnnotation(parameter)
058 ? TypeUsage.MEMBER_SIGNATURE_COVARIANT
059 : TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT;
060
061 JavaType parameterType = parameter.getType();
062
063 JetType varargElementType;
064 JetType outType;
065 if (parameter.isVararg()) {
066 // TODO: test this code
067 assert parameterType instanceof JavaArrayType : "Vararg parameter should be an array: " + parameterType;
068 JetType arrayType = typeTransformer.transformVarargType(((JavaArrayType) parameterType), typeUsage, typeVariableResolver);
069
070 outType = TypeUtils.makeNotNullable(arrayType);
071 varargElementType = KotlinBuiltIns.getInstance().getArrayElementType(outType);
072 }
073 else {
074 JetType transformedType = typeTransformer.transformToType(parameterType, typeUsage, typeVariableResolver);
075 if (transformedType.isNullable() && annotationResolver.hasNotNullAnnotation(parameter)) {
076 transformedType = TypeUtils.makeNotNullable(transformedType);
077 }
078
079 outType = transformedType;
080 varargElementType = null;
081 }
082
083 return new ValueParameterDescriptorImpl(
084 containingDeclaration,
085 i,
086 annotationResolver.resolveAnnotations(parameter),
087 getParameterName(i, parameter), // TODO: must be very slow, make it lazy?
088 outType,
089 false,
090 varargElementType
091 );
092 }
093
094 @NotNull
095 private static Name getParameterName(int number, @NotNull JavaValueParameter parameter) {
096 Name psiParameterName = parameter.getName();
097 return psiParameterName != null ? psiParameterName : Name.identifier("p" + number);
098 }
099
100 @NotNull
101 public List<ValueParameterDescriptor> resolveValueParameters(
102 @NotNull DeclarationDescriptor container,
103 @NotNull JavaMethod method,
104 @NotNull TypeVariableResolver typeVariableResolver
105 ) {
106 List<JavaValueParameter> parameters = method.getValueParameters();
107 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(parameters.size());
108 for (int i = 0, size = parameters.size(); i < size; i++) {
109 result.add(resolveValueParameter(container, i, parameters.get(i), typeVariableResolver));
110 }
111 return result;
112 }
113 }