001 /* 002 * Copyright 2010-2015 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.kotlin.builtins; 018 019 import kotlin.KotlinPackage; 020 import kotlin.jvm.functions.Function1; 021 import org.jetbrains.annotations.NotNull; 022 import org.jetbrains.annotations.Nullable; 023 import org.jetbrains.kotlin.builtins.functions.BuiltInFictitiousFunctionClassFactory; 024 import org.jetbrains.kotlin.descriptors.*; 025 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; 026 import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptorImpl; 027 import org.jetbrains.kotlin.descriptors.annotations.Annotations; 028 import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl; 029 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; 030 import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl; 031 import org.jetbrains.kotlin.name.FqName; 032 import org.jetbrains.kotlin.name.FqNameUnsafe; 033 import org.jetbrains.kotlin.name.Name; 034 import org.jetbrains.kotlin.resolve.DescriptorUtils; 035 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant; 036 import org.jetbrains.kotlin.resolve.scopes.JetScope; 037 import org.jetbrains.kotlin.storage.LockBasedStorageManager; 038 import org.jetbrains.kotlin.types.*; 039 import org.jetbrains.kotlin.types.checker.JetTypeChecker; 040 041 import java.io.InputStream; 042 import java.util.*; 043 044 import static kotlin.KotlinPackage.*; 045 import static org.jetbrains.kotlin.builtins.PrimitiveType.*; 046 import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName; 047 048 public class KotlinBuiltIns { 049 public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin"); 050 public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME); 051 052 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 053 054 private static volatile KotlinBuiltIns instance = null; 055 056 private static volatile boolean initializing; 057 private static Throwable initializationFailed; 058 059 private static synchronized void initialize() { 060 if (instance == null) { 061 if (initializationFailed != null) { 062 throw new IllegalStateException( 063 "Built-in library initialization failed previously: " + initializationFailed, initializationFailed 064 ); 065 } 066 if (initializing) { 067 throw new IllegalStateException("Built-in library initialization loop"); 068 } 069 initializing = true; 070 try { 071 instance = new KotlinBuiltIns(); 072 instance.doInitialize(); 073 } 074 catch (Throwable e) { 075 initializationFailed = e; 076 throw new IllegalStateException("Built-in library initialization failed. " + 077 "Please ensure you have kotlin-runtime.jar in the classpath: " + e, e); 078 } 079 finally { 080 initializing = false; 081 } 082 } 083 } 084 085 @NotNull 086 public static KotlinBuiltIns getInstance() { 087 if (initializing) { 088 synchronized (KotlinBuiltIns.class) { 089 assert instance != null : "Built-ins are not initialized (note: We are under the same lock as initializing and instance)"; 090 return instance; 091 } 092 } 093 if (instance == null) { 094 initialize(); 095 } 096 return instance; 097 } 098 099 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 100 101 private final ModuleDescriptorImpl builtInsModule; 102 private final BuiltinsPackageFragment builtinsPackageFragment; 103 104 private final Map<PrimitiveType, JetType> primitiveTypeToArrayJetType; 105 private final Map<JetType, JetType> primitiveJetTypeToJetArrayType; 106 private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType; 107 108 public static final FqNames FQ_NAMES = new FqNames(); 109 110 private KotlinBuiltIns() { 111 LockBasedStorageManager storageManager = new LockBasedStorageManager(); 112 builtInsModule = new ModuleDescriptorImpl( 113 Name.special("<built-ins module>"), storageManager, ModuleParameters.Empty.INSTANCE$ 114 ); 115 116 PackageFragmentProvider packageFragmentProvider = BuiltinsPackage.createBuiltInPackageFragmentProvider( 117 storageManager, builtInsModule, 118 setOf(BUILT_INS_PACKAGE_FQ_NAME, BuiltinsPackage.getKOTLIN_REFLECT_FQ_NAME()), 119 new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule), 120 new Function1<String, InputStream>() { 121 @Override 122 public InputStream invoke(String path) { 123 return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path); 124 } 125 } 126 ); 127 128 builtInsModule.initialize(packageFragmentProvider); 129 builtInsModule.addDependencyOnModule(builtInsModule); 130 builtInsModule.seal(); 131 132 builtinsPackageFragment = (BuiltinsPackageFragment) single(packageFragmentProvider.getPackageFragments(BUILT_INS_PACKAGE_FQ_NAME)); 133 134 primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class); 135 primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>(); 136 jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>(); 137 } 138 139 private void doInitialize() { 140 for (PrimitiveType primitive : PrimitiveType.values()) { 141 makePrimitive(primitive); 142 } 143 } 144 145 private void makePrimitive(@NotNull PrimitiveType primitiveType) { 146 JetType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString()); 147 JetType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString()); 148 149 primitiveTypeToArrayJetType.put(primitiveType, arrayType); 150 primitiveJetTypeToJetArrayType.put(type, arrayType); 151 jetArrayTypeToPrimitiveJetType.put(arrayType, type); 152 } 153 154 public static class FqNames { 155 public final FqNameUnsafe any = fqNameUnsafe("Any"); 156 public final FqNameUnsafe nothing = fqNameUnsafe("Nothing"); 157 public final FqNameUnsafe cloneable = fqNameUnsafe("Cloneable"); 158 public final FqNameUnsafe suppress = fqNameUnsafe("suppress"); 159 public final FqNameUnsafe unit = fqNameUnsafe("Unit"); 160 public final FqNameUnsafe string = fqNameUnsafe("String"); 161 public final FqNameUnsafe array = fqNameUnsafe("Array"); 162 163 public final FqNameUnsafe _boolean = fqNameUnsafe("Boolean"); 164 public final FqNameUnsafe _char = fqNameUnsafe("Char"); 165 public final FqNameUnsafe _byte = fqNameUnsafe("Byte"); 166 public final FqNameUnsafe _short = fqNameUnsafe("Short"); 167 public final FqNameUnsafe _int = fqNameUnsafe("Int"); 168 public final FqNameUnsafe _long = fqNameUnsafe("Long"); 169 public final FqNameUnsafe _float = fqNameUnsafe("Float"); 170 public final FqNameUnsafe _double = fqNameUnsafe("Double"); 171 172 public final FqName data = fqName("data"); 173 public final FqName deprecated = fqName("deprecated"); 174 public final FqName tailRecursive = fqName("tailRecursive"); 175 public final FqName inline = fqName("inline"); 176 public final FqName noinline = fqName("noinline"); 177 public final FqName inlineOptions = fqName("inlineOptions"); 178 public final FqName extension = fqName("extension"); 179 180 public final FqNameUnsafe kClass = new FqName("kotlin.reflect.KClass").toUnsafe(); 181 182 public final Map<FqNameUnsafe, PrimitiveType> fqNameToPrimitiveType; 183 public final Map<FqNameUnsafe, PrimitiveType> arrayClassFqNameToPrimitiveType; 184 { 185 fqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0); 186 arrayClassFqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0); 187 for (PrimitiveType primitiveType : PrimitiveType.values()) { 188 fqNameToPrimitiveType.put(fqNameUnsafe(primitiveType.getTypeName().asString()), primitiveType); 189 arrayClassFqNameToPrimitiveType.put(fqNameUnsafe(primitiveType.getArrayTypeName().asString()), primitiveType); 190 } 191 } 192 193 @NotNull 194 private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) { 195 return fqName(simpleName).toUnsafe(); 196 } 197 198 @NotNull 199 private static FqName fqName(@NotNull String simpleName) { 200 return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName)); 201 } 202 } 203 204 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 205 206 @NotNull 207 public ModuleDescriptorImpl getBuiltInsModule() { 208 return builtInsModule; 209 } 210 211 @NotNull 212 public PackageFragmentDescriptor getBuiltInsPackageFragment() { 213 return builtinsPackageFragment; 214 } 215 216 @NotNull 217 public JetScope getBuiltInsPackageScope() { 218 return builtinsPackageFragment.getMemberScope(); 219 } 220 221 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 222 223 // GET CLASS 224 225 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 226 227 @NotNull 228 public ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName) { 229 ClassifierDescriptor classifier = getBuiltInsPackageFragment().getMemberScope().getClassifier(simpleName); 230 assert classifier instanceof ClassDescriptor : "Must be a class descriptor " + simpleName + ", but was " + classifier; 231 return (ClassDescriptor) classifier; 232 } 233 234 @NotNull 235 private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) { 236 return getBuiltInClassByName(Name.identifier(simpleName)); 237 } 238 239 // Special 240 241 @NotNull 242 public ClassDescriptor getAny() { 243 return getBuiltInClassByName("Any"); 244 } 245 246 @NotNull 247 public ClassDescriptor getNothing() { 248 return getBuiltInClassByName("Nothing"); 249 } 250 251 // Primitive 252 253 @NotNull 254 public ClassDescriptor getPrimitiveClassDescriptor(@NotNull PrimitiveType type) { 255 return getBuiltInClassByName(type.getTypeName().asString()); 256 } 257 258 @NotNull 259 public ClassDescriptor getByte() { 260 return getPrimitiveClassDescriptor(BYTE); 261 } 262 263 @NotNull 264 public ClassDescriptor getShort() { 265 return getPrimitiveClassDescriptor(SHORT); 266 } 267 268 @NotNull 269 public ClassDescriptor getInt() { 270 return getPrimitiveClassDescriptor(INT); 271 } 272 273 @NotNull 274 public ClassDescriptor getLong() { 275 return getPrimitiveClassDescriptor(LONG); 276 } 277 278 @NotNull 279 public ClassDescriptor getFloat() { 280 return getPrimitiveClassDescriptor(FLOAT); 281 } 282 283 @NotNull 284 public ClassDescriptor getDouble() { 285 return getPrimitiveClassDescriptor(DOUBLE); 286 } 287 288 @NotNull 289 public ClassDescriptor getChar() { 290 return getPrimitiveClassDescriptor(CHAR); 291 } 292 293 @NotNull 294 public ClassDescriptor getBoolean() { 295 return getPrimitiveClassDescriptor(BOOLEAN); 296 } 297 298 // Recognized 299 300 @NotNull 301 public Set<DeclarationDescriptor> getIntegralRanges() { 302 return KotlinPackage.<DeclarationDescriptor>setOf( 303 getBuiltInClassByName("ByteRange"), 304 getBuiltInClassByName("ShortRange"), 305 getBuiltInClassByName("CharRange"), 306 getBuiltInClassByName("IntRange") 307 ); 308 } 309 310 @NotNull 311 public ClassDescriptor getArray() { 312 return getBuiltInClassByName("Array"); 313 } 314 315 @NotNull 316 public ClassDescriptor getPrimitiveArrayClassDescriptor(@NotNull PrimitiveType type) { 317 return getBuiltInClassByName(type.getArrayTypeName().asString()); 318 } 319 320 @NotNull 321 public ClassDescriptor getNumber() { 322 return getBuiltInClassByName("Number"); 323 } 324 325 @NotNull 326 public ClassDescriptor getUnit() { 327 return getBuiltInClassByName("Unit"); 328 } 329 330 @NotNull 331 public ClassDescriptor getFunction(int parameterCount) { 332 return getBuiltInClassByName("Function" + parameterCount); 333 } 334 335 /** 336 * @return the descriptor representing the class kotlin.Function{parameterCount + 1} 337 * @deprecated there are no ExtensionFunction classes anymore, use {@link #getFunction(int)} instead 338 */ 339 @Deprecated 340 @NotNull 341 public ClassDescriptor getExtensionFunction(int parameterCount) { 342 return getBuiltInClassByName("Function" + (parameterCount + 1)); 343 } 344 345 @NotNull 346 public ClassDescriptor getThrowable() { 347 return getBuiltInClassByName("Throwable"); 348 } 349 350 @NotNull 351 public ClassDescriptor getCloneable() { 352 return getBuiltInClassByName("Cloneable"); 353 } 354 355 @NotNull 356 public ClassDescriptor getDataClassAnnotation() { 357 return getBuiltInClassByName("data"); 358 } 359 360 @NotNull 361 public ClassDescriptor getDeprecatedAnnotation() { 362 return getBuiltInClassByName("deprecated"); 363 } 364 365 @NotNull 366 public ClassDescriptor getString() { 367 return getBuiltInClassByName("String"); 368 } 369 370 @NotNull 371 public ClassDescriptor getCharSequence() { 372 return getBuiltInClassByName("CharSequence"); 373 } 374 375 @NotNull 376 public ClassDescriptor getComparable() { 377 return getBuiltInClassByName("Comparable"); 378 } 379 380 @NotNull 381 public ClassDescriptor getEnum() { 382 return getBuiltInClassByName("Enum"); 383 } 384 385 @NotNull 386 public ClassDescriptor getAnnotation() { 387 return getBuiltInClassByName("Annotation"); 388 } 389 390 @NotNull 391 public ClassDescriptor getIterator() { 392 return getBuiltInClassByName("Iterator"); 393 } 394 395 @NotNull 396 public ClassDescriptor getIterable() { 397 return getBuiltInClassByName("Iterable"); 398 } 399 400 @NotNull 401 public ClassDescriptor getMutableIterable() { 402 return getBuiltInClassByName("MutableIterable"); 403 } 404 405 @NotNull 406 public ClassDescriptor getMutableIterator() { 407 return getBuiltInClassByName("MutableIterator"); 408 } 409 410 @NotNull 411 public ClassDescriptor getCollection() { 412 return getBuiltInClassByName("Collection"); 413 } 414 415 @NotNull 416 public ClassDescriptor getMutableCollection() { 417 return getBuiltInClassByName("MutableCollection"); 418 } 419 420 @NotNull 421 public ClassDescriptor getList() { 422 return getBuiltInClassByName("List"); 423 } 424 425 @NotNull 426 public ClassDescriptor getMutableList() { 427 return getBuiltInClassByName("MutableList"); 428 } 429 430 @NotNull 431 public ClassDescriptor getSet() { 432 return getBuiltInClassByName("Set"); 433 } 434 435 @NotNull 436 public ClassDescriptor getMutableSet() { 437 return getBuiltInClassByName("MutableSet"); 438 } 439 440 @NotNull 441 public ClassDescriptor getMap() { 442 return getBuiltInClassByName("Map"); 443 } 444 445 @NotNull 446 public ClassDescriptor getMutableMap() { 447 return getBuiltInClassByName("MutableMap"); 448 } 449 450 @NotNull 451 public ClassDescriptor getMapEntry() { 452 ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMap(), "Entry"); 453 assert classDescriptor != null : "Can't find Map.Entry"; 454 return classDescriptor; 455 } 456 457 @NotNull 458 public ClassDescriptor getMutableMapEntry() { 459 ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMutableMap(), "MutableEntry"); 460 assert classDescriptor != null : "Can't find MutableMap.MutableEntry"; 461 return classDescriptor; 462 } 463 464 @NotNull 465 public ClassDescriptor getListIterator() { 466 return getBuiltInClassByName("ListIterator"); 467 } 468 469 @NotNull 470 public ClassDescriptor getMutableListIterator() { 471 return getBuiltInClassByName("MutableListIterator"); 472 } 473 474 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 475 476 // GET TYPE 477 478 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 479 480 @NotNull 481 private JetType getBuiltInTypeByClassName(@NotNull String classSimpleName) { 482 return getBuiltInClassByName(classSimpleName).getDefaultType(); 483 } 484 485 // Special 486 487 @NotNull 488 public JetType getNothingType() { 489 return getNothing().getDefaultType(); 490 } 491 492 @NotNull 493 public JetType getNullableNothingType() { 494 return TypeUtils.makeNullable(getNothingType()); 495 } 496 497 @NotNull 498 public JetType getAnyType() { 499 return getAny().getDefaultType(); 500 } 501 502 @NotNull 503 public JetType getNullableAnyType() { 504 return TypeUtils.makeNullable(getAnyType()); 505 } 506 507 // Primitive 508 509 @NotNull 510 public JetType getPrimitiveJetType(@NotNull PrimitiveType type) { 511 return getPrimitiveClassDescriptor(type).getDefaultType(); 512 } 513 514 @NotNull 515 public JetType getByteType() { 516 return getPrimitiveJetType(BYTE); 517 } 518 519 @NotNull 520 public JetType getShortType() { 521 return getPrimitiveJetType(SHORT); 522 } 523 524 @NotNull 525 public JetType getIntType() { 526 return getPrimitiveJetType(INT); 527 } 528 529 @NotNull 530 public JetType getLongType() { 531 return getPrimitiveJetType(LONG); 532 } 533 534 @NotNull 535 public JetType getFloatType() { 536 return getPrimitiveJetType(FLOAT); 537 } 538 539 @NotNull 540 public JetType getDoubleType() { 541 return getPrimitiveJetType(DOUBLE); 542 } 543 544 @NotNull 545 public JetType getCharType() { 546 return getPrimitiveJetType(CHAR); 547 } 548 549 @NotNull 550 public JetType getBooleanType() { 551 return getPrimitiveJetType(BOOLEAN); 552 } 553 554 // Recognized 555 556 @NotNull 557 public JetType getUnitType() { 558 return getUnit().getDefaultType(); 559 } 560 561 @NotNull 562 public JetType getStringType() { 563 return getString().getDefaultType(); 564 } 565 566 @NotNull 567 public JetType getArrayElementType(@NotNull JetType arrayType) { 568 if (isArray(arrayType)) { 569 if (arrayType.getArguments().size() != 1) { 570 throw new IllegalStateException(); 571 } 572 return arrayType.getArguments().get(0).getType(); 573 } 574 JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(TypeUtils.makeNotNullable(arrayType)); 575 if (primitiveType == null) { 576 throw new IllegalStateException("not array: " + arrayType); 577 } 578 return primitiveType; 579 } 580 581 @NotNull 582 public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) { 583 return primitiveTypeToArrayJetType.get(primitiveType); 584 } 585 586 /** 587 * @return {@code null} if not primitive 588 */ 589 @Nullable 590 public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) { 591 return primitiveJetTypeToJetArrayType.get(jetType); 592 } 593 594 @Nullable 595 public static PrimitiveType getPrimitiveTypeByFqName(@NotNull FqNameUnsafe primitiveClassFqName) { 596 return FQ_NAMES.fqNameToPrimitiveType.get(primitiveClassFqName); 597 } 598 599 @Nullable 600 public static PrimitiveType getPrimitiveTypeByArrayClassFqName(@NotNull FqNameUnsafe primitiveArrayClassFqName) { 601 return FQ_NAMES.arrayClassFqNameToPrimitiveType.get(primitiveArrayClassFqName); 602 } 603 604 @NotNull 605 public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) { 606 List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument)); 607 return new JetTypeImpl( 608 Annotations.EMPTY, 609 getArray().getTypeConstructor(), 610 false, 611 types, 612 getArray().getMemberScope(types) 613 ); 614 } 615 616 @NotNull 617 public JetType getEnumType(@NotNull JetType argument) { 618 Variance projectionType = Variance.INVARIANT; 619 List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument)); 620 return new JetTypeImpl( 621 Annotations.EMPTY, 622 getEnum().getTypeConstructor(), 623 false, 624 types, 625 getEnum().getMemberScope(types) 626 ); 627 } 628 629 @NotNull 630 public JetType getAnnotationType() { 631 return getAnnotation().getDefaultType(); 632 } 633 634 @NotNull 635 public ClassDescriptor getPropertyMetadata() { 636 return getBuiltInClassByName("PropertyMetadata"); 637 } 638 639 @NotNull 640 public ClassDescriptor getPropertyMetadataImpl() { 641 return getBuiltInClassByName("PropertyMetadataImpl"); 642 } 643 644 @NotNull 645 public AnnotationDescriptor createExtensionAnnotation() { 646 return new AnnotationDescriptorImpl(getBuiltInClassByName("extension").getDefaultType(), 647 Collections.<ValueParameterDescriptor, CompileTimeConstant<?>>emptyMap()); 648 } 649 650 private static boolean isTypeAnnotatedWithExtension(@NotNull JetType type) { 651 return type.getAnnotations().findAnnotation(FQ_NAMES.extension) != null; 652 } 653 654 @NotNull 655 public JetType getFunctionType( 656 @NotNull Annotations annotations, 657 @Nullable JetType receiverType, 658 @NotNull List<JetType> parameterTypes, 659 @NotNull JetType returnType 660 ) { 661 List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType); 662 int size = parameterTypes.size(); 663 ClassDescriptor classDescriptor = receiverType == null ? getFunction(size) : getExtensionFunction(size); 664 TypeConstructor constructor = classDescriptor.getTypeConstructor(); 665 666 Annotations typeAnnotations = receiverType == null ? annotations : addExtensionAnnotation(annotations); 667 668 return new JetTypeImpl(typeAnnotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments)); 669 } 670 671 @NotNull 672 private Annotations addExtensionAnnotation(@NotNull Annotations annotations) { 673 if (annotations.findAnnotation(FQ_NAMES.extension) != null) return annotations; 674 675 // TODO: preserve laziness of given annotations 676 return new AnnotationsImpl(plus(annotations, listOf(createExtensionAnnotation()))); 677 } 678 679 @NotNull 680 public static List<TypeProjection> getFunctionTypeArgumentProjections( 681 @Nullable JetType receiverType, 682 @NotNull List<JetType> parameterTypes, 683 @NotNull JetType returnType 684 ) { 685 List<TypeProjection> arguments = new ArrayList<TypeProjection>(); 686 if (receiverType != null) { 687 arguments.add(defaultProjection(receiverType)); 688 } 689 for (JetType parameterType : parameterTypes) { 690 arguments.add(defaultProjection(parameterType)); 691 } 692 arguments.add(defaultProjection(returnType)); 693 return arguments; 694 } 695 696 private static TypeProjection defaultProjection(JetType returnType) { 697 return new TypeProjectionImpl(Variance.INVARIANT, returnType); 698 } 699 700 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 701 702 // IS TYPE 703 704 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 705 706 public static boolean isArray(@NotNull JetType type) { 707 return isConstructedFromGivenClass(type, FQ_NAMES.array); 708 } 709 710 public static boolean isPrimitiveArray(@NotNull JetType type) { 711 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 712 return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null; 713 } 714 715 public static boolean isPrimitiveType(@NotNull JetType type) { 716 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 717 return !type.isMarkedNullable() && descriptor instanceof ClassDescriptor && isPrimitiveClass((ClassDescriptor) descriptor); 718 } 719 720 public static boolean isPrimitiveClass(@NotNull ClassDescriptor descriptor) { 721 return getPrimitiveTypeByFqName(getFqName(descriptor)) != null; 722 } 723 724 // Functions 725 726 public static boolean isFunctionOrExtensionFunctionType(@NotNull JetType type) { 727 return isFunctionType(type) || isExtensionFunctionType(type); 728 } 729 730 public static boolean isFunctionType(@NotNull JetType type) { 731 if (isExactFunctionType(type)) return true; 732 733 for (JetType superType : type.getConstructor().getSupertypes()) { 734 if (isFunctionType(superType)) return true; 735 } 736 737 return false; 738 } 739 740 public static boolean isExtensionFunctionType(@NotNull JetType type) { 741 if (isExactExtensionFunctionType(type)) return true; 742 743 for (JetType superType : type.getConstructor().getSupertypes()) { 744 if (isExtensionFunctionType(superType)) return true; 745 } 746 747 return false; 748 } 749 750 public static boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) { 751 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 752 return descriptor != null && isNumberedFunctionClassFqName(getFqName(descriptor)); 753 } 754 755 public static boolean isExactFunctionType(@NotNull JetType type) { 756 return isExactFunctionOrExtensionFunctionType(type) && !isTypeAnnotatedWithExtension(type); 757 } 758 759 public static boolean isExactExtensionFunctionType(@NotNull JetType type) { 760 return isExactFunctionOrExtensionFunctionType(type) && isTypeAnnotatedWithExtension(type); 761 } 762 763 /** 764 * @return true if this is an FQ name of a fictitious class representing the function type, 765 * e.g. kotlin.Function1 (but NOT kotlin.reflect.KFunction1) 766 */ 767 public static boolean isNumberedFunctionClassFqName(@NotNull FqNameUnsafe fqName) { 768 List<Name> segments = fqName.pathSegments(); 769 if (segments.size() != 2) return false; 770 771 if (!BUILT_INS_PACKAGE_NAME.equals(first(segments))) return false; 772 773 String shortName = last(segments).asString(); 774 return BuiltInFictitiousFunctionClassFactory.parseClassName(shortName, BUILT_INS_PACKAGE_FQ_NAME) != null; 775 } 776 777 @Nullable 778 public static JetType getReceiverType(@NotNull JetType type) { 779 assert isFunctionOrExtensionFunctionType(type) : type; 780 if (isExtensionFunctionType(type)) { 781 // TODO: this is incorrect when a class extends from an extension function and swaps type arguments 782 return type.getArguments().get(0).getType(); 783 } 784 return null; 785 } 786 787 @NotNull 788 public static List<ValueParameterDescriptor> getValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull JetType type) { 789 assert isFunctionOrExtensionFunctionType(type); 790 List<TypeProjection> parameterTypes = getParameterTypeProjectionsFromFunctionType(type); 791 List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(parameterTypes.size()); 792 for (int i = 0; i < parameterTypes.size(); i++) { 793 TypeProjection parameterType = parameterTypes.get(i); 794 ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl( 795 functionDescriptor, null, i, Annotations.EMPTY, 796 Name.identifier("p" + (i + 1)), parameterType.getType(), false, null, SourceElement.NO_SOURCE 797 ); 798 valueParameters.add(valueParameterDescriptor); 799 } 800 return valueParameters; 801 } 802 803 @NotNull 804 public static JetType getReturnTypeFromFunctionType(@NotNull JetType type) { 805 assert isFunctionOrExtensionFunctionType(type); 806 List<TypeProjection> arguments = type.getArguments(); 807 return arguments.get(arguments.size() - 1).getType(); 808 } 809 810 @NotNull 811 public static List<TypeProjection> getParameterTypeProjectionsFromFunctionType(@NotNull JetType type) { 812 assert isFunctionOrExtensionFunctionType(type); 813 List<TypeProjection> arguments = type.getArguments(); 814 int first = isExtensionFunctionType(type) ? 1 : 0; 815 int last = arguments.size() - 2; 816 List<TypeProjection> parameterTypes = new ArrayList<TypeProjection>(last - first + 1); 817 for (int i = first; i <= last; i++) { 818 parameterTypes.add(arguments.get(i)); 819 } 820 return parameterTypes; 821 } 822 823 // Recognized & special 824 825 private static boolean isConstructedFromGivenClass(@NotNull JetType type, @NotNull FqNameUnsafe fqName) { 826 ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); 827 return descriptor != null && fqName.equals(getFqName(descriptor)); 828 } 829 830 private static boolean isNotNullConstructedFromGivenClass(@NotNull JetType type, @NotNull FqNameUnsafe fqName) { 831 return !type.isMarkedNullable() && isConstructedFromGivenClass(type, fqName); 832 } 833 834 public static boolean isSpecialClassWithNoSupertypes(@NotNull ClassDescriptor descriptor) { 835 FqNameUnsafe fqName = getFqName(descriptor); 836 return FQ_NAMES.any.equals(fqName) || FQ_NAMES.nothing.equals(fqName); 837 } 838 839 public static boolean isAny(@NotNull ClassDescriptor descriptor) { 840 return isAny(getFqName(descriptor)); 841 } 842 843 public static boolean isBoolean(@NotNull JetType type) { 844 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._boolean); 845 } 846 847 public static boolean isBoolean(@NotNull ClassDescriptor classDescriptor) { 848 return FQ_NAMES._boolean.equals(getFqName(classDescriptor)); 849 } 850 851 public static boolean isChar(@NotNull JetType type) { 852 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._char); 853 } 854 855 public static boolean isInt(@NotNull JetType type) { 856 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._int); 857 } 858 859 public static boolean isByte(@NotNull JetType type) { 860 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._byte); 861 } 862 863 public static boolean isLong(@NotNull JetType type) { 864 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._long); 865 } 866 867 public static boolean isShort(@NotNull JetType type) { 868 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._short); 869 } 870 871 public static boolean isFloat(@NotNull JetType type) { 872 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._float); 873 } 874 875 public static boolean isDouble(@NotNull JetType type) { 876 return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._double); 877 } 878 879 private static boolean isConstructedFromGivenClassAndNotNullable(@NotNull JetType type, @NotNull FqNameUnsafe fqName) { 880 return isConstructedFromGivenClass(type, fqName) && !type.isMarkedNullable(); 881 } 882 883 public static boolean isAny(@NotNull FqNameUnsafe fqName) { 884 return FQ_NAMES.any.equals(fqName); 885 } 886 887 public static boolean isNothing(@NotNull JetType type) { 888 return isNothingOrNullableNothing(type) 889 && !type.isMarkedNullable(); 890 } 891 892 public static boolean isNullableNothing(@NotNull JetType type) { 893 return isNothingOrNullableNothing(type) 894 && type.isMarkedNullable(); 895 } 896 897 public static boolean isNothingOrNullableNothing(@NotNull JetType type) { 898 return isConstructedFromGivenClass(type, FQ_NAMES.nothing); 899 } 900 901 public static boolean isAnyOrNullableAny(@NotNull JetType type) { 902 return isConstructedFromGivenClass(type, FQ_NAMES.any); 903 } 904 905 public static boolean isNullableAny(@NotNull JetType type) { 906 return isAnyOrNullableAny(type) && type.isMarkedNullable(); 907 } 908 909 public static boolean isUnit(@NotNull JetType type) { 910 return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit); 911 } 912 913 public boolean isBooleanOrSubtype(@NotNull JetType type) { 914 return JetTypeChecker.DEFAULT.isSubtypeOf(type, getBooleanType()); 915 } 916 917 public static boolean isString(@Nullable JetType type) { 918 return type != null && isNotNullConstructedFromGivenClass(type, FQ_NAMES.string); 919 } 920 921 public static boolean isKClass(@NotNull ClassDescriptor descriptor) { 922 return FQ_NAMES.kClass.equals(getFqName(descriptor)); 923 } 924 925 public static boolean isNonPrimitiveArray(@NotNull ClassDescriptor descriptor) { 926 return FQ_NAMES.array.equals(getFqName(descriptor)); 927 } 928 929 public static boolean isCloneable(@NotNull ClassDescriptor descriptor) { 930 return FQ_NAMES.cloneable.equals(getFqName(descriptor)); 931 } 932 933 public static boolean isData(@NotNull ClassDescriptor classDescriptor) { 934 return containsAnnotation(classDescriptor, FQ_NAMES.data); 935 } 936 937 public static boolean isDeprecated(@NotNull DeclarationDescriptor declarationDescriptor) { 938 return containsAnnotation(declarationDescriptor, FQ_NAMES.deprecated); 939 } 940 941 public static boolean isTailRecursive(@NotNull DeclarationDescriptor declarationDescriptor) { 942 return containsAnnotation(declarationDescriptor, FQ_NAMES.tailRecursive); 943 } 944 945 /** Checks that the symbol represented by the descriptor is annotated with the {@code kotlin.noinline} annotation */ 946 public static boolean isNoinline(@NotNull DeclarationDescriptor descriptor) { 947 return containsAnnotation(descriptor, FQ_NAMES.noinline); 948 } 949 950 public static boolean isSuppressAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) { 951 return isConstructedFromGivenClass(annotationDescriptor.getType(), FQ_NAMES.suppress); 952 } 953 954 private static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) { 955 return descriptor.getOriginal().getAnnotations().findAnnotation(annotationClassFqName) != null; 956 } 957 958 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 959 960 @NotNull 961 public JetType getDefaultBound() { 962 return getNullableAnyType(); 963 } 964 965 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 966 967 // GET FUNCTION 968 969 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 970 971 @NotNull 972 public FunctionDescriptor getIdentityEquals() { 973 return KotlinPackage.first(getBuiltInsPackageFragment().getMemberScope().getFunctions(Name.identifier("identityEquals"))); 974 } 975 }