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