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.TypeUtilPackage;
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 JetType 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<JetType> typeArguments
057        ) {
058            if (functionDescriptor.getTypeParameters().isEmpty()) return TypeSubstitution.getEMPTY();
059    
060            return new IndexedParametersSubstitution(functionDescriptor.getTypeParameters(), TypeUtilPackage.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, "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 JetType 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                                          false);
108        }
109    
110        public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
111            return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
112        }
113    
114        /**
115         * Returns function's copy with new parameter list. Note that parameters may belong to other methods or have incorrect "index" property
116         * -- it will be fixed by this function.
117         */
118        @NotNull
119        public static FunctionDescriptor replaceFunctionParameters(
120                @NotNull FunctionDescriptor function,
121                @NotNull List<ValueParameterDescriptor> newParameters
122        ) {
123            FunctionDescriptorImpl descriptor = SimpleFunctionDescriptorImpl.create(
124                    function.getContainingDeclaration(),
125                    function.getAnnotations(),
126                    function.getName(),
127                    function.getKind(),
128                    SourceElement.NO_SOURCE
129            );
130            List<ValueParameterDescriptor> parameters = new ArrayList<ValueParameterDescriptor>(newParameters.size());
131            int idx = 0;
132            for (ValueParameterDescriptor parameter : newParameters) {
133                JetType returnType = parameter.getReturnType();
134                assert returnType != null;
135    
136                parameters.add(
137                        new ValueParameterDescriptorImpl(
138                                descriptor,
139                                null,
140                                idx,
141                                parameter.getAnnotations(),
142                                parameter.getName(),
143                                returnType,
144                                parameter.declaresDefaultValue(),
145                                parameter.getVarargElementType(),
146                                SourceElement.NO_SOURCE
147                        )
148                );
149                idx++;
150            }
151            ReceiverParameterDescriptor receiver = function.getExtensionReceiverParameter();
152            descriptor.initialize(
153                    receiver == null ? null : receiver.getType(),
154                    function.getDispatchReceiverParameter(),
155                    function.getTypeParameters(),
156                    parameters,
157                    function.getReturnType(),
158                    function.getModality(),
159                    function.getVisibility(),
160                    function.isOperator());
161            return descriptor;
162        }
163    }