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