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