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