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.descriptors.impl;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.resolve.BindingTrace;
023 import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler;
024 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
025 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
026 import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
027 import org.jetbrains.jet.lang.types.*;
028 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
029
030 import java.util.*;
031
032 public class FunctionDescriptorUtil {
033 private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitution() {
034
035 @Override
036 public TypeProjection get(TypeConstructor key) {
037 return null;
038 }
039
040 @Override
041 public boolean isEmpty() {
042 return false;
043 }
044
045 @Override
046 public String toString() {
047 return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH";
048 }
049 });
050
051 private FunctionDescriptorUtil() {
052 }
053
054 public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
055 if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
056
057 Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
058
059 int typeArgumentsSize = typeArguments.size();
060 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
061 assert typeArgumentsSize == typeParameters.size();
062 for (int i = 0; i < typeArgumentsSize; i++) {
063 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
064 JetType typeArgument = typeArguments.get(i);
065 result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument));
066 }
067 return result;
068 }
069
070 @Nullable
071 public static List<ValueParameterDescriptor> getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) {
072 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>();
073 List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters();
074 for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
075 // TODO : Lazy?
076 JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
077 JetType varargElementType = unsubstitutedValueParameter.getVarargElementType();
078 JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
079 if (substitutedType == null) return null;
080 result.add(new ValueParameterDescriptorImpl(
081 substitutedDescriptor,
082 unsubstitutedValueParameter,
083 unsubstitutedValueParameter.getAnnotations(),
084 substitutedType,
085 substituteVarargElementType
086 ));
087 }
088 return result;
089 }
090
091 @Nullable
092 public static JetType getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) {
093 return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE);
094 }
095
096 @Nullable
097 public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) {
098 Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments);
099 return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext));
100 }
101
102 @NotNull
103 public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
104 WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace), "Function inner scope");
105 ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter();
106 if (receiver != null) {
107 parameterScope.setImplicitReceiver(receiver);
108 }
109 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
110 parameterScope.addTypeParameterDescriptor(typeParameter);
111 }
112 for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
113 parameterScope.addVariableDescriptor(valueParameterDescriptor);
114 }
115 parameterScope.addLabeledDeclaration(descriptor);
116 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
117 return parameterScope;
118 }
119
120 public static void initializeFromFunctionType(
121 @NotNull FunctionDescriptorImpl functionDescriptor,
122 @NotNull JetType functionType,
123 @Nullable ReceiverParameterDescriptor expectedThisObject,
124 @NotNull Modality modality,
125 @NotNull Visibility visibility
126 ) {
127
128 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType);
129 functionDescriptor.initialize(KotlinBuiltIns.getInstance().getReceiverType(functionType),
130 expectedThisObject,
131 Collections.<TypeParameterDescriptorImpl>emptyList(),
132 KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, functionType),
133 KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(functionType),
134 modality,
135 visibility);
136 }
137
138 public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
139 return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
140 }
141
142 /**
143 * Returns function's copy with new parameter list. Note that parameters may belong to other methods or have incorrect "index" property
144 * -- it will be fixed by this function.
145 */
146 @NotNull
147 public static FunctionDescriptor replaceFunctionParameters(
148 @NotNull FunctionDescriptor function,
149 @NotNull List<ValueParameterDescriptor> newParameters
150 ) {
151 FunctionDescriptorImpl descriptor = new SimpleFunctionDescriptorImpl(
152 function.getContainingDeclaration(),
153 function.getAnnotations(),
154 function.getName(),
155 function.getKind());
156 List<ValueParameterDescriptor> parameters = new ArrayList<ValueParameterDescriptor>(newParameters.size());
157 int idx = 0;
158 for (ValueParameterDescriptor parameter : newParameters) {
159 JetType returnType = parameter.getReturnType();
160 assert returnType != null;
161
162 parameters.add(new ValueParameterDescriptorImpl(
163 descriptor,
164 idx,
165 parameter.getAnnotations(),
166 parameter.getName(),
167 returnType,
168 parameter.declaresDefaultValue(),
169 parameter.getVarargElementType())
170 );
171 idx++;
172 }
173 ReceiverParameterDescriptor receiver = function.getReceiverParameter();
174 descriptor.initialize(
175 receiver == null ? null : receiver.getType(),
176 function.getExpectedThisObject(),
177 function.getTypeParameters(),
178 parameters,
179 function.getReturnType(),
180 function.getModality(),
181 function.getVisibility());
182 return descriptor;
183 }
184 }