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.collections.SetsKt;
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.incremental.components.NoLookupLocation;
028    import org.jetbrains.kotlin.name.ClassId;
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.scopes.MemberScope;
034    import org.jetbrains.kotlin.serialization.deserialization.AdditionalSupertypes;
035    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
036    import org.jetbrains.kotlin.types.*;
037    import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
038    
039    import java.io.InputStream;
040    import java.util.*;
041    
042    import static kotlin.collections.CollectionsKt.single;
043    import static kotlin.collections.SetsKt.setOf;
044    import static org.jetbrains.kotlin.builtins.PrimitiveType.*;
045    import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
046    
047    public abstract class KotlinBuiltIns {
048        public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin");
049        public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME);
050        private static final FqName ANNOTATION_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("annotation"));
051        public static final FqName COLLECTIONS_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("collections"));
052        public static final FqName RANGES_PACKAGE_FQ_NAME = BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("ranges"));
053    
054        public static final Set<FqName> BUILT_INS_PACKAGE_FQ_NAMES = setOf(
055                BUILT_INS_PACKAGE_FQ_NAME,
056                COLLECTIONS_PACKAGE_FQ_NAME,
057                RANGES_PACKAGE_FQ_NAME,
058                ANNOTATION_PACKAGE_FQ_NAME,
059                ReflectionTypesKt.getKOTLIN_REFLECT_FQ_NAME(),
060                BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier("internal"))
061        );
062    
063        protected final ModuleDescriptorImpl builtInsModule;
064        private final BuiltInsPackageFragment builtInsPackageFragment;
065        private final BuiltInsPackageFragment collectionsPackageFragment;
066        private final BuiltInsPackageFragment rangesPackageFragment;
067        private final BuiltInsPackageFragment annotationPackageFragment;
068    
069        private final Set<BuiltInsPackageFragment> builtInsPackageFragments;
070    
071        private final Map<PrimitiveType, KotlinType> primitiveTypeToArrayKotlinType;
072        private final Map<KotlinType, KotlinType> primitiveKotlinTypeToKotlinArrayType;
073        private final Map<KotlinType, KotlinType> kotlinArrayTypeToPrimitiveKotlinType;
074        private final Map<FqName, BuiltInsPackageFragment> packageNameToPackageFragment;
075    
076        public static final FqNames FQ_NAMES = new FqNames();
077    
078        protected KotlinBuiltIns() {
079            LockBasedStorageManager storageManager = new LockBasedStorageManager();
080            builtInsModule = new ModuleDescriptorImpl(
081                    Name.special("<built-ins module>"), storageManager, ModuleParameters.Empty.INSTANCE, this
082            );
083    
084            PackageFragmentProvider packageFragmentProvider = BuiltInsPackageFragmentProviderKt.createBuiltInPackageFragmentProvider(
085                    storageManager, builtInsModule, BUILT_INS_PACKAGE_FQ_NAMES,
086                    new BuiltInFictitiousFunctionClassFactory(storageManager, builtInsModule),
087                    getAdditionalSupertypesProvider(),
088                    new Function1<String, InputStream>() {
089                        @Override
090                        public InputStream invoke(String path) {
091                            return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
092                        }
093                    }
094            );
095    
096            builtInsModule.initialize(packageFragmentProvider);
097            builtInsModule.setDependencies(builtInsModule);
098    
099            packageNameToPackageFragment = new LinkedHashMap<FqName, BuiltInsPackageFragment>();
100    
101            builtInsPackageFragment = createPackage(packageFragmentProvider, packageNameToPackageFragment, BUILT_INS_PACKAGE_FQ_NAME);
102            collectionsPackageFragment = createPackage(packageFragmentProvider, packageNameToPackageFragment, COLLECTIONS_PACKAGE_FQ_NAME);
103            rangesPackageFragment = createPackage(packageFragmentProvider, packageNameToPackageFragment, RANGES_PACKAGE_FQ_NAME);
104            annotationPackageFragment = createPackage(packageFragmentProvider, packageNameToPackageFragment, ANNOTATION_PACKAGE_FQ_NAME);
105    
106            builtInsPackageFragments = new LinkedHashSet<BuiltInsPackageFragment>(packageNameToPackageFragment.values());
107    
108            primitiveTypeToArrayKotlinType = new EnumMap<PrimitiveType, KotlinType>(PrimitiveType.class);
109            primitiveKotlinTypeToKotlinArrayType = new HashMap<KotlinType, KotlinType>();
110            kotlinArrayTypeToPrimitiveKotlinType = new HashMap<KotlinType, KotlinType>();
111            for (PrimitiveType primitive : PrimitiveType.values()) {
112                makePrimitive(primitive);
113            }
114        }
115    
116        @NotNull
117        protected AdditionalSupertypes getAdditionalSupertypesProvider() {
118            return AdditionalSupertypes.None.INSTANCE;
119        }
120    
121        private void makePrimitive(@NotNull PrimitiveType primitiveType) {
122            KotlinType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString());
123            KotlinType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString());
124    
125            primitiveTypeToArrayKotlinType.put(primitiveType, arrayType);
126            primitiveKotlinTypeToKotlinArrayType.put(type, arrayType);
127            kotlinArrayTypeToPrimitiveKotlinType.put(arrayType, type);
128        }
129    
130    
131        @NotNull
132        private static BuiltInsPackageFragment createPackage(
133                @NotNull PackageFragmentProvider fragmentProvider,
134                @NotNull Map<FqName, BuiltInsPackageFragment> packageNameToPackageFragment,
135                @NotNull FqName packageFqName
136        ) {
137            BuiltInsPackageFragment packageFragment = (BuiltInsPackageFragment) single(fragmentProvider.getPackageFragments(packageFqName));
138            packageNameToPackageFragment.put(packageFqName, packageFragment);
139            return packageFragment;
140        }
141    
142        @SuppressWarnings("WeakerAccess")
143        public static class FqNames {
144            public final FqNameUnsafe any = fqNameUnsafe("Any");
145            public final FqNameUnsafe nothing = fqNameUnsafe("Nothing");
146            public final FqNameUnsafe cloneable = fqNameUnsafe("Cloneable");
147            public final FqNameUnsafe suppress = fqNameUnsafe("Suppress");
148            public final FqNameUnsafe unit = fqNameUnsafe("Unit");
149            public final FqNameUnsafe charSequence = fqNameUnsafe("CharSequence");
150            public final FqNameUnsafe string = fqNameUnsafe("String");
151            public final FqNameUnsafe array = fqNameUnsafe("Array");
152    
153            public final FqNameUnsafe _boolean = fqNameUnsafe("Boolean");
154            public final FqNameUnsafe _char = fqNameUnsafe("Char");
155            public final FqNameUnsafe _byte = fqNameUnsafe("Byte");
156            public final FqNameUnsafe _short = fqNameUnsafe("Short");
157            public final FqNameUnsafe _int = fqNameUnsafe("Int");
158            public final FqNameUnsafe _long = fqNameUnsafe("Long");
159            public final FqNameUnsafe _float = fqNameUnsafe("Float");
160            public final FqNameUnsafe _double = fqNameUnsafe("Double");
161            public final FqNameUnsafe number = fqNameUnsafe("Number");
162    
163            public final FqNameUnsafe _enum = fqNameUnsafe("Enum");
164    
165    
166    
167            public final FqName throwable = fqName("Throwable");
168    
169            public final FqName deprecated = fqName("Deprecated");
170            public final FqName deprecationLevel = fqName("DeprecationLevel");
171            public final FqName extensionFunctionType = fqName("ExtensionFunctionType");
172            public final FqName target = annotationName("Target");
173            public final FqName annotationTarget = annotationName("AnnotationTarget");
174            public final FqName annotationRetention = annotationName("AnnotationRetention");
175            public final FqName retention = annotationName("Retention");
176            public final FqName repeatable = annotationName("Repeatable");
177            public final FqName mustBeDocumented = annotationName("MustBeDocumented");
178            public final FqName unsafeVariance = fqName("UnsafeVariance");
179    
180            public final FqName iterator = collectionsFqName("Iterator");
181            public final FqName iterable = collectionsFqName("Iterable");
182            public final FqName collection = collectionsFqName("Collection");
183            public final FqName list = collectionsFqName("List");
184            public final FqName listIterator = collectionsFqName("ListIterator");
185            public final FqName set = collectionsFqName("Set");
186            public final FqName map = collectionsFqName("Map");
187            public final FqName mapEntry = map.child(Name.identifier("Entry"));
188            public final FqName mutableIterator = collectionsFqName("MutableIterator");
189            public final FqName mutableIterable = collectionsFqName("MutableIterable");
190            public final FqName mutableCollection = collectionsFqName("MutableCollection");
191            public final FqName mutableList = collectionsFqName("MutableList");
192            public final FqName mutableListIterator = collectionsFqName("MutableListIterator");
193            public final FqName mutableSet = collectionsFqName("MutableSet");
194            public final FqName mutableMap = collectionsFqName("MutableMap");
195            public final FqName mutableMapEntry = mutableMap.child(Name.identifier("MutableEntry"));
196    
197            private final FqNameUnsafe _collection = collection.toUnsafe();
198            private final FqNameUnsafe _list = list.toUnsafe();
199            private final FqNameUnsafe _set = set.toUnsafe();
200            private final FqNameUnsafe _iterable = iterable.toUnsafe();
201    
202            public final FqNameUnsafe kClass = reflect("KClass");
203            public final FqNameUnsafe kCallable = reflect("KCallable");
204            public final FqNameUnsafe kMutableProperty0 = reflect("KMutableProperty0");
205            public final FqNameUnsafe kMutableProperty1 = reflect("KMutableProperty1");
206            public final FqNameUnsafe kMutableProperty2 = reflect("KMutableProperty2");
207            public final ClassId kProperty = ClassId.topLevel(reflect("KProperty").toSafe());
208    
209            public final Map<FqNameUnsafe, PrimitiveType> fqNameToPrimitiveType;
210            public final Map<FqNameUnsafe, PrimitiveType> arrayClassFqNameToPrimitiveType;
211            {
212                fqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0);
213                arrayClassFqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0);
214                for (PrimitiveType primitiveType : PrimitiveType.values()) {
215                    fqNameToPrimitiveType.put(fqNameUnsafe(primitiveType.getTypeName().asString()), primitiveType);
216                    arrayClassFqNameToPrimitiveType.put(fqNameUnsafe(primitiveType.getArrayTypeName().asString()), primitiveType);
217                }
218            }
219    
220            @NotNull
221            private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) {
222                return fqName(simpleName).toUnsafe();
223            }
224    
225            @NotNull
226            private static FqName fqName(@NotNull String simpleName) {
227                return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName));
228            }
229    
230            @NotNull
231            private static FqName collectionsFqName(@NotNull String simpleName) {
232                return COLLECTIONS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName));
233            }
234    
235            @NotNull
236            private static FqNameUnsafe reflect(@NotNull String simpleName) {
237                return ReflectionTypesKt.getKOTLIN_REFLECT_FQ_NAME().child(Name.identifier(simpleName)).toUnsafe();
238            }
239    
240            @NotNull
241            private static FqName annotationName(@NotNull String simpleName) {
242                return ANNOTATION_PACKAGE_FQ_NAME.child(Name.identifier(simpleName));
243            }
244        }
245    
246        @NotNull
247        public ModuleDescriptorImpl getBuiltInsModule() {
248            return builtInsModule;
249        }
250    
251        @NotNull
252        public Set<BuiltInsPackageFragment> getBuiltInsPackageFragments() {
253            return builtInsPackageFragments;
254        }
255    
256        @NotNull
257        public PackageFragmentDescriptor getBuiltInsPackageFragment() {
258            return builtInsPackageFragment;
259        }
260    
261        public boolean isBuiltInPackageFragment(@Nullable PackageFragmentDescriptor packageFragment) {
262            return packageFragment != null && packageFragment.getContainingDeclaration() == getBuiltInsModule();
263        }
264    
265        @NotNull
266        public MemberScope getBuiltInsPackageScope() {
267            return builtInsPackageFragment.getMemberScope();
268        }
269    
270        @NotNull
271        private ClassDescriptor getAnnotationClassByName(@NotNull Name simpleName) {
272            return getBuiltInClassByName(simpleName, annotationPackageFragment);
273        }
274    
275        @NotNull
276        public ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName) {
277            return getBuiltInClassByName(simpleName, getBuiltInsPackageFragment());
278        }
279    
280        @NotNull
281        private static ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName, @NotNull PackageFragmentDescriptor packageFragment) {
282            ClassDescriptor classDescriptor = getBuiltInClassByNameNullable(simpleName, packageFragment);
283            assert classDescriptor != null : "Built-in class " + simpleName + " is not found";
284            return classDescriptor;
285        }
286    
287        @Nullable
288        public ClassDescriptor getBuiltInClassByNameNullable(@NotNull Name simpleName) {
289            return getBuiltInClassByNameNullable(simpleName, getBuiltInsPackageFragment());
290        }
291    
292        @Nullable
293        public ClassDescriptor getBuiltInClassByFqNameNullable(@NotNull FqName fqName) {
294            if (!fqName.isRoot()) {
295                FqName parent = fqName.parent();
296                BuiltInsPackageFragment packageFragment = packageNameToPackageFragment.get(parent);
297                if (packageFragment != null) {
298                    return getBuiltInClassByNameNullable(fqName.shortName(), packageFragment);
299                }
300            }
301            return null;
302        }
303    
304        @Nullable
305        private static ClassDescriptor getBuiltInClassByNameNullable(@NotNull Name simpleName, @NotNull PackageFragmentDescriptor packageFragment) {
306            ClassifierDescriptor classifier = packageFragment.getMemberScope().getContributedClassifier(
307                    simpleName,
308                    NoLookupLocation.FROM_BUILTINS);
309    
310            assert classifier == null ||
311                   classifier instanceof ClassDescriptor : "Must be a class descriptor " + simpleName + ", but was " + classifier;
312            return (ClassDescriptor) classifier;
313        }
314    
315        @NotNull
316        private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) {
317            return getBuiltInClassByName(Name.identifier(simpleName));
318        }
319    
320        @NotNull
321        private static ClassDescriptor getBuiltInClassByName(@NotNull String simpleName, PackageFragmentDescriptor packageFragment) {
322            return getBuiltInClassByName(Name.identifier(simpleName), packageFragment);
323        }
324    
325        @NotNull
326        public ClassDescriptor getAny() {
327            return getBuiltInClassByName("Any");
328        }
329    
330        @NotNull
331        public ClassDescriptor getNothing() {
332            return getBuiltInClassByName("Nothing");
333        }
334    
335        @NotNull
336        public ClassDescriptor getPrimitiveClassDescriptor(@NotNull PrimitiveType type) {
337            return getBuiltInClassByName(type.getTypeName().asString());
338        }
339    
340        @NotNull
341        public ClassDescriptor getByte() {
342            return getPrimitiveClassDescriptor(BYTE);
343        }
344    
345        @NotNull
346        public ClassDescriptor getShort() {
347            return getPrimitiveClassDescriptor(SHORT);
348        }
349    
350        @NotNull
351        public ClassDescriptor getInt() {
352            return getPrimitiveClassDescriptor(INT);
353        }
354    
355        @NotNull
356        public ClassDescriptor getLong() {
357            return getPrimitiveClassDescriptor(LONG);
358        }
359    
360        @NotNull
361        public ClassDescriptor getFloat() {
362            return getPrimitiveClassDescriptor(FLOAT);
363        }
364    
365        @NotNull
366        public ClassDescriptor getDouble() {
367            return getPrimitiveClassDescriptor(DOUBLE);
368        }
369    
370        @NotNull
371        public ClassDescriptor getChar() {
372            return getPrimitiveClassDescriptor(CHAR);
373        }
374    
375        @NotNull
376        public ClassDescriptor getBoolean() {
377            return getPrimitiveClassDescriptor(BOOLEAN);
378        }
379    
380        @NotNull
381        public Set<DeclarationDescriptor> getIntegralRanges() {
382            return SetsKt.<DeclarationDescriptor>setOf(
383                    getBuiltInClassByName("CharRange", rangesPackageFragment),
384                    getBuiltInClassByName("IntRange", rangesPackageFragment)
385                    // TODO: contains in LongRange should be optimized too
386            );
387        }
388    
389        @NotNull
390        public ClassDescriptor getArray() {
391            return getBuiltInClassByName("Array");
392        }
393    
394        @NotNull
395        public ClassDescriptor getPrimitiveArrayClassDescriptor(@NotNull PrimitiveType type) {
396            return getBuiltInClassByName(type.getArrayTypeName().asString());
397        }
398    
399        @NotNull
400        public ClassDescriptor getNumber() {
401            return getBuiltInClassByName("Number");
402        }
403    
404        @NotNull
405        public ClassDescriptor getUnit() {
406            return getBuiltInClassByName("Unit");
407        }
408    
409        @NotNull
410        public static String getFunctionName(int parameterCount) {
411            return "Function" + parameterCount;
412        }
413    
414        @NotNull
415        public ClassDescriptor getFunction(int parameterCount) {
416            return getBuiltInClassByName(getFunctionName(parameterCount));
417        }
418    
419        @NotNull
420        public ClassDescriptor getThrowable() {
421            return getBuiltInClassByName("Throwable");
422        }
423    
424        @NotNull
425        public ClassDescriptor getCloneable() {
426            return getBuiltInClassByName("Cloneable");
427        }
428    
429        @NotNull
430        public ClassDescriptor getDeprecatedAnnotation() {
431            return getBuiltInClassByName(FQ_NAMES.deprecated.shortName());
432        }
433    
434        @Nullable
435        private static ClassDescriptor getEnumEntry(@NotNull ClassDescriptor enumDescriptor, @NotNull String entryName) {
436            ClassifierDescriptor result = enumDescriptor.getUnsubstitutedInnerClassesScope().getContributedClassifier(
437                    Name.identifier(entryName), NoLookupLocation.FROM_BUILTINS
438            );
439            return result instanceof ClassDescriptor ? (ClassDescriptor) result : null;
440        }
441    
442        @Nullable
443        public ClassDescriptor getDeprecationLevelEnumEntry(@NotNull String level) {
444            return getEnumEntry(getBuiltInClassByName(FQ_NAMES.deprecationLevel.shortName()), level);
445        }
446    
447        @NotNull
448        public ClassDescriptor getTargetAnnotation() {
449            return getAnnotationClassByName(FQ_NAMES.target.shortName());
450        }
451    
452        @NotNull
453        public ClassDescriptor getRetentionAnnotation() {
454            return getAnnotationClassByName(FQ_NAMES.retention.shortName());
455        }
456    
457        @NotNull
458        public ClassDescriptor getRepeatableAnnotation() {
459            return getAnnotationClassByName(FQ_NAMES.repeatable.shortName());
460        }
461    
462        @NotNull
463        public ClassDescriptor getMustBeDocumentedAnnotation() {
464            return getAnnotationClassByName(FQ_NAMES.mustBeDocumented.shortName());
465        }
466    
467        @Nullable
468        public ClassDescriptor getAnnotationTargetEnumEntry(@NotNull KotlinTarget target) {
469            return getEnumEntry(getAnnotationClassByName(FQ_NAMES.annotationTarget.shortName()), target.name());
470        }
471    
472        @Nullable
473        public ClassDescriptor getAnnotationRetentionEnumEntry(@NotNull KotlinRetention retention) {
474            return getEnumEntry(getAnnotationClassByName(FQ_NAMES.annotationRetention.shortName()), retention.name());
475        }
476    
477        @NotNull
478        public ClassDescriptor getString() {
479            return getBuiltInClassByName("String");
480        }
481    
482        @NotNull
483        public ClassDescriptor getCharSequence() {
484            return getBuiltInClassByName("CharSequence");
485        }
486    
487        @NotNull
488        public ClassDescriptor getComparable() {
489            return getBuiltInClassByName("Comparable");
490        }
491    
492        @NotNull
493        public ClassDescriptor getEnum() {
494            return getBuiltInClassByName("Enum");
495        }
496    
497        @NotNull
498        public ClassDescriptor getAnnotation() {
499            return getBuiltInClassByName("Annotation");
500        }
501    
502        @NotNull
503        public ClassDescriptor getIterator() {
504            return getBuiltInClassByName("Iterator", collectionsPackageFragment);
505        }
506    
507        @NotNull
508        public ClassDescriptor getIterable() {
509            return getBuiltInClassByName("Iterable", collectionsPackageFragment);
510        }
511    
512        @NotNull
513        public ClassDescriptor getMutableIterable() {
514            return getBuiltInClassByName("MutableIterable", collectionsPackageFragment);
515        }
516    
517        @NotNull
518        public ClassDescriptor getMutableIterator() {
519            return getBuiltInClassByName("MutableIterator", collectionsPackageFragment);
520        }
521    
522        @NotNull
523        public ClassDescriptor getCollection() {
524            return getBuiltInClassByName("Collection", collectionsPackageFragment);
525        }
526    
527        @NotNull
528        public ClassDescriptor getMutableCollection() {
529            return getBuiltInClassByName("MutableCollection", collectionsPackageFragment);
530        }
531    
532        @NotNull
533        public ClassDescriptor getList() {
534            return getBuiltInClassByName("List", collectionsPackageFragment);
535        }
536    
537        @NotNull
538        public ClassDescriptor getMutableList() {
539            return getBuiltInClassByName("MutableList", collectionsPackageFragment);
540        }
541    
542        @NotNull
543        public ClassDescriptor getSet() {
544            return getBuiltInClassByName("Set", collectionsPackageFragment);
545        }
546    
547        @NotNull
548        public ClassDescriptor getMutableSet() {
549            return getBuiltInClassByName("MutableSet", collectionsPackageFragment);
550        }
551    
552        @NotNull
553        public ClassDescriptor getMap() {
554            return getBuiltInClassByName("Map", collectionsPackageFragment);
555        }
556    
557        @NotNull
558        public ClassDescriptor getMutableMap() {
559            return getBuiltInClassByName("MutableMap", collectionsPackageFragment);
560        }
561    
562        @NotNull
563        public ClassDescriptor getMapEntry() {
564            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMap(), "Entry", NoLookupLocation.FROM_BUILTINS);
565            assert classDescriptor != null : "Can't find Map.Entry";
566            return classDescriptor;
567        }
568    
569        @NotNull
570        public ClassDescriptor getMutableMapEntry() {
571            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMutableMap(), "MutableEntry", NoLookupLocation.FROM_BUILTINS);
572            assert classDescriptor != null : "Can't find MutableMap.MutableEntry";
573            return classDescriptor;
574        }
575    
576        @NotNull
577        public ClassDescriptor getListIterator() {
578            return getBuiltInClassByName("ListIterator", collectionsPackageFragment);
579        }
580    
581        @NotNull
582        public ClassDescriptor getMutableListIterator() {
583            return getBuiltInClassByName("MutableListIterator", collectionsPackageFragment);
584        }
585    
586        @NotNull
587        private KotlinType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
588            return getBuiltInClassByName(classSimpleName).getDefaultType();
589        }
590    
591        @NotNull
592        public KotlinType getNothingType() {
593            return getNothing().getDefaultType();
594        }
595    
596        @NotNull
597        public KotlinType getNullableNothingType() {
598            return TypeUtils.makeNullable(getNothingType());
599        }
600    
601        @NotNull
602        public KotlinType getAnyType() {
603            return getAny().getDefaultType();
604        }
605    
606        @NotNull
607        public KotlinType getNullableAnyType() {
608            return TypeUtils.makeNullable(getAnyType());
609        }
610    
611        @NotNull
612        public KotlinType getDefaultBound() {
613            return getNullableAnyType();
614        }
615    
616        @NotNull
617        public KotlinType getPrimitiveKotlinType(@NotNull PrimitiveType type) {
618            return getPrimitiveClassDescriptor(type).getDefaultType();
619        }
620    
621        @NotNull
622        public KotlinType getByteType() {
623            return getPrimitiveKotlinType(BYTE);
624        }
625    
626        @NotNull
627        public KotlinType getShortType() {
628            return getPrimitiveKotlinType(SHORT);
629        }
630    
631        @NotNull
632        public KotlinType getIntType() {
633            return getPrimitiveKotlinType(INT);
634        }
635    
636        @NotNull
637        public KotlinType getLongType() {
638            return getPrimitiveKotlinType(LONG);
639        }
640    
641        @NotNull
642        public KotlinType getFloatType() {
643            return getPrimitiveKotlinType(FLOAT);
644        }
645    
646        @NotNull
647        public KotlinType getDoubleType() {
648            return getPrimitiveKotlinType(DOUBLE);
649        }
650    
651        @NotNull
652        public KotlinType getCharType() {
653            return getPrimitiveKotlinType(CHAR);
654        }
655    
656        @NotNull
657        public KotlinType getBooleanType() {
658            return getPrimitiveKotlinType(BOOLEAN);
659        }
660    
661        @NotNull
662        public KotlinType getUnitType() {
663            return getUnit().getDefaultType();
664        }
665    
666        @NotNull
667        public KotlinType getStringType() {
668            return getString().getDefaultType();
669        }
670    
671        @NotNull
672        public KotlinType getArrayElementType(@NotNull KotlinType arrayType) {
673            if (isArray(arrayType)) {
674                if (arrayType.getArguments().size() != 1) {
675                    throw new IllegalStateException();
676                }
677                return arrayType.getArguments().get(0).getType();
678            }
679            KotlinType primitiveType = kotlinArrayTypeToPrimitiveKotlinType.get(TypeUtils.makeNotNullable(arrayType));
680            if (primitiveType == null) {
681                throw new IllegalStateException("not array: " + arrayType);
682            }
683            return primitiveType;
684        }
685    
686        @NotNull
687        public KotlinType getPrimitiveArrayKotlinType(@NotNull PrimitiveType primitiveType) {
688            return primitiveTypeToArrayKotlinType.get(primitiveType);
689        }
690    
691        /**
692         * @return {@code null} if not primitive
693         */
694        @Nullable
695        public KotlinType getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(@NotNull KotlinType kotlinType) {
696            return primitiveKotlinTypeToKotlinArrayType.get(kotlinType);
697        }
698    
699        public static boolean isPrimitiveArray(@NotNull FqNameUnsafe arrayFqName) {
700            return getPrimitiveTypeByArrayClassFqName(arrayFqName) != null;
701        }
702    
703        @Nullable
704        public static PrimitiveType getPrimitiveTypeByFqName(@NotNull FqNameUnsafe primitiveClassFqName) {
705            return FQ_NAMES.fqNameToPrimitiveType.get(primitiveClassFqName);
706        }
707    
708        @Nullable
709        public static PrimitiveType getPrimitiveTypeByArrayClassFqName(@NotNull FqNameUnsafe primitiveArrayClassFqName) {
710            return FQ_NAMES.arrayClassFqNameToPrimitiveType.get(primitiveArrayClassFqName);
711        }
712    
713        @NotNull
714        public KotlinType getArrayType(@NotNull Variance projectionType, @NotNull KotlinType argument) {
715            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
716            return KotlinTypeImpl.create(
717                    Annotations.Companion.getEMPTY(),
718                    getArray(),
719                    false,
720                    types
721            );
722        }
723    
724        @NotNull
725        public KotlinType getEnumType(@NotNull KotlinType argument) {
726            Variance projectionType = Variance.INVARIANT;
727            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
728            return KotlinTypeImpl.create(
729                    Annotations.Companion.getEMPTY(),
730                    getEnum(),
731                    false,
732                    types
733            );
734        }
735    
736        @NotNull
737        public KotlinType getAnnotationType() {
738            return getAnnotation().getDefaultType();
739        }
740    
741        public static boolean isArray(@NotNull KotlinType type) {
742            return isConstructedFromGivenClass(type, FQ_NAMES.array);
743        }
744    
745        public static boolean isArrayOrPrimitiveArray(@NotNull ClassDescriptor descriptor) {
746            return classFqNameEquals(descriptor, FQ_NAMES.array) || getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
747        }
748    
749        public static boolean isPrimitiveArray(@NotNull KotlinType type) {
750            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
751            return descriptor != null && getPrimitiveTypeByArrayClassFqName(getFqName(descriptor)) != null;
752        }
753    
754        public static boolean isPrimitiveType(@NotNull KotlinType type) {
755            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
756            return !type.isMarkedNullable() && descriptor instanceof ClassDescriptor && isPrimitiveClass((ClassDescriptor) descriptor);
757        }
758    
759        public static boolean isPrimitiveClass(@NotNull ClassDescriptor descriptor) {
760            return getPrimitiveTypeByFqName(getFqName(descriptor)) != null;
761        }
762    
763        private static boolean isConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
764            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
765            return descriptor instanceof ClassDescriptor && classFqNameEquals(descriptor, fqName);
766        }
767    
768        private static boolean classFqNameEquals(@NotNull ClassifierDescriptor descriptor, @NotNull FqNameUnsafe fqName) {
769            // Quick check to avoid creation of full FqName instance
770            return descriptor.getName().equals(fqName.shortName()) &&
771                   fqName.equals(getFqName(descriptor));
772        }
773    
774        private static boolean isNotNullConstructedFromGivenClass(@NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
775            return !type.isMarkedNullable() && isConstructedFromGivenClass(type, fqName);
776        }
777    
778        public static boolean isSpecialClassWithNoSupertypes(@NotNull ClassDescriptor descriptor) {
779            return classFqNameEquals(descriptor, FQ_NAMES.any) || classFqNameEquals(descriptor, FQ_NAMES.nothing);
780        }
781    
782        public static boolean isAny(@NotNull ClassDescriptor descriptor) {
783            return classFqNameEquals(descriptor, FQ_NAMES.any);
784        }
785    
786        public static boolean isAny(@NotNull KotlinType type) {
787            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES.any);
788        }
789    
790        public static boolean isBoolean(@NotNull KotlinType type) {
791            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._boolean);
792        }
793    
794        public static boolean isBooleanOrNullableBoolean(@NotNull KotlinType type) {
795            return isConstructedFromGivenClass(type, FQ_NAMES._boolean);
796        }
797    
798        public static boolean isBoolean(@NotNull ClassDescriptor classDescriptor) {
799            return classFqNameEquals(classDescriptor, FQ_NAMES._boolean);
800        }
801    
802        public static boolean isChar(@NotNull KotlinType type) {
803            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._char);
804        }
805    
806        public static boolean isInt(@NotNull KotlinType type) {
807            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._int);
808        }
809    
810        public static boolean isByte(@NotNull KotlinType type) {
811            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._byte);
812        }
813    
814        public static boolean isLong(@NotNull KotlinType type) {
815            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._long);
816        }
817    
818        public static boolean isShort(@NotNull KotlinType type) {
819            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._short);
820        }
821    
822        public static boolean isFloat(@NotNull KotlinType type) {
823            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._float);
824        }
825    
826        public static boolean isDouble(@NotNull KotlinType type) {
827            return isConstructedFromGivenClassAndNotNullable(type, FQ_NAMES._double);
828        }
829    
830        private static boolean isConstructedFromGivenClassAndNotNullable(@NotNull KotlinType type, @NotNull FqNameUnsafe fqName) {
831            return isConstructedFromGivenClass(type, fqName) && !type.isMarkedNullable();
832        }
833    
834        public static boolean isNothing(@NotNull KotlinType type) {
835            return isNothingOrNullableNothing(type)
836                   && !type.isMarkedNullable();
837        }
838    
839        public static boolean isNullableNothing(@NotNull KotlinType type) {
840            return isNothingOrNullableNothing(type)
841                   && type.isMarkedNullable();
842        }
843    
844        public static boolean isNothingOrNullableNothing(@NotNull KotlinType type) {
845            return isConstructedFromGivenClass(type, FQ_NAMES.nothing);
846        }
847    
848        public static boolean isAnyOrNullableAny(@NotNull KotlinType type) {
849            return isConstructedFromGivenClass(type, FQ_NAMES.any);
850        }
851    
852        public static boolean isNullableAny(@NotNull KotlinType type) {
853            return isAnyOrNullableAny(type) && type.isMarkedNullable();
854        }
855    
856        public static boolean isDefaultBound(@NotNull KotlinType type) {
857            return isNullableAny(type);
858        }
859    
860        public static boolean isUnit(@NotNull KotlinType type) {
861            return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit);
862        }
863    
864        public static boolean isUnitOrNullableUnit(@NotNull KotlinType type) {
865            return isConstructedFromGivenClass(type, FQ_NAMES.unit);
866        }
867    
868        public boolean isBooleanOrSubtype(@NotNull KotlinType type) {
869            return KotlinTypeChecker.DEFAULT.isSubtypeOf(type, getBooleanType());
870        }
871    
872        public boolean isMemberOfAny(@NotNull DeclarationDescriptor descriptor) {
873            return descriptor.getContainingDeclaration() == getAny();
874        }
875    
876        public static boolean isString(@Nullable KotlinType type) {
877            return type != null && isNotNullConstructedFromGivenClass(type, FQ_NAMES.string);
878        }
879    
880        public static boolean isCharSequenceOrNullableCharSequence(@Nullable KotlinType type) {
881            return type != null && isConstructedFromGivenClass(type, FQ_NAMES.charSequence);
882        }
883    
884        public static boolean isStringOrNullableString(@Nullable KotlinType type) {
885            return type != null && isConstructedFromGivenClass(type, FQ_NAMES.string);
886        }
887    
888        public static boolean isCollectionOrNullableCollection(@NotNull KotlinType type) {
889            return isConstructedFromGivenClass(type, FQ_NAMES._collection);
890        }
891    
892        public static boolean isListOrNullableList(@NotNull KotlinType type) {
893            return isConstructedFromGivenClass(type, FQ_NAMES._list);
894        }
895    
896        public static boolean isSetOrNullableSet(@NotNull KotlinType type) {
897            return isConstructedFromGivenClass(type, FQ_NAMES._set);
898        }
899    
900        public static boolean isIterableOrNullableIterable(@NotNull KotlinType type) {
901            return isConstructedFromGivenClass(type, FQ_NAMES._iterable);
902        }
903    
904        public static boolean isKClass(@NotNull ClassDescriptor descriptor) {
905            return classFqNameEquals(descriptor, FQ_NAMES.kClass);
906        }
907    
908        public static boolean isNonPrimitiveArray(@NotNull ClassDescriptor descriptor) {
909            return classFqNameEquals(descriptor, FQ_NAMES.array);
910        }
911    
912        public static boolean isCloneable(@NotNull ClassDescriptor descriptor) {
913            return classFqNameEquals(descriptor, FQ_NAMES.cloneable);
914        }
915    
916        public static boolean isDeprecated(@NotNull DeclarationDescriptor declarationDescriptor) {
917            if (containsAnnotation(declarationDescriptor, FQ_NAMES.deprecated)) return true;
918    
919            if (declarationDescriptor instanceof PropertyDescriptor) {
920                boolean isVar = ((PropertyDescriptor) declarationDescriptor).isVar();
921                PropertyGetterDescriptor getter = ((PropertyDescriptor) declarationDescriptor).getGetter();
922                PropertySetterDescriptor setter = ((PropertyDescriptor) declarationDescriptor).getSetter();
923                return getter != null && isDeprecated(getter) && (!isVar || setter != null && isDeprecated(setter));
924            }
925    
926            return false;
927        }
928    
929        public static boolean isSuppressAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
930            return isConstructedFromGivenClass(annotationDescriptor.getType(), FQ_NAMES.suppress);
931        }
932    
933        private static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) {
934            DeclarationDescriptor original = descriptor.getOriginal();
935            Annotations annotations = original.getAnnotations();
936    
937            if (annotations.findAnnotation(annotationClassFqName) != null) return true;
938    
939            AnnotationUseSiteTarget associatedUseSiteTarget = AnnotationUseSiteTarget.Companion.getAssociatedUseSiteTarget(descriptor);
940            if (associatedUseSiteTarget != null) {
941                if (Annotations.Companion.findUseSiteTargetedAnnotation(annotations, associatedUseSiteTarget, annotationClassFqName) != null) {
942                    return true;
943                }
944            }
945    
946            return false;
947        }
948    }