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            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(new ValueParameterDescriptorImpl(
133                        descriptor,
134                        null,
135                        idx,
136                        parameter.getAnnotations(),
137                        parameter.getName(),
138                        returnType,
139                        parameter.declaresDefaultValue(),
140                        parameter.getVarargElementType())
141                );
142                idx++;
143            }
144            ReceiverParameterDescriptor receiver = function.getReceiverParameter();
145            descriptor.initialize(
146                    receiver == null ? null : receiver.getType(),
147                    function.getExpectedThisObject(),
148                    function.getTypeParameters(),
149                    parameters,
150                    function.getReturnType(),
151                    function.getModality(),
152                    function.getVisibility());
153            return descriptor;
154        }
155    }