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