001    /*
002     * Copyright 2010-2016 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.kotlin.descriptors.*;
023    import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
024    import org.jetbrains.kotlin.resolve.scopes.*;
025    import org.jetbrains.kotlin.types.*;
026    import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
027    
028    import java.util.List;
029    
030    public class FunctionDescriptorUtil {
031        private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitution() {
032            @Override
033            public TypeProjection get(@NotNull KotlinType key) {
034                return null;
035            }
036    
037            @Override
038            public String toString() {
039                return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH";
040            }
041        });
042    
043        private FunctionDescriptorUtil() {
044        }
045    
046        public static TypeSubstitution createSubstitution(
047                @NotNull FunctionDescriptor functionDescriptor,
048                @NotNull List<KotlinType> typeArguments
049        ) {
050            if (functionDescriptor.getTypeParameters().isEmpty()) return TypeSubstitution.EMPTY;
051    
052            return new IndexedParametersSubstitution(functionDescriptor.getTypeParameters(), TypeUtilsKt.defaultProjections(typeArguments));
053        }
054    
055        @NotNull
056        public static LexicalScope getFunctionInnerScope(
057                @NotNull LexicalScope outerScope, @NotNull FunctionDescriptor descriptor,
058                @NotNull BindingTrace trace, @NotNull OverloadChecker overloadChecker
059        ) {
060            return getFunctionInnerScope(outerScope, descriptor, new TraceBasedLocalRedeclarationChecker(trace, overloadChecker));
061        }
062    
063        @NotNull
064        public static LexicalScope getFunctionInnerScope(
065                @NotNull LexicalScope outerScope,
066                @NotNull final FunctionDescriptor descriptor,
067                @NotNull LocalRedeclarationChecker redeclarationChecker
068        ) {
069            ReceiverParameterDescriptor receiver = descriptor.getExtensionReceiverParameter();
070    
071            return new LexicalScopeImpl(outerScope, descriptor, true, receiver, LexicalScopeKind.FUNCTION_INNER_SCOPE, redeclarationChecker,
072                                        new Function1<LexicalScopeImpl.InitializeHandler, Unit>() {
073                                            @Override
074                                            public Unit invoke(LexicalScopeImpl.InitializeHandler handler) {
075                                                for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
076                                                    handler.addClassifierDescriptor(typeParameter);
077                                                }
078                                                for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
079                                                    if (valueParameterDescriptor instanceof ValueParameterDescriptorImpl.WithDestructuringDeclaration) {
080                                                        List<VariableDescriptor> entries =
081                                                                ((ValueParameterDescriptorImpl.WithDestructuringDeclaration) valueParameterDescriptor)
082                                                                        .getDestructuringVariables();
083                                                        for (VariableDescriptor entry : entries) {
084                                                            handler.addVariableDescriptor(entry);
085                                                        }
086                                                    }
087                                                    else {
088                                                        handler.addVariableDescriptor(valueParameterDescriptor);
089                                                    }
090                                                }
091                                                return Unit.INSTANCE;
092                                            }
093                                        });
094        }
095    
096        @SuppressWarnings("unchecked")
097        public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
098            return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
099        }
100    }