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