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