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.resolve.java.sam; 018 019import com.google.common.collect.Lists; 020import org.jetbrains.annotations.NotNull; 021import org.jetbrains.annotations.Nullable; 022import org.jetbrains.jet.lang.descriptors.*; 023import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 024import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl; 025import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl; 026import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; 027import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; 028import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; 029import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; 030import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil; 031import org.jetbrains.jet.lang.resolve.name.Name; 032import org.jetbrains.jet.lang.types.*; 033import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 034 035import java.util.Arrays; 036import java.util.Collections; 037import java.util.List; 038import java.util.Map; 039 040import static org.jetbrains.jet.lang.types.Variance.INVARIANT; 041 042public class SingleAbstractMethodUtils { 043 044 @NotNull 045 public static List<CallableMemberDescriptor> getAbstractMembers(@NotNull JetType type) { 046 List<CallableMemberDescriptor> abstractMembers = Lists.newArrayList(); 047 for (DeclarationDescriptor member : type.getMemberScope().getAllDescriptors()) { 048 if (member instanceof CallableMemberDescriptor && 049 ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT && 050 !CallResolverUtil.isOrOverridesSynthesized((CallableMemberDescriptor) member)) { 051 abstractMembers.add((CallableMemberDescriptor) member); 052 } 053 } 054 return abstractMembers; 055 } 056 057 private static JetType fixProjections(@NotNull JetType functionType) { 058 //removes redundant projection kinds and detects conflicts 059 060 List<TypeProjection> arguments = Lists.newArrayList(); 061 for (TypeParameterDescriptor typeParameter : functionType.getConstructor().getParameters()) { 062 Variance variance = typeParameter.getVariance(); 063 TypeProjection argument = functionType.getArguments().get(typeParameter.getIndex()); 064 Variance kind = argument.getProjectionKind(); 065 if (kind != INVARIANT && variance != INVARIANT) { 066 if (kind == variance) { 067 arguments.add(new TypeProjection(argument.getType())); 068 } 069 else { 070 return null; 071 } 072 } 073 else { 074 arguments.add(argument); 075 } 076 } 077 ClassifierDescriptor classifier = functionType.getConstructor().getDeclarationDescriptor(); 078 assert classifier instanceof ClassDescriptor : "Not class: " + classifier; 079 return new JetTypeImpl( 080 functionType.getAnnotations(), 081 functionType.getConstructor(), 082 functionType.isNullable(), 083 arguments, 084 ((ClassDescriptor) classifier).getMemberScope(arguments) 085 ); 086 } 087 088 @Nullable 089 private static JetType getFunctionTypeForSamType(@NotNull JetType samType) { 090 // e.g. samType == Comparator<String>? 091 092 ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor(); 093 if (classifier instanceof ClassDescriptorFromJvmBytecode) { 094 // Function2<T, T, Int> 095 JetType functionTypeDefault = ((ClassDescriptorFromJvmBytecode) classifier).getFunctionTypeForSamInterface(); 096 097 if (functionTypeDefault != null) { 098 // Function2<String, String, Int>? 099 JetType substitute = TypeSubstitutor.create(samType).substitute(functionTypeDefault, Variance.INVARIANT); 100 101 return substitute == null ? null : fixProjections(TypeUtils.makeNullableAsSpecified(substitute, samType.isNullable())); 102 } 103 } 104 return null; 105 } 106 107 @NotNull 108 public static JetType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) { 109 JetType returnType = function.getReturnType(); 110 assert returnType != null : "function is not initialized: " + function; 111 List<JetType> parameterTypes = Lists.newArrayList(); 112 for (ValueParameterDescriptor parameter : function.getValueParameters()) { 113 parameterTypes.add(parameter.getType()); 114 } 115 return KotlinBuiltIns.getInstance().getFunctionType( 116 Collections.<AnnotationDescriptor>emptyList(), null, parameterTypes, returnType); 117 } 118 119 private static boolean isSamInterface(@NotNull ClassDescriptor klass) { 120 if (klass.getKind() != ClassKind.TRAIT) { 121 return false; 122 } 123 124 List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType()); 125 if (abstractMembers.size() == 1) { 126 CallableMemberDescriptor member = abstractMembers.get(0); 127 if (member instanceof SimpleFunctionDescriptor) { 128 return member.getTypeParameters().isEmpty(); 129 } 130 } 131 return false; 132 } 133 134 @NotNull 135 public static SimpleFunctionDescriptor createSamConstructorFunction( 136 @NotNull ClassOrNamespaceDescriptor owner, 137 @NotNull ClassDescriptor samInterface 138 ) { 139 assert isSamInterface(samInterface) : samInterface; 140 141 SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl( 142 owner, 143 samInterface.getAnnotations(), 144 samInterface.getName(), 145 CallableMemberDescriptor.Kind.SYNTHESIZED 146 ); 147 148 TypeParameters typeParameters = recreateAndInitializeTypeParameters(samInterface.getTypeConstructor().getParameters(), result); 149 150 JetType parameterTypeUnsubstituted = getFunctionTypeForSamType(samInterface.getDefaultType()); 151 assert parameterTypeUnsubstituted != null : "couldn't get function type for SAM type " + samInterface.getDefaultType(); 152 JetType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE); 153 assert parameterType != null : "couldn't substitute type: " + parameterType + ", substitutor = " + typeParameters.substitutor; 154 ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl( 155 result, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("function"), parameterType, false, null); 156 157 JetType returnType = typeParameters.substitutor.substitute(samInterface.getDefaultType(), Variance.OUT_VARIANCE); 158 assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor; 159 160 result.initialize( 161 null, 162 null, 163 typeParameters.descriptors, 164 Arrays.asList(parameter), 165 returnType, 166 Modality.FINAL, 167 samInterface.getVisibility(), 168 false 169 ); 170 171 return result; 172 } 173 174 public static boolean isSamType(@NotNull JetType type) { 175 return getFunctionTypeForSamType(type) != null; 176 } 177 178 public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) { 179 for (ValueParameterDescriptor param : fun.getValueParameters()) { 180 if (isSamType(param.getType())) { 181 return true; 182 } 183 } 184 return false; 185 } 186 187 @NotNull 188 public static SimpleFunctionDescriptor createSamAdapterFunction(@NotNull final SimpleFunctionDescriptor original) { 189 final SimpleFunctionDescriptorImpl result = new SimpleFunctionDescriptorImpl( 190 original.getContainingDeclaration(), 191 original.getAnnotations(), 192 original.getName(), 193 CallableMemberDescriptor.Kind.SYNTHESIZED 194 ); 195 FunctionInitializer initializer = new FunctionInitializer() { 196 @Override 197 public void initialize( 198 @NotNull List<TypeParameterDescriptor> typeParameters, 199 @NotNull List<ValueParameterDescriptor> valueParameters, 200 @Nullable JetType returnType 201 ) { 202 result.initialize( 203 null, 204 original.getExpectedThisObject(), 205 typeParameters, 206 valueParameters, 207 returnType, 208 original.getModality(), 209 original.getVisibility(), 210 false 211 ); 212 } 213 }; 214 return initSamAdapter(original, result, initializer); 215 } 216 217 @NotNull 218 public static ConstructorDescriptor createSamAdapterConstructor(@NotNull final ConstructorDescriptor original) { 219 final ConstructorDescriptorImpl result = new ConstructorDescriptorImpl( 220 original.getContainingDeclaration(), 221 original.getAnnotations(), 222 original.isPrimary(), 223 CallableMemberDescriptor.Kind.SYNTHESIZED 224 ); 225 FunctionInitializer initializer = new FunctionInitializer() { 226 @Override 227 public void initialize( 228 @NotNull List<TypeParameterDescriptor> typeParameters, 229 @NotNull List<ValueParameterDescriptor> valueParameters, 230 @Nullable JetType returnType 231 ) { 232 result.initialize( 233 typeParameters, 234 valueParameters, 235 original.getVisibility(), 236 original.getExpectedThisObject() == ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER 237 ); 238 } 239 }; 240 return initSamAdapter(original, result, initializer); 241 } 242 243 private static <F extends FunctionDescriptor> F initSamAdapter( 244 @NotNull F original, 245 @NotNull F adapter, 246 @NotNull FunctionInitializer initializer 247 ) { 248 TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter); 249 250 JetType returnTypeUnsubstituted = original.getReturnType(); 251 JetType returnType; 252 if (returnTypeUnsubstituted == null) { // return type may be null for not yet initialized constructors 253 returnType = null; 254 } 255 else { 256 returnType = typeParameters.substitutor.substitute(returnTypeUnsubstituted, Variance.OUT_VARIANCE); 257 assert returnType != null : "couldn't substitute type: " + returnType + ", substitutor = " + typeParameters.substitutor; 258 } 259 260 List<ValueParameterDescriptor> valueParameters = Lists.newArrayList(); 261 for (ValueParameterDescriptor originalParam : original.getValueParameters()) { 262 JetType originalType = originalParam.getType(); 263 JetType functionType = getFunctionTypeForSamType(originalType); 264 JetType newTypeUnsubstituted = functionType != null ? functionType : originalType; 265 JetType newType = typeParameters.substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE); 266 assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + typeParameters.substitutor; 267 268 ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl( 269 adapter, originalParam.getIndex(), originalParam.getAnnotations(), originalParam.getName(), newType, false, null); 270 valueParameters.add(newParam); 271 } 272 273 initializer.initialize(typeParameters.descriptors, valueParameters, returnType); 274 return adapter; 275 } 276 277 @NotNull 278 private static TypeParameters recreateAndInitializeTypeParameters( 279 @NotNull List<TypeParameterDescriptor> originalParameters, 280 @Nullable DeclarationDescriptor newOwner 281 ) { 282 Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> traitToFunTypeParameters = 283 SignaturesUtil.recreateTypeParametersAndReturnMapping(originalParameters, newOwner); 284 TypeSubstitutor typeParametersSubstitutor = SignaturesUtil.createSubstitutorForTypeParameters(traitToFunTypeParameters); 285 for (Map.Entry<TypeParameterDescriptor, TypeParameterDescriptorImpl> mapEntry : traitToFunTypeParameters.entrySet()) { 286 TypeParameterDescriptor traitTypeParameter = mapEntry.getKey(); 287 TypeParameterDescriptorImpl funTypeParameter = mapEntry.getValue(); 288 289 for (JetType upperBound : traitTypeParameter.getUpperBounds()) { 290 JetType upperBoundSubstituted = typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT); 291 assert upperBoundSubstituted != null : "couldn't substitute type: " + upperBound + ", substitutor = " + typeParametersSubstitutor; 292 funTypeParameter.addUpperBound(upperBoundSubstituted); 293 } 294 295 funTypeParameter.setInitialized(); 296 } 297 298 List<TypeParameterDescriptor> typeParameters = Lists.<TypeParameterDescriptor>newArrayList(traitToFunTypeParameters.values()); 299 return new TypeParameters(typeParameters, typeParametersSubstitutor); 300 } 301 302 @NotNull 303 public static SimpleFunctionDescriptor getAbstractMethodOfSamType(@NotNull JetType type) { 304 return (SimpleFunctionDescriptor) getAbstractMembers(type).get(0); 305 } 306 307 @NotNull 308 public static SimpleFunctionDescriptor getAbstractMethodOfSamInterface(@NotNull ClassDescriptor samInterface) { 309 return getAbstractMethodOfSamType(samInterface.getDefaultType()); 310 } 311 312 private SingleAbstractMethodUtils() { 313 } 314 315 private static class TypeParameters { 316 public final List<TypeParameterDescriptor> descriptors; 317 public final TypeSubstitutor substitutor; 318 319 private TypeParameters(List<TypeParameterDescriptor> descriptors, TypeSubstitutor substitutor) { 320 this.descriptors = descriptors; 321 this.substitutor = substitutor; 322 } 323 } 324 325 private static abstract class FunctionInitializer { 326 public abstract void initialize( 327 @NotNull List<TypeParameterDescriptor> typeParameters, 328 @NotNull List<ValueParameterDescriptor> valueParameters, 329 @Nullable JetType returnType 330 ); 331 } 332}