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