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