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