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(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
057 if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
058
059 Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>();
060
061 int typeArgumentsSize = typeArguments.size();
062 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
063 assert typeArgumentsSize == typeParameters.size();
064 for (int i = 0; i < typeArgumentsSize; i++) {
065 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
066 JetType typeArgument = typeArguments.get(i);
067 result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjectionImpl(typeArgument));
068 }
069 return result;
070 }
071
072 @NotNull
073 public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
074 WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace), "Function inner scope");
075 ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter();
076 if (receiver != null) {
077 parameterScope.setImplicitReceiver(receiver);
078 }
079 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
080 parameterScope.addTypeParameterDescriptor(typeParameter);
081 }
082 for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
083 parameterScope.addVariableDescriptor(valueParameterDescriptor);
084 }
085 parameterScope.addLabeledDeclaration(descriptor);
086 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
087 return parameterScope;
088 }
089
090 public static void initializeFromFunctionType(
091 @NotNull FunctionDescriptorImpl functionDescriptor,
092 @NotNull JetType functionType,
093 @Nullable ReceiverParameterDescriptor expectedThisObject,
094 @NotNull Modality modality,
095 @NotNull Visibility visibility
096 ) {
097
098 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType);
099 functionDescriptor.initialize(KotlinBuiltIns.getInstance().getReceiverType(functionType),
100 expectedThisObject,
101 Collections.<TypeParameterDescriptorImpl>emptyList(),
102 KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, functionType),
103 KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(functionType),
104 modality,
105 visibility);
106 }
107
108 public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
109 return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
110 }
111
112 /**
113 * Returns function's copy with new parameter list. Note that parameters may belong to other methods or have incorrect "index" property
114 * -- it will be fixed by this function.
115 */
116 @NotNull
117 public static FunctionDescriptor replaceFunctionParameters(
118 @NotNull FunctionDescriptor function,
119 @NotNull List<ValueParameterDescriptor> newParameters
120 ) {
121 FunctionDescriptorImpl descriptor = SimpleFunctionDescriptorImpl.create(
122 function.getContainingDeclaration(),
123 function.getAnnotations(),
124 function.getName(),
125 function.getKind(),
126 SourceElement.NO_SOURCE
127 );
128 List<ValueParameterDescriptor> parameters = new ArrayList<ValueParameterDescriptor>(newParameters.size());
129 int idx = 0;
130 for (ValueParameterDescriptor parameter : newParameters) {
131 JetType returnType = parameter.getReturnType();
132 assert returnType != null;
133
134 parameters.add(
135 new ValueParameterDescriptorImpl(
136 descriptor,
137 null,
138 idx,
139 parameter.getAnnotations(),
140 parameter.getName(),
141 returnType,
142 parameter.declaresDefaultValue(),
143 parameter.getVarargElementType(),
144 SourceElement.NO_SOURCE
145 )
146 );
147 idx++;
148 }
149 ReceiverParameterDescriptor receiver = function.getReceiverParameter();
150 descriptor.initialize(
151 receiver == null ? null : receiver.getType(),
152 function.getExpectedThisObject(),
153 function.getTypeParameters(),
154 parameters,
155 function.getReturnType(),
156 function.getModality(),
157 function.getVisibility());
158 return descriptor;
159 }
160 }