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.load.java.sam; 018 019 import org.jetbrains.annotations.NotNull; 020 import org.jetbrains.annotations.Nullable; 021 import org.jetbrains.kotlin.descriptors.*; 022 import org.jetbrains.kotlin.descriptors.annotations.Annotations; 023 import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl; 024 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; 025 import org.jetbrains.kotlin.load.java.descriptors.*; 026 import org.jetbrains.kotlin.load.java.lazy.types.LazyJavaTypeResolver; 027 import org.jetbrains.kotlin.name.Name; 028 import org.jetbrains.kotlin.resolve.DescriptorUtils; 029 import org.jetbrains.kotlin.resolve.FunctionTypeResolveUtilsKt; 030 import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; 031 import org.jetbrains.kotlin.resolve.jvm.JavaResolverUtils; 032 import org.jetbrains.kotlin.types.*; 033 034 import java.util.ArrayList; 035 import java.util.Collections; 036 import java.util.List; 037 import java.util.Map; 038 039 import static org.jetbrains.kotlin.types.Variance.IN_VARIANCE; 040 041 public class SingleAbstractMethodUtils { 042 private SingleAbstractMethodUtils() { 043 } 044 045 @NotNull 046 public static List<CallableMemberDescriptor> getAbstractMembers(@NotNull KotlinType type) { 047 List<CallableMemberDescriptor> abstractMembers = new ArrayList<CallableMemberDescriptor>(); 048 for (DeclarationDescriptor member : DescriptorUtils.getAllDescriptors(type.getMemberScope())) { 049 if (member instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) member).getModality() == Modality.ABSTRACT) { 050 abstractMembers.add((CallableMemberDescriptor) member); 051 } 052 } 053 return abstractMembers; 054 } 055 056 @Nullable 057 public static KotlinType getFunctionTypeForSamType(@NotNull KotlinType samType) { 058 // e.g. samType == Comparator<String>? 059 060 ClassifierDescriptor classifier = samType.getConstructor().getDeclarationDescriptor(); 061 if (classifier instanceof JavaClassDescriptor) { 062 // Function2<T, T, Int> 063 KotlinType functionTypeDefault = ((JavaClassDescriptor) classifier).getFunctionTypeForSamInterface(); 064 065 if (functionTypeDefault != null) { 066 KotlinType noProjectionsSamType = SingleAbstractMethodUtilsKt.nonProjectionParametrization(samType); 067 if (noProjectionsSamType == null) return null; 068 069 // Function2<String, String, Int>? 070 KotlinType type = TypeSubstitutor.create(noProjectionsSamType).substitute(functionTypeDefault, IN_VARIANCE); 071 assert type != null : "Substitution based on type with no projections '" + noProjectionsSamType + 072 "' should not end with conflict"; 073 074 if (FlexibleTypesKt.isNullabilityFlexible(samType)) { 075 return LazyJavaTypeResolver.FlexibleJavaClassifierTypeFactory.INSTANCE.create(type, TypeUtils.makeNullable(type)); 076 } 077 078 return TypeUtils.makeNullableAsSpecified(type, samType.isMarkedNullable()); 079 } 080 } 081 return null; 082 } 083 084 @NotNull 085 public static KotlinType getFunctionTypeForAbstractMethod(@NotNull FunctionDescriptor function) { 086 KotlinType returnType = function.getReturnType(); 087 assert returnType != null : "function is not initialized: " + function; 088 List<ValueParameterDescriptor> valueParameters = function.getValueParameters(); 089 List<KotlinType> parameterTypes = new ArrayList<KotlinType>(valueParameters.size()); 090 for (ValueParameterDescriptor parameter : valueParameters) { 091 parameterTypes.add(parameter.getType()); 092 } 093 return FunctionTypeResolveUtilsKt.createFunctionType( 094 DescriptorUtilsKt.getBuiltIns(function), Annotations.Companion.getEMPTY(), null, parameterTypes, returnType 095 ); 096 } 097 098 @Nullable 099 public static FunctionDescriptor getSingleAbstractMethodOrNull(@NotNull ClassDescriptor klass) { 100 if (klass.getKind() != ClassKind.INTERFACE) { 101 return null; 102 } 103 104 List<CallableMemberDescriptor> abstractMembers = getAbstractMembers(klass.getDefaultType()); 105 if (abstractMembers.size() == 1) { 106 CallableMemberDescriptor member = abstractMembers.get(0); 107 if (member instanceof SimpleFunctionDescriptor) { 108 return member.getTypeParameters().isEmpty() 109 ? (FunctionDescriptor) member 110 : null; 111 } 112 } 113 114 return null; 115 } 116 117 @NotNull 118 public static SamConstructorDescriptor createSamConstructorFunction( 119 @NotNull DeclarationDescriptor owner, 120 @NotNull JavaClassDescriptor samInterface 121 ) { 122 assert getSingleAbstractMethodOrNull(samInterface) != null : samInterface; 123 124 SamConstructorDescriptor result = new SamConstructorDescriptor(owner, samInterface); 125 126 TypeParameters typeParameters = recreateAndInitializeTypeParameters(samInterface.getTypeConstructor().getParameters(), result); 127 128 KotlinType parameterTypeUnsubstituted = getFunctionTypeForSamType(samInterface.getDefaultType()); 129 assert parameterTypeUnsubstituted != null : "couldn't get function type for SAM type " + samInterface.getDefaultType(); 130 KotlinType parameterType = typeParameters.substitutor.substitute(parameterTypeUnsubstituted, Variance.IN_VARIANCE); 131 assert parameterType != null : "couldn't substitute type: " + parameterTypeUnsubstituted + 132 ", substitutor = " + typeParameters.substitutor; 133 ValueParameterDescriptor parameter = new ValueParameterDescriptorImpl( 134 result, null, 0, Annotations.Companion.getEMPTY(), Name.identifier("function"), parameterType, 135 /* declaresDefaultValue = */ false, 136 /* isCrossinline = */ false, 137 /* isNoinline = */ false, 138 null, SourceElement.NO_SOURCE); 139 140 KotlinType returnType = typeParameters.substitutor.substitute(samInterface.getDefaultType(), Variance.OUT_VARIANCE); 141 assert returnType != null : "couldn't substitute type: " + samInterface.getDefaultType() + 142 ", substitutor = " + typeParameters.substitutor; 143 144 result.initialize( 145 null, 146 null, 147 typeParameters.descriptors, 148 Collections.singletonList(parameter), 149 returnType, 150 Modality.FINAL, 151 samInterface.getVisibility() 152 ); 153 154 return result; 155 } 156 157 public static boolean isSamType(@NotNull KotlinType type) { 158 return getFunctionTypeForSamType(type) != null; 159 } 160 161 public static boolean isSamAdapterNecessary(@NotNull FunctionDescriptor fun) { 162 for (ValueParameterDescriptor param : fun.getValueParameters()) { 163 if (isSamType(param.getType())) { 164 return true; 165 } 166 } 167 return false; 168 } 169 170 @NotNull 171 public static SamAdapterDescriptor<JavaMethodDescriptor> createSamAdapterFunction(@NotNull final JavaMethodDescriptor original) { 172 final SamAdapterFunctionDescriptor result = new SamAdapterFunctionDescriptor(original); 173 return initSamAdapter(original, result, new FunctionInitializer() { 174 @Override 175 public void initialize( 176 @NotNull List<TypeParameterDescriptor> typeParameters, 177 @NotNull List<ValueParameterDescriptor> valueParameters, 178 @NotNull KotlinType returnType 179 ) { 180 result.initialize( 181 null, 182 original.getDispatchReceiverParameter(), 183 typeParameters, 184 valueParameters, 185 returnType, 186 Modality.FINAL, 187 original.getVisibility() 188 ); 189 } 190 }); 191 } 192 193 @NotNull 194 public static SamAdapterDescriptor<JavaConstructorDescriptor> createSamAdapterConstructor(@NotNull final JavaConstructorDescriptor original) { 195 final SamAdapterConstructorDescriptor result = new SamAdapterConstructorDescriptor(original); 196 return initSamAdapter(original, result, new FunctionInitializer() { 197 @Override 198 public void initialize( 199 @NotNull List<TypeParameterDescriptor> typeParameters, 200 @NotNull List<ValueParameterDescriptor> valueParameters, 201 @NotNull KotlinType returnType 202 ) { 203 result.initialize(valueParameters, original.getVisibility()); 204 result.setReturnType(returnType); 205 } 206 }); 207 } 208 209 @NotNull 210 private static <F extends FunctionDescriptor> SamAdapterDescriptor<F> initSamAdapter( 211 @NotNull F original, 212 @NotNull SamAdapterDescriptor<F> adapter, 213 @NotNull FunctionInitializer initializer 214 ) { 215 TypeParameters typeParameters = recreateAndInitializeTypeParameters(original.getTypeParameters(), adapter); 216 217 KotlinType returnTypeUnsubstituted = original.getReturnType(); 218 assert returnTypeUnsubstituted != null : "Creating SAM adapter for not initialized original: " + original; 219 220 TypeSubstitutor substitutor = typeParameters.substitutor; 221 KotlinType returnType = substitutor.substitute(returnTypeUnsubstituted, Variance.INVARIANT); 222 assert returnType != null : "couldn't substitute type: " + returnTypeUnsubstituted + 223 ", substitutor = " + substitutor; 224 225 226 List<ValueParameterDescriptor> valueParameters = createValueParametersForSamAdapter(original, adapter, substitutor); 227 228 initializer.initialize(typeParameters.descriptors, valueParameters, returnType); 229 230 return adapter; 231 } 232 233 public static List<ValueParameterDescriptor> createValueParametersForSamAdapter( 234 @NotNull FunctionDescriptor original, 235 @NotNull FunctionDescriptor samAdapter, 236 @NotNull TypeSubstitutor substitutor 237 ) { 238 List<ValueParameterDescriptor> originalValueParameters = original.getValueParameters(); 239 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(originalValueParameters.size()); 240 for (ValueParameterDescriptor originalParam : originalValueParameters) { 241 KotlinType originalType = originalParam.getType(); 242 KotlinType functionType = getFunctionTypeForSamType(originalType); 243 KotlinType newTypeUnsubstituted = functionType != null ? functionType : originalType; 244 KotlinType newType = substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE); 245 assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + substitutor; 246 247 ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl( 248 samAdapter, null, originalParam.getIndex(), originalParam.getAnnotations(), 249 originalParam.getName(), newType, 250 /* declaresDefaultValue = */ false, 251 /* isCrossinline = */ false, 252 /* isNoinline = */ false, 253 null, SourceElement.NO_SOURCE 254 ); 255 valueParameters.add(newParam); 256 } 257 return valueParameters; 258 } 259 260 @NotNull 261 private static TypeParameters recreateAndInitializeTypeParameters( 262 @NotNull List<TypeParameterDescriptor> originalParameters, 263 @Nullable DeclarationDescriptor newOwner 264 ) { 265 if (newOwner instanceof SamAdapterConstructorDescriptor) { 266 return new TypeParameters(originalParameters, TypeSubstitutor.EMPTY); 267 } 268 269 Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> traitToFunTypeParameters = 270 JavaResolverUtils.recreateTypeParametersAndReturnMapping(originalParameters, newOwner); 271 TypeSubstitutor typeParametersSubstitutor = JavaResolverUtils.createSubstitutorForTypeParameters(traitToFunTypeParameters); 272 for (Map.Entry<TypeParameterDescriptor, TypeParameterDescriptorImpl> mapEntry : traitToFunTypeParameters.entrySet()) { 273 TypeParameterDescriptor traitTypeParameter = mapEntry.getKey(); 274 TypeParameterDescriptorImpl funTypeParameter = mapEntry.getValue(); 275 276 for (KotlinType upperBound : traitTypeParameter.getUpperBounds()) { 277 KotlinType upperBoundSubstituted = typeParametersSubstitutor.substitute(upperBound, Variance.INVARIANT); 278 assert upperBoundSubstituted != null : "couldn't substitute type: " + upperBound + ", substitutor = " + typeParametersSubstitutor; 279 funTypeParameter.addUpperBound(upperBoundSubstituted); 280 } 281 282 funTypeParameter.setInitialized(); 283 } 284 285 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(traitToFunTypeParameters.values()); 286 return new TypeParameters(typeParameters, typeParametersSubstitutor); 287 } 288 289 private static class TypeParameters { 290 public final List<TypeParameterDescriptor> descriptors; 291 public final TypeSubstitutor substitutor; 292 293 private TypeParameters(List<TypeParameterDescriptor> descriptors, TypeSubstitutor substitutor) { 294 this.descriptors = descriptors; 295 this.substitutor = substitutor; 296 } 297 } 298 299 private static abstract class FunctionInitializer { 300 public abstract void initialize( 301 @NotNull List<TypeParameterDescriptor> typeParameters, 302 @NotNull List<ValueParameterDescriptor> valueParameters, 303 @NotNull KotlinType returnType 304 ); 305 } 306 307 308 }