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