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 017package org.jetbrains.jet.lang.descriptors.impl; 018 019import org.jetbrains.annotations.NotNull; 020import org.jetbrains.annotations.Nullable; 021import org.jetbrains.jet.lang.descriptors.*; 022import org.jetbrains.jet.lang.resolve.BindingTrace; 023import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; 024import org.jetbrains.jet.lang.resolve.scopes.JetScope; 025import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 026import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; 027import org.jetbrains.jet.lang.types.*; 028import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 029 030import java.util.*; 031 032public class FunctionDescriptorUtil { 033 private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitution() { 034 035 @Override 036 public TypeProjection get(TypeConstructor key) { 037 return null; 038 } 039 040 @Override 041 public boolean isEmpty() { 042 return false; 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 Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) { 055 if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap(); 056 057 Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>(); 058 059 int typeArgumentsSize = typeArguments.size(); 060 List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters(); 061 assert typeArgumentsSize == typeParameters.size(); 062 for (int i = 0; i < typeArgumentsSize; i++) { 063 TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); 064 JetType typeArgument = typeArguments.get(i); 065 result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument)); 066 } 067 return result; 068 } 069 070 @Nullable 071 public static List<ValueParameterDescriptor> getSubstitutedValueParameters(FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) { 072 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(); 073 List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters(); 074 for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) { 075 // TODO : Lazy? 076 JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE); 077 JetType varargElementType = unsubstitutedValueParameter.getVarargElementType(); 078 JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE); 079 if (substitutedType == null) return null; 080 result.add(new ValueParameterDescriptorImpl( 081 substitutedDescriptor, 082 unsubstitutedValueParameter, 083 unsubstitutedValueParameter.getAnnotations(), 084 substitutedType, 085 substituteVarargElementType 086 )); 087 } 088 return result; 089 } 090 091 @Nullable 092 public static JetType getSubstitutedReturnType(@NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) { 093 return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE); 094 } 095 096 @Nullable 097 public static FunctionDescriptor substituteFunctionDescriptor(@NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) { 098 Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments); 099 return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext)); 100 } 101 102 @NotNull 103 public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { 104 WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace), "Function inner scope"); 105 ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter(); 106 if (receiver != null) { 107 parameterScope.setImplicitReceiver(receiver); 108 } 109 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { 110 parameterScope.addTypeParameterDescriptor(typeParameter); 111 } 112 for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) { 113 parameterScope.addVariableDescriptor(valueParameterDescriptor); 114 } 115 parameterScope.addLabeledDeclaration(descriptor); 116 parameterScope.changeLockLevel(WritableScope.LockLevel.READING); 117 return parameterScope; 118 } 119 120 public static void initializeFromFunctionType( 121 @NotNull FunctionDescriptorImpl functionDescriptor, 122 @NotNull JetType functionType, 123 @Nullable ReceiverParameterDescriptor expectedThisObject, 124 @NotNull Modality modality, 125 @NotNull Visibility visibility 126 ) { 127 128 assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType); 129 functionDescriptor.initialize(KotlinBuiltIns.getInstance().getReceiverType(functionType), 130 expectedThisObject, 131 Collections.<TypeParameterDescriptorImpl>emptyList(), 132 KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, functionType), 133 KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(functionType), 134 modality, 135 visibility); 136 } 137 138 public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) { 139 return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH); 140 } 141 142 /** 143 * Returns function's copy with new parameter list. Note that parameters may belong to other methods or have incorrect "index" property 144 * -- it will be fixed by this function. 145 */ 146 @NotNull 147 public static FunctionDescriptor replaceFunctionParameters( 148 @NotNull FunctionDescriptor function, 149 @NotNull List<ValueParameterDescriptor> newParameters 150 ) { 151 FunctionDescriptorImpl descriptor = new SimpleFunctionDescriptorImpl( 152 function.getContainingDeclaration(), 153 function.getAnnotations(), 154 function.getName(), 155 function.getKind()); 156 List<ValueParameterDescriptor> parameters = new ArrayList<ValueParameterDescriptor>(newParameters.size()); 157 int idx = 0; 158 for (ValueParameterDescriptor parameter : newParameters) { 159 JetType returnType = parameter.getReturnType(); 160 assert returnType != null; 161 162 parameters.add(new ValueParameterDescriptorImpl( 163 descriptor, 164 idx, 165 parameter.getAnnotations(), 166 parameter.getName(), 167 returnType, 168 parameter.declaresDefaultValue(), 169 parameter.getVarargElementType()) 170 ); 171 idx++; 172 } 173 ReceiverParameterDescriptor receiver = function.getReceiverParameter(); 174 descriptor.initialize( 175 receiver == null ? null : receiver.getType(), 176 function.getExpectedThisObject(), 177 function.getTypeParameters(), 178 parameters, 179 function.getReturnType(), 180 function.getModality(), 181 function.getVisibility()); 182 return descriptor; 183 } 184}