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 017package org.jetbrains.jet.lang.resolve.java.kotlinSignature; 018 019import com.google.common.collect.*; 020import com.intellij.openapi.diagnostic.Logger; 021import com.intellij.openapi.util.Pair; 022import com.intellij.openapi.util.SystemInfo; 023import com.intellij.psi.PsiClass; 024import com.intellij.psi.PsiElement; 025import com.intellij.psi.PsiManager; 026import com.intellij.psi.PsiMethod; 027import com.intellij.util.Function; 028import com.intellij.util.containers.ContainerUtil; 029import org.jetbrains.annotations.NotNull; 030import org.jetbrains.annotations.Nullable; 031import org.jetbrains.jet.lang.descriptors.*; 032import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; 033import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl; 034import org.jetbrains.jet.lang.resolve.BindingContext; 035import org.jetbrains.jet.lang.resolve.BindingContextUtils; 036import org.jetbrains.jet.lang.resolve.BindingTrace; 037import org.jetbrains.jet.lang.resolve.DescriptorUtils; 038import org.jetbrains.jet.lang.resolve.java.*; 039import org.jetbrains.jet.lang.resolve.java.provider.MembersCache; 040import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; 041import org.jetbrains.jet.lang.resolve.name.FqName; 042import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 043import org.jetbrains.jet.lang.resolve.name.Name; 044import org.jetbrains.jet.lang.resolve.scopes.JetScope; 045import org.jetbrains.jet.lang.types.*; 046import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 047 048import java.util.*; 049 050import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFQName; 051import static org.jetbrains.jet.lang.resolve.java.TypeUsage.*; 052import static org.jetbrains.jet.lang.types.Variance.INVARIANT; 053 054public 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}