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