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 }