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 kotlin.Unit;
020    import kotlin.jvm.functions.Function1;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
024    import org.jetbrains.kotlin.descriptors.*;
025    import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
026    import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
028    import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
029    import org.jetbrains.kotlin.resolve.scopes.*;
030    import org.jetbrains.kotlin.types.*;
031    import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
032    
033    import java.util.ArrayList;
034    import java.util.Collections;
035    import java.util.List;
036    
037    public class FunctionDescriptorUtil {
038        private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitution() {
039    
040            @Override
041            public TypeProjection get(@NotNull KotlinType key) {
042                return null;
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 TypeSubstitution createSubstitution(
055                @NotNull FunctionDescriptor functionDescriptor,
056                @NotNull List<KotlinType> typeArguments
057        ) {
058            if (functionDescriptor.getTypeParameters().isEmpty()) return TypeSubstitution.EMPTY;
059    
060            return new IndexedParametersSubstitution(functionDescriptor.getTypeParameters(), TypeUtilsKt.defaultProjections(typeArguments));
061        }
062    
063        @NotNull
064        public static LexicalScope getFunctionInnerScope(@NotNull LexicalScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
065            TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace);
066            return getFunctionInnerScope(outerScope, descriptor, redeclarationHandler);
067        }
068    
069        @NotNull
070        public static LexicalScope getFunctionInnerScope(
071                @NotNull LexicalScope outerScope,
072                @NotNull final FunctionDescriptor descriptor,
073                @NotNull RedeclarationHandler redeclarationHandler
074        ) {
075            ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
076            return new LexicalScopeImpl(outerScope, descriptor, true, receiver, LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationHandler,
077                                        new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
078                                            @Override
079                                            public Unit invoke(LexicalScopeImpl.InitializeHandler handler) {
080                                                for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
081                                                    handler.addClassifierDescriptor(typeParameter);
082                                                }
083                                                for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
084                                                    handler.addVariableDescriptor(valueParameterDescriptor);
085                                                }
086                                                return Unit.INSTANCE;
087                                            }
088                                        });
089        }
090    
091        public static void initializeFromFunctionType(
092                @NotNull FunctionDescriptorImpl functionDescriptor,
093                @NotNull KotlinType functionType,
094                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
095                @NotNull Modality modality,
096                @NotNull Visibility visibility
097        ) {
098    
099            assert KotlinBuiltIns.isFunctionOrExtensionFunctionType(functionType);
100            functionDescriptor.initialize(KotlinBuiltIns.getReceiverType(functionType),
101                                          dispatchReceiverParameter,
102                                          Collections.<TypeParameterDescriptorImpl>emptyList(),
103                                          KotlinBuiltIns.getValueParameters(functionDescriptor, functionType),
104                                          KotlinBuiltIns.getReturnTypeFromFunctionType(functionType),
105                                          modality,
106                                          visibility);
107        }
108    
109        public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
110            return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
111        }
112    
113        /**
114         * Returns function's copy with new parameter list. Note that parameters may belong to other methods or have incorrect "index" property
115         * -- it will be fixed by this function.
116         */
117        @NotNull
118        public static FunctionDescriptor replaceFunctionParameters(
119                @NotNull FunctionDescriptor function,
120                @NotNull List<ValueParameterDescriptor> newParameters
121        ) {
122            FunctionDescriptorImpl descriptor = SimpleFunctionDescriptorImpl.create(
123                    function.getContainingDeclaration(),
124                    function.getAnnotations(),
125                    function.getName(),
126                    function.getKind(),
127                    SourceElement.NO_SOURCE
128            );
129            List<ValueParameterDescriptor> parameters = new ArrayList<ValueParameterDescriptor>(newParameters.size());
130            int idx = 0;
131            for (ValueParameterDescriptor parameter : newParameters) {
132                KotlinType returnType = parameter.getReturnType();
133                assert returnType != null;
134    
135                parameters.add(
136                        new ValueParameterDescriptorImpl(
137                                descriptor,
138                                null,
139                                idx,
140                                parameter.getAnnotations(),
141                                parameter.getName(),
142                                returnType,
143                                parameter.declaresDefaultValue(),
144                                parameter.isCrossinline(),
145                                parameter.isNoinline(),
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            descriptor.setOperator(function.isOperator());
162            descriptor.setInfix(function.isInfix());
163            descriptor.setExternal(function.isExternal());
164            descriptor.setInline(function.isInline());
165            descriptor.setTailrec(function.isTailrec());
166            return descriptor;
167        }
168    }