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