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