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