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 }