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
017 package org.jetbrains.jet.lang.resolve.java.kotlinSignature;
018
019 import com.google.common.collect.*;
020 import com.intellij.openapi.diagnostic.Logger;
021 import com.intellij.openapi.util.Pair;
022 import com.intellij.openapi.util.SystemInfo;
023 import com.intellij.psi.PsiElement;
024 import com.intellij.psi.PsiManager;
025 import com.intellij.psi.PsiMethod;
026 import com.intellij.util.Function;
027 import com.intellij.util.containers.ContainerUtil;
028 import org.jetbrains.annotations.NotNull;
029 import org.jetbrains.annotations.Nullable;
030 import org.jetbrains.jet.lang.descriptors.*;
031 import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
032 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
033 import org.jetbrains.jet.lang.resolve.BindingContext;
034 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
035 import org.jetbrains.jet.lang.resolve.BindingTrace;
036 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
037 import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
038 import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
039 import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils;
040 import org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage;
041 import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
042 import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
043 import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaMethodImpl;
044 import org.jetbrains.jet.lang.resolve.name.FqName;
045 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
046 import org.jetbrains.jet.lang.resolve.name.Name;
047 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
048 import org.jetbrains.jet.lang.types.*;
049 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
050 import org.jetbrains.jet.renderer.DescriptorRenderer;
051
052 import java.util.*;
053
054 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName;
055 import static org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage.*;
056 import static org.jetbrains.jet.lang.types.Variance.INVARIANT;
057
058 public class SignaturesPropagationData {
059 private static final Logger LOG = Logger.getInstance(SignaturesPropagationData.class);
060
061 private final List<TypeParameterDescriptor> modifiedTypeParameters;
062 private final ValueParameters modifiedValueParameters;
063 private final JetType modifiedReturnType;
064
065 private final List<String> signatureErrors = Lists.newArrayList();
066 private final List<FunctionDescriptor> superFunctions;
067 private final Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> autoTypeParameterToModified;
068 final ClassDescriptor containingClass;
069
070 public SignaturesPropagationData(
071 @NotNull ClassDescriptor containingClass,
072 @NotNull JetType autoReturnType, // type built by JavaTypeTransformer from Java signature and @NotNull annotations
073 @Nullable JetType receiverType,
074 @NotNull List<ValueParameterDescriptor> autoValueParameters, // descriptors built by parameters resolver
075 @NotNull List<TypeParameterDescriptor> autoTypeParameters, // descriptors built by signature resolver
076 @NotNull JavaMethodImpl method,
077 @NotNull BindingTrace trace
078 ) {
079 this.containingClass = containingClass;
080 superFunctions = getSuperFunctionsForMethod(method, trace, containingClass);
081
082 autoTypeParameterToModified = DescriptorResolverUtils.recreateTypeParametersAndReturnMapping(autoTypeParameters, null);
083
084 modifiedTypeParameters = modifyTypeParametersAccordingToSuperMethods(autoTypeParameters);
085 modifiedReturnType = modifyReturnTypeAccordingToSuperMethods(autoReturnType);
086 modifiedValueParameters = modifyValueParametersAccordingToSuperMethods(receiverType, autoValueParameters);
087 }
088
089 public List<TypeParameterDescriptor> getModifiedTypeParameters() {
090 return modifiedTypeParameters;
091 }
092
093 public JetType getModifiedReceiverType() {
094 return modifiedValueParameters.receiverType;
095 }
096
097 public List<ValueParameterDescriptor> getModifiedValueParameters() {
098 return modifiedValueParameters.descriptors;
099 }
100
101 public JetType getModifiedReturnType() {
102 return modifiedReturnType;
103 }
104
105 public List<String> getSignatureErrors() {
106 return signatureErrors;
107 }
108
109 public List<FunctionDescriptor> getSuperFunctions() {
110 return superFunctions;
111 }
112
113 void reportError(String error) {
114 signatureErrors.add(error);
115 }
116
117 private JetType modifyReturnTypeAccordingToSuperMethods(
118 @NotNull JetType autoType // type built by JavaTypeTransformer
119 ) {
120 List<TypeAndVariance> typesFromSuperMethods = ContainerUtil.map(superFunctions,
121 new Function<FunctionDescriptor, TypeAndVariance>() {
122 @Override
123 public TypeAndVariance fun(FunctionDescriptor superFunction) {
124 return new TypeAndVariance(superFunction.getReturnType(), Variance.OUT_VARIANCE);
125 }
126 });
127
128 return modifyTypeAccordingToSuperMethods(autoType, typesFromSuperMethods, MEMBER_SIGNATURE_COVARIANT);
129 }
130
131 private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods(List<TypeParameterDescriptor> autoTypeParameters) {
132 List<TypeParameterDescriptor> result = Lists.newArrayList();
133
134 for (TypeParameterDescriptor autoParameter : autoTypeParameters) {
135 int index = autoParameter.getIndex();
136 TypeParameterDescriptorImpl modifiedTypeParameter = autoTypeParameterToModified.get(autoParameter);
137
138 List<Iterator<JetType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList();
139 for (FunctionDescriptor superFunction : superFunctions) {
140 upperBoundFromSuperFunctionsIterators.add(superFunction.getTypeParameters().get(index).getUpperBounds().iterator());
141 }
142
143 for (JetType autoUpperBound : autoParameter.getUpperBounds()) {
144 List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList();
145
146 for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
147 assert iterator.hasNext();
148 upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT));
149 }
150
151 JetType modifiedUpperBound = modifyTypeAccordingToSuperMethods(autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND);
152 modifiedTypeParameter.addUpperBound(modifiedUpperBound);
153 }
154
155 for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) {
156 assert !iterator.hasNext();
157 }
158
159 modifiedTypeParameter.setInitialized();
160 result.add(modifiedTypeParameter);
161 }
162
163 return result;
164 }
165
166 private ValueParameters modifyValueParametersAccordingToSuperMethods(
167 @Nullable JetType receiverType,
168 @NotNull List<ValueParameterDescriptor> parameters // descriptors built by parameters resolver
169 ) {
170 assert receiverType == null : "Parameters before propagation have receiver type," +
171 " but propagation should be disabled for functions compiled from Kotlin in class: " +
172 DescriptorUtils.getFQName(containingClass);
173
174 JetType resultReceiverType = null;
175 List<ValueParameterDescriptor> resultParameters = Lists.newArrayList();
176
177 boolean shouldBeExtension = checkIfShouldBeExtension();
178
179 for (ValueParameterDescriptor originalParam : parameters) {
180 final int originalIndex = originalParam.getIndex();
181 List<TypeAndVariance> typesFromSuperMethods = ContainerUtil.map(superFunctions,
182 new Function<FunctionDescriptor, TypeAndVariance>() {
183 @Override
184 public TypeAndVariance fun(FunctionDescriptor superFunction) {
185 ReceiverParameterDescriptor receiver = superFunction.getReceiverParameter();
186 int index = receiver != null ? originalIndex - 1 : originalIndex;
187 if (index == -1) {
188 assert receiver != null : "can't happen: index is -1, while function is not extension";
189 return new TypeAndVariance(receiver.getType(), INVARIANT);
190 }
191 return new TypeAndVariance(superFunction.getValueParameters().get(index).getType(), INVARIANT);
192 }
193 });
194
195 VarargCheckResult varargCheckResult = checkVarargInSuperFunctions(originalParam);
196
197 JetType altType = modifyTypeAccordingToSuperMethods(varargCheckResult.parameterType, typesFromSuperMethods, MEMBER_SIGNATURE_CONTRAVARIANT);
198
199 if (shouldBeExtension && originalIndex == 0) {
200 resultReceiverType = altType;
201 }
202 else {
203 resultParameters.add(new ValueParameterDescriptorImpl(
204 originalParam.getContainingDeclaration(),
205 shouldBeExtension ? originalIndex - 1 : originalIndex,
206 originalParam.getAnnotations(),
207 originalParam.getName(),
208 altType,
209 originalParam.declaresDefaultValue(),
210 varargCheckResult.isVararg ? KotlinBuiltIns.getInstance().getArrayElementType(altType) : null
211 ));
212 }
213 }
214
215 return new ValueParameters(resultReceiverType, resultParameters);
216 }
217
218 private static List<FunctionDescriptor> getSuperFunctionsForMethod(
219 @NotNull JavaMethodImpl method,
220 @NotNull BindingTrace trace,
221 @NotNull ClassDescriptor containingClass
222 ) {
223 List<FunctionDescriptor> superFunctions = Lists.newArrayList();
224
225 Map<ClassDescriptor, JetType> superclassToSupertype = getSuperclassToSupertypeMap(containingClass);
226
227 Multimap<FqName, Pair<FunctionDescriptor, JavaMethodImpl>> superclassToFunctions =
228 getSuperclassToFunctionsMultimap(method, trace.getBindingContext(), containingClass);
229
230 for (JavaMethodImpl superMethod : PropagationHeuristics.getSuperMethods(method)) {
231 JavaClass javaClass = superMethod.getContainingClass();
232 FqName classFqName = javaClass.getFqName();
233 assert classFqName != null : "Class FQ name should not be null: " + javaClass;
234
235 if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(classFqName).isEmpty()) {
236 for (FunctionDescriptor superFun : JavaToKotlinMethodMap.INSTANCE.getFunctions(superMethod, classFqName, containingClass)) {
237 superFunctions.add(substituteSuperFunction(superclassToSupertype, superFun));
238 }
239 continue;
240 }
241
242 DeclarationDescriptor superFun = superMethod.getPsi() instanceof KotlinLightMethod
243 ? trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ((KotlinLightMethod) superMethod.getPsi()).getOrigin())
244 : findSuperFunction(superclassToFunctions.get(classFqName), superMethod);
245 if (superFun == null) {
246 // Super methods which are Object methods in interfaces are not loaded by JDR.
247 if (!DescriptorResolverUtils.isObjectMethodInInterface(superMethod)) {
248 reportCantFindSuperFunction(method);
249 }
250 continue;
251 }
252
253 // TODO: Add propagation for other kotlin descriptors (KT-3621)
254 if (superFun instanceof FunctionDescriptor) {
255 superFunctions.add(substituteSuperFunction(superclassToSupertype, (FunctionDescriptor) superFun));
256 }
257 }
258
259 // sorting for diagnostic stability
260 Collections.sort(superFunctions, new Comparator<FunctionDescriptor>() {
261 @Override
262 public int compare(FunctionDescriptor fun1, FunctionDescriptor fun2) {
263 FqNameUnsafe fqName1 = getFQName(fun1.getContainingDeclaration());
264 FqNameUnsafe fqName2 = getFQName(fun2.getContainingDeclaration());
265 return fqName1.asString().compareTo(fqName2.asString());
266 }
267 });
268 return superFunctions;
269 }
270
271 @NotNull
272 private static Multimap<FqName, Pair<FunctionDescriptor, JavaMethodImpl>> getSuperclassToFunctionsMultimap(
273 @NotNull JavaMethod method,
274 @NotNull BindingContext bindingContext,
275 @NotNull ClassDescriptor containingClass
276 ) {
277 Multimap<FqName, Pair<FunctionDescriptor, JavaMethodImpl>> result = HashMultimap.create();
278
279 Name functionName = method.getName();
280 int parameterCount = method.getValueParameters().size();
281
282 for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
283 ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor();
284 assert klass != null;
285 FqName fqName = DescriptorUtils.getFQName(klass).toSafe();
286
287 for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
288 CallableMemberDescriptor.Kind kind = fun.getKind();
289 if ((kind == CallableMemberDescriptor.Kind.DECLARATION || kind == CallableMemberDescriptor.Kind.DELEGATION) &&
290 fun.getValueParameters().size() + (fun.getReceiverParameter() != null ? 1 : 0) == parameterCount) {
291 PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
292 if (declaration instanceof PsiMethod) {
293 result.put(fqName, Pair.create(fun, new JavaMethodImpl((PsiMethod) declaration)));
294 } // else declaration is null or JetNamedFunction: both cases are processed later
295 }
296 }
297 }
298 return result;
299 }
300
301 @Nullable
302 private static DeclarationDescriptor findSuperFunction(
303 @NotNull Collection<Pair<FunctionDescriptor, JavaMethodImpl>> superFunctionCandidates,
304 @NotNull JavaMethodImpl superMethod
305 ) {
306 PsiManager psiManager = PsiManager.getInstance(superMethod.getPsi().getProject());
307 for (Pair<FunctionDescriptor, JavaMethodImpl> candidate : superFunctionCandidates) {
308 if (psiManager.areElementsEquivalent(candidate.second.getPsi(), superMethod.getPsi())) {
309 return candidate.first;
310 }
311 }
312 return null;
313 }
314
315 private boolean checkIfShouldBeExtension() {
316 boolean someSupersExtension = false;
317 boolean someSupersNotExtension = false;
318
319 for (FunctionDescriptor superFunction : superFunctions) {
320 if (superFunction.getReceiverParameter() != null) {
321 someSupersExtension = true;
322 }
323 else {
324 someSupersNotExtension = true;
325 }
326 }
327
328 if (someSupersExtension) {
329 if (someSupersNotExtension) {
330 reportError("Incompatible super methods: some are extension functions, some are not");
331 }
332 else {
333 return true;
334 }
335 }
336 return false;
337 }
338
339 @NotNull
340 private VarargCheckResult checkVarargInSuperFunctions(@NotNull ValueParameterDescriptor originalParam) {
341 boolean someSupersVararg = false;
342 boolean someSupersNotVararg = false;
343 for (FunctionDescriptor superFunction : superFunctions) {
344 int originalIndex = originalParam.getIndex();
345 int index = superFunction.getReceiverParameter() != null ? originalIndex - 1 : originalIndex;
346 if (index != -1 && superFunction.getValueParameters().get(index).getVarargElementType() != null) {
347 someSupersVararg = true;
348 }
349 else {
350 someSupersNotVararg = true;
351 }
352 }
353
354 JetType originalVarargElementType = originalParam.getVarargElementType();
355 JetType originalType = originalParam.getType();
356
357 if (someSupersVararg && someSupersNotVararg) {
358 reportError("Incompatible super methods: some have vararg parameter, some have not");
359 return new VarargCheckResult(originalType, originalVarargElementType != null);
360 }
361
362 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
363 if (someSupersVararg && originalVarargElementType == null) {
364 // convert to vararg
365
366 assert isArrayType(originalType);
367
368 if (builtIns.isPrimitiveArray(originalType)) {
369 // replace IntArray? with IntArray
370 return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true);
371 }
372
373 // replace Array<out Foo>? with Array<Foo>
374 JetType varargElementType = builtIns.getArrayElementType(originalType);
375 return new VarargCheckResult(builtIns.getArrayType(INVARIANT, varargElementType), true);
376 }
377 else if (someSupersNotVararg && originalVarargElementType != null) {
378 // convert to non-vararg
379
380 assert isArrayType(originalType);
381
382 if (builtIns.isPrimitiveArray(originalType)) {
383 // replace IntArray with IntArray?
384 return new VarargCheckResult(TypeUtils.makeNullable(originalType), false);
385 }
386
387 // replace Array<Foo> with Array<out Foo>?
388 return new VarargCheckResult(TypeUtils.makeNullable(builtIns.getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)),
389 false);
390 }
391
392 return new VarargCheckResult(originalType, originalVarargElementType != null);
393 }
394
395 @NotNull
396 private JetType modifyTypeAccordingToSuperMethods(
397 @NotNull JetType autoType,
398 @NotNull List<TypeAndVariance> typesFromSuper,
399 @NotNull TypeUsage howThisTypeIsUsed
400 ) {
401 if (autoType.isError()) {
402 return autoType;
403 }
404
405 boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, howThisTypeIsUsed);
406 ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper);
407 List<TypeProjection> resultArguments = getTypeArgsOfType(autoType, resultClassifier, typesFromSuper);
408 JetScope resultScope;
409 if (resultClassifier instanceof ClassDescriptor) {
410 resultScope = ((ClassDescriptor) resultClassifier).getMemberScope(resultArguments);
411 }
412 else {
413 resultScope = autoType.getMemberScope();
414 }
415
416 JetTypeImpl type = new JetTypeImpl(autoType.getAnnotations(),
417 resultClassifier.getTypeConstructor(),
418 resultNullable,
419 resultArguments,
420 resultScope);
421
422 PropagationHeuristics.checkArrayInReturnType(this, type, typesFromSuper);
423 return type;
424 }
425
426 @NotNull
427 private List<TypeProjection> getTypeArgsOfType(
428 @NotNull JetType autoType,
429 @NotNull ClassifierDescriptor classifier,
430 @NotNull List<TypeAndVariance> typesFromSuper
431 ) {
432 List<TypeProjection> autoArguments = autoType.getArguments();
433
434 if (!(classifier instanceof ClassDescriptor)) {
435 assert autoArguments.isEmpty() :
436 "Unexpected type arguments when type constructor is not ClassDescriptor, type = " + autoType;
437 return autoArguments;
438 }
439
440 List<List<TypeProjectionAndVariance>> typeArgumentsFromSuper = calculateTypeArgumentsFromSuper((ClassDescriptor) classifier,
441 typesFromSuper);
442
443 // Modify type arguments using info from typesFromSuper
444 List<TypeProjection> resultArguments = Lists.newArrayList();
445 for (TypeParameterDescriptor parameter : classifier.getTypeConstructor().getParameters()) {
446 TypeProjection argument = autoArguments.get(parameter.getIndex());
447
448 JetType argumentType = argument.getType();
449 List<TypeProjectionAndVariance> projectionsFromSuper = typeArgumentsFromSuper.get(parameter.getIndex());
450 List<TypeAndVariance> argTypesFromSuper = getTypes(projectionsFromSuper);
451
452 JetType type = modifyTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, TYPE_ARGUMENT);
453 Variance projectionKind = calculateArgumentProjectionKindFromSuper(argument, projectionsFromSuper);
454
455 resultArguments.add(new TypeProjectionImpl(projectionKind, type));
456 }
457 return resultArguments;
458 }
459
460 private Variance calculateArgumentProjectionKindFromSuper(
461 @NotNull TypeProjection argument,
462 @NotNull List<TypeProjectionAndVariance> projectionsFromSuper
463 ) {
464 Set<Variance> projectionKindsInSuper = Sets.newLinkedHashSet();
465 for (TypeProjectionAndVariance projectionAndVariance : projectionsFromSuper) {
466 projectionKindsInSuper.add(projectionAndVariance.typeProjection.getProjectionKind());
467 }
468
469 Variance defaultProjectionKind = argument.getProjectionKind();
470 if (projectionKindsInSuper.size() == 0) {
471 return defaultProjectionKind;
472 }
473 else if (projectionKindsInSuper.size() == 1) {
474 Variance projectionKindInSuper = projectionKindsInSuper.iterator().next();
475 if (defaultProjectionKind == INVARIANT || defaultProjectionKind == projectionKindInSuper) {
476 return projectionKindInSuper;
477 }
478 else {
479 reportError("Incompatible projection kinds in type arguments of super methods' return types: "
480 + projectionsFromSuper + ", defined in current: " + argument);
481 return defaultProjectionKind;
482 }
483 }
484 else {
485 reportError("Incompatible projection kinds in type arguments of super methods' return types: " + projectionsFromSuper);
486 return defaultProjectionKind;
487 }
488 }
489
490 @NotNull
491 private static List<TypeAndVariance> getTypes(@NotNull List<TypeProjectionAndVariance> projections) {
492 List<TypeAndVariance> types = Lists.newArrayList();
493 for (TypeProjectionAndVariance projection : projections) {
494 types.add(new TypeAndVariance(projection.typeProjection.getType(),
495 merge(projection.varianceOfPosition, projection.typeProjection.getProjectionKind())));
496 }
497 return types;
498 }
499
500 private static Variance merge(Variance positionOfOuter, Variance projectionKind) {
501 // Inv<Inv<out X>>, X is in invariant position
502 if (positionOfOuter == INVARIANT) return INVARIANT;
503 // Out<X>, X is in out-position
504 if (projectionKind == INVARIANT) return positionOfOuter;
505 // Out<Out<X>>, X is in out-position
506 // In<In<X>>, X is in out-position
507 // Out<In<X>>, X is in in-position
508 // In<Out<X>>, X is in in-position
509 return positionOfOuter.superpose(projectionKind);
510 }
511
512 // Returns list with type arguments info from supertypes
513 // Example:
514 // - Foo<A, B> is a subtype of Bar<A, List<B>>, Baz<Boolean, A>
515 // - input: klass = Foo, typesFromSuper = [Bar<String, List<Int>>, Baz<Boolean, CharSequence>]
516 // - output[0] = [String, CharSequence], output[1] = []
517 private static List<List<TypeProjectionAndVariance>> calculateTypeArgumentsFromSuper(
518 @NotNull ClassDescriptor klass,
519 @NotNull Collection<TypeAndVariance> typesFromSuper
520 ) {
521 // For each superclass of klass and its parameters, hold their mapping to klass' parameters
522 // #0 of Bar -> A
523 // #1 of Bar -> List<B>
524 // #0 of Baz -> Boolean
525 // #1 of Baz -> A
526 // #0 of Foo -> A (mapped to itself)
527 // #1 of Foo -> B (mapped to itself)
528 Multimap<TypeConstructor, TypeProjection> substitution = SubstitutionUtils.buildDeepSubstitutionMultimap(
529 TypeUtils.makeUnsubstitutedType(klass, ErrorUtils.createErrorScope("Do not access this scope", true)));
530
531 // for each parameter of klass, hold arguments in corresponding supertypes
532 List<List<TypeProjectionAndVariance>> parameterToArgumentsFromSuper = Lists.newArrayList();
533 for (TypeParameterDescriptor ignored : klass.getTypeConstructor().getParameters()) {
534 parameterToArgumentsFromSuper.add(new ArrayList<TypeProjectionAndVariance>());
535 }
536
537 // Enumerate all types from super and all its parameters
538 for (TypeAndVariance typeFromSuper : typesFromSuper) {
539 for (TypeParameterDescriptor parameter : typeFromSuper.type.getConstructor().getParameters()) {
540 TypeProjection argument = typeFromSuper.type.getArguments().get(parameter.getIndex());
541
542 // for given example, this block is executed four times:
543 // 1. typeFromSuper = Bar<String, List<Int>>, parameter = "#0 of Bar", argument = String
544 // 2. typeFromSuper = Bar<String, List<Int>>, parameter = "#1 of Bar", argument = List<Int>
545 // 3. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#0 of Baz", argument = Boolean
546 // 4. typeFromSuper = Baz<Boolean, CharSequence>, parameter = "#1 of Baz", argument = CharSequence
547
548 // if it is mapped to klass' parameter, then store it into map
549 for (TypeProjection projection : substitution.get(parameter.getTypeConstructor())) {
550 // 1. projection = A
551 // 2. projection = List<B>
552 // 3. projection = Boolean
553 // 4. projection = A
554 ClassifierDescriptor classifier = projection.getType().getConstructor().getDeclarationDescriptor();
555
556 // this condition is true for 1 and 4, false for 2 and 3
557 if (classifier instanceof TypeParameterDescriptor && classifier.getContainingDeclaration() == klass) {
558 int parameterIndex = ((TypeParameterDescriptor) classifier).getIndex();
559 Variance effectiveVariance = parameter.getVariance().superpose(typeFromSuper.varianceOfPosition);
560 parameterToArgumentsFromSuper.get(parameterIndex).add(new TypeProjectionAndVariance(argument, effectiveVariance));
561 }
562 }
563 }
564 }
565 return parameterToArgumentsFromSuper;
566 }
567
568 private boolean typeMustBeNullable(
569 @NotNull JetType autoType,
570 @NotNull List<TypeAndVariance> typesFromSuper,
571 @NotNull TypeUsage howThisTypeIsUsed
572 ) {
573 boolean someSupersNotCovariantNullable = false;
574 boolean someSupersCovariantNullable = false;
575 boolean someSupersNotNull = false;
576 for (TypeAndVariance typeFromSuper : typesFromSuper) {
577 if (!typeFromSuper.type.isNullable()) {
578 someSupersNotNull = true;
579 }
580 else {
581 if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
582 someSupersCovariantNullable = true;
583 }
584 else {
585 someSupersNotCovariantNullable = true;
586 }
587 }
588 }
589
590 if (someSupersNotNull && someSupersNotCovariantNullable) {
591 reportError("Incompatible types in superclasses: " + typesFromSuper);
592 return autoType.isNullable();
593 }
594 else if (someSupersNotNull) {
595 return false;
596 }
597 else if (someSupersNotCovariantNullable || someSupersCovariantNullable) {
598 boolean annotatedAsNotNull = howThisTypeIsUsed != TYPE_ARGUMENT && !autoType.isNullable();
599
600 if (annotatedAsNotNull && someSupersNotCovariantNullable) {
601 DescriptorRenderer renderer = DescriptorRenderer.SOURCE_CODE_SHORT_NAMES_IN_TYPES;
602 reportError("In superclass type is nullable: " + typesFromSuper + ", in subclass it is not: " + renderer.renderType(autoType));
603 return true;
604 }
605
606 return !annotatedAsNotNull;
607 }
608 return autoType.isNullable();
609 }
610
611 @NotNull
612 private ClassifierDescriptor modifyTypeClassifier(
613 @NotNull JetType autoType,
614 @NotNull List<TypeAndVariance> typesFromSuper
615 ) {
616 ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor();
617 if (!(classifier instanceof ClassDescriptor)) {
618 assert classifier != null : "no declaration descriptor for type " + autoType;
619
620 if (classifier instanceof TypeParameterDescriptor && autoTypeParameterToModified.containsKey(classifier)) {
621 return autoTypeParameterToModified.get(classifier);
622 }
623 return classifier;
624 }
625 ClassDescriptor klass = (ClassDescriptor) classifier;
626
627 CollectionClassMapping collectionMapping = CollectionClassMapping.getInstance();
628
629 boolean someSupersMutable = false;
630 boolean someSupersCovariantReadOnly = false;
631 boolean someSupersNotCovariantReadOnly = false;
632 for (TypeAndVariance typeFromSuper : typesFromSuper) {
633 ClassifierDescriptor classifierFromSuper = typeFromSuper.type.getConstructor().getDeclarationDescriptor();
634 if (classifierFromSuper instanceof ClassDescriptor) {
635 ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper;
636
637 if (collectionMapping.isMutableCollection(classFromSuper)) {
638 someSupersMutable = true;
639 }
640 else if (collectionMapping.isReadOnlyCollection(classFromSuper)) {
641 if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
642 someSupersCovariantReadOnly = true;
643 }
644 else {
645 someSupersNotCovariantReadOnly = true;
646 }
647 }
648 }
649 }
650
651 if (someSupersMutable && someSupersNotCovariantReadOnly) {
652 reportError("Incompatible types in superclasses: " + typesFromSuper);
653 return classifier;
654 }
655 else if (someSupersMutable) {
656 if (collectionMapping.isReadOnlyCollection(klass)) {
657 return collectionMapping.convertReadOnlyToMutable(klass);
658 }
659 }
660 else if (someSupersNotCovariantReadOnly || someSupersCovariantReadOnly) {
661 if (collectionMapping.isMutableCollection(klass)) {
662 return collectionMapping.convertMutableToReadOnly(klass);
663 }
664 }
665
666 ClassifierDescriptor fixed = PropagationHeuristics.tryToFixOverridingTWithRawType(this, typesFromSuper);
667 return fixed != null ? fixed : classifier;
668 }
669
670 private static Map<ClassDescriptor, JetType> getSuperclassToSupertypeMap(ClassDescriptor containingClass) {
671 Map<ClassDescriptor, JetType> superclassToSupertype = Maps.newHashMap();
672 for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
673 ClassifierDescriptor superclass = supertype.getConstructor().getDeclarationDescriptor();
674 assert superclass instanceof ClassDescriptor;
675 superclassToSupertype.put((ClassDescriptor) superclass, supertype);
676 }
677 return superclassToSupertype;
678 }
679
680 @NotNull
681 private static FunctionDescriptor substituteSuperFunction(
682 @NotNull Map<ClassDescriptor, JetType> superclassToSupertype,
683 @NotNull FunctionDescriptor superFun
684 ) {
685 DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration();
686 assert superFunContainer instanceof ClassDescriptor: superFunContainer;
687
688 JetType supertype = superclassToSupertype.get(superFunContainer);
689 assert supertype != null : "Couldn't find super type for super function: " + superFun;
690 TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype);
691
692 FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor);
693 assert substitutedSuperFun != null;
694 return substitutedSuperFun;
695 }
696
697 private static boolean isArrayType(@NotNull JetType type) {
698 KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
699 return builtIns.isArray(type) || builtIns.isPrimitiveArray(type);
700 }
701
702 private static void reportCantFindSuperFunction(@NotNull JavaMethod javaMethod) {
703 String errorMessage = "Can't find super function for " + javaMethod + " defined in " + javaMethod.getContainingClass();
704 if (SystemInfo.isMac) {
705 LOG.error("Remove duplicates from your JDK definition\n" + errorMessage);
706 }
707 else {
708 LOG.error(errorMessage);
709 }
710 }
711
712 private static class VarargCheckResult {
713 public final JetType parameterType;
714 public final boolean isVararg;
715
716 public VarargCheckResult(JetType parameterType, boolean isVararg) {
717 this.parameterType = parameterType;
718 this.isVararg = isVararg;
719 }
720 }
721
722 private static class TypeProjectionAndVariance {
723 public final TypeProjection typeProjection;
724 public final Variance varianceOfPosition;
725
726 public TypeProjectionAndVariance(TypeProjection typeProjection, Variance varianceOfPosition) {
727 this.typeProjection = typeProjection;
728 this.varianceOfPosition = varianceOfPosition;
729 }
730
731 public String toString() {
732 return typeProjection.toString();
733 }
734 }
735
736 static class TypeAndVariance {
737 public final JetType type;
738 public final Variance varianceOfPosition;
739
740 public TypeAndVariance(JetType type, Variance varianceOfPosition) {
741 this.type = type;
742 this.varianceOfPosition = varianceOfPosition;
743 }
744
745 public String toString() {
746 return type.toString();
747 }
748 }
749
750 private static class ValueParameters {
751 private final JetType receiverType;
752 private final List<ValueParameterDescriptor> descriptors;
753
754 public ValueParameters(@Nullable JetType receiverType, @NotNull List<ValueParameterDescriptor> descriptors) {
755 this.receiverType = receiverType;
756 this.descriptors = descriptors;
757 }
758 }
759 }