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