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