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