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