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.Function1;
020    import kotlin.KotlinPackage;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.descriptors.*;
024    import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
025    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
026    import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
027    import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
028    import org.jetbrains.kotlin.name.FqName;
029    import org.jetbrains.kotlin.name.FqNameUnsafe;
030    import org.jetbrains.kotlin.name.Name;
031    import org.jetbrains.kotlin.platform.PlatformToKotlinClassMap;
032    import org.jetbrains.kotlin.resolve.DescriptorUtils;
033    import org.jetbrains.kotlin.resolve.ImportPath;
034    import org.jetbrains.kotlin.resolve.scopes.JetScope;
035    import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeCapabilitiesDeserializer;
036    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
037    import org.jetbrains.kotlin.types.*;
038    import org.jetbrains.kotlin.types.checker.JetTypeChecker;
039    
040    import java.io.InputStream;
041    import java.util.*;
042    
043    import static kotlin.KotlinPackage.single;
044    import static org.jetbrains.kotlin.builtins.PrimitiveType.*;
045    
046    public class KotlinBuiltIns {
047        public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier("kotlin");
048        public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME);
049    
050        public static final int FUNCTION_TRAIT_COUNT = 23;
051    
052        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
053    
054        private static volatile KotlinBuiltIns instance = null;
055    
056        private static volatile boolean initializing;
057        private static Throwable initializationFailed;
058    
059        private static synchronized void initialize() {
060            if (instance == null) {
061                if (initializationFailed != null) {
062                    throw new IllegalStateException(
063                            "Built-in library initialization failed previously: " + initializationFailed, initializationFailed
064                    );
065                }
066                if (initializing) {
067                    throw new IllegalStateException("Built-in library initialization loop");
068                }
069                initializing = true;
070                try {
071                    instance = new KotlinBuiltIns();
072                    instance.doInitialize();
073                }
074                catch (Throwable e) {
075                    initializationFailed = e;
076                    throw new IllegalStateException("Built-in library initialization failed. " +
077                                                    "Please ensure you have kotlin-runtime.jar in the classpath: " + e, e);
078                }
079                finally {
080                    initializing = false;
081                }
082            }
083        }
084    
085        @NotNull
086        public static KotlinBuiltIns getInstance() {
087            if (initializing) {
088                synchronized (KotlinBuiltIns.class) {
089                    assert instance != null : "Built-ins are not initialized (note: We are under the same lock as initializing and instance)";
090                    return instance;
091                }
092            }
093            if (instance == null) {
094                initialize();
095            }
096            return instance;
097        }
098    
099        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100    
101        private final ModuleDescriptorImpl builtInsModule;
102        private final BuiltinsPackageFragment builtinsPackageFragment;
103    
104        private final Map<PrimitiveType, JetType> primitiveTypeToNullableJetType;
105        private final Map<PrimitiveType, JetType> primitiveTypeToArrayJetType;
106        private final Map<JetType, JetType> primitiveJetTypeToJetArrayType;
107        private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
108    
109        public static final FqNames FQ_NAMES = new FqNames();
110    
111        private KotlinBuiltIns() {
112            builtInsModule = new ModuleDescriptorImpl(
113                    Name.special("<built-ins module>"), Collections.<ImportPath>emptyList(), PlatformToKotlinClassMap.EMPTY
114            );
115    
116            PackageFragmentProvider packageFragmentProvider = BuiltinsPackage.createBuiltInPackageFragmentProvider(
117                    new LockBasedStorageManager(), builtInsModule, Collections.singleton(BUILT_INS_PACKAGE_FQ_NAME),
118                    FlexibleTypeCapabilitiesDeserializer.ThrowException.INSTANCE$, new Function1<String, InputStream>() {
119                        @Override
120                        public InputStream invoke(String path) {
121                            return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
122                        }
123                    }
124            );
125    
126            builtInsModule.initialize(packageFragmentProvider);
127            builtInsModule.addDependencyOnModule(builtInsModule);
128            builtInsModule.seal();
129    
130            builtinsPackageFragment = (BuiltinsPackageFragment) single(packageFragmentProvider.getPackageFragments(BUILT_INS_PACKAGE_FQ_NAME));
131    
132            primitiveTypeToNullableJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
133            primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
134            primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
135            jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
136        }
137    
138        private void doInitialize() {
139            for (PrimitiveType primitive : PrimitiveType.values()) {
140                makePrimitive(primitive);
141            }
142        }
143    
144        private void makePrimitive(@NotNull PrimitiveType primitiveType) {
145            JetType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString());
146            JetType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString());
147    
148            primitiveTypeToNullableJetType.put(primitiveType, TypeUtils.makeNullable(type));
149            primitiveTypeToArrayJetType.put(primitiveType, arrayType);
150            primitiveJetTypeToJetArrayType.put(type, arrayType);
151            jetArrayTypeToPrimitiveJetType.put(arrayType, type);
152        }
153    
154        public static class FqNames {
155            public final FqNameUnsafe any = fqNameUnsafe("Any");
156            public final FqNameUnsafe nothing = fqNameUnsafe("Nothing");
157            public final FqNameUnsafe cloneable = fqNameUnsafe("Cloneable");
158            public final FqNameUnsafe suppress = fqNameUnsafe("suppress");
159            public final FqNameUnsafe unit = fqNameUnsafe("Unit");
160            public final FqNameUnsafe string = fqNameUnsafe("String");
161            public final FqNameUnsafe array = fqNameUnsafe("Array");
162    
163            public final FqName data = fqName("data");
164            public final FqName deprecated = fqName("deprecated");
165            public final FqName tailRecursive = fqName("tailRecursive");
166            public final FqName noinline = fqName("noinline");
167    
168            public final Set<FqNameUnsafe> primitiveTypes;
169            public final Set<FqNameUnsafe> primitiveArrays;
170            {
171                primitiveTypes = new HashSet<FqNameUnsafe>(0);
172                primitiveArrays = new HashSet<FqNameUnsafe>(0);
173                for (PrimitiveType primitiveType : PrimitiveType.values()) {
174                    primitiveTypes.add(fqNameUnsafe(primitiveType.getTypeName().asString()));
175                    primitiveArrays.add(fqNameUnsafe(primitiveType.getArrayTypeName().asString()));
176                }
177            }
178    
179            public final Set<FqNameUnsafe> functionClasses = computeIndexedFqNames("Function", FUNCTION_TRAIT_COUNT);
180            public final Set<FqNameUnsafe> extensionFunctionClasses = computeIndexedFqNames("ExtensionFunction", FUNCTION_TRAIT_COUNT);
181    
182            @NotNull
183            private static FqNameUnsafe fqNameUnsafe(@NotNull String simpleName) {
184                return fqName(simpleName).toUnsafe();
185            }
186    
187            private static FqName fqName(String simpleName) {
188                return BUILT_INS_PACKAGE_FQ_NAME.child(Name.identifier(simpleName));
189            }
190    
191            @NotNull
192            private static Set<FqNameUnsafe> computeIndexedFqNames(@NotNull String prefix, int count) {
193                Set<FqNameUnsafe> result = new HashSet<FqNameUnsafe>();
194                for (int i = 0; i < count; i++) {
195                    result.add(fqNameUnsafe(prefix + i));
196                }
197                return result;
198            }
199        }
200    
201        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
202    
203        @NotNull
204        public ModuleDescriptorImpl getBuiltInsModule() {
205            return builtInsModule;
206        }
207    
208        @NotNull
209        public PackageFragmentDescriptor getBuiltInsPackageFragment() {
210            return builtinsPackageFragment;
211        }
212    
213        @NotNull
214        public JetScope getBuiltInsPackageScope() {
215            return builtinsPackageFragment.getMemberScope();
216        }
217    
218        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219    
220        // GET CLASS
221    
222        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
223    
224        @NotNull
225        public ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName) {
226            ClassifierDescriptor classifier = getBuiltInsPackageFragment().getMemberScope().getClassifier(simpleName);
227            assert classifier instanceof ClassDescriptor : "Must be a class descriptor " + simpleName + ", but was " + classifier;
228            return (ClassDescriptor) classifier;
229        }
230    
231        @NotNull
232        private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) {
233            return getBuiltInClassByName(Name.identifier(simpleName));
234        }
235    
236        // Special
237    
238        @NotNull
239        public ClassDescriptor getAny() {
240            return getBuiltInClassByName("Any");
241        }
242    
243        @NotNull
244        public ClassDescriptor getNothing() {
245            return getBuiltInClassByName("Nothing");
246        }
247    
248        // Primitive
249    
250        @NotNull
251        public ClassDescriptor getPrimitiveClassDescriptor(@NotNull PrimitiveType type) {
252            return getBuiltInClassByName(type.getTypeName().asString());
253        }
254    
255        @NotNull
256        public ClassDescriptor getByte() {
257            return getPrimitiveClassDescriptor(BYTE);
258        }
259    
260        @NotNull
261        public ClassDescriptor getShort() {
262            return getPrimitiveClassDescriptor(SHORT);
263        }
264    
265        @NotNull
266        public ClassDescriptor getInt() {
267            return getPrimitiveClassDescriptor(INT);
268        }
269    
270        @NotNull
271        public ClassDescriptor getLong() {
272            return getPrimitiveClassDescriptor(LONG);
273        }
274    
275        @NotNull
276        public ClassDescriptor getFloat() {
277            return getPrimitiveClassDescriptor(FLOAT);
278        }
279    
280        @NotNull
281        public ClassDescriptor getDouble() {
282            return getPrimitiveClassDescriptor(DOUBLE);
283        }
284    
285        @NotNull
286        public ClassDescriptor getChar() {
287            return getPrimitiveClassDescriptor(CHAR);
288        }
289    
290        @NotNull
291        public ClassDescriptor getBoolean() {
292            return getPrimitiveClassDescriptor(BOOLEAN);
293        }
294    
295        // Recognized
296    
297        @NotNull
298        public Set<DeclarationDescriptor> getIntegralRanges() {
299            return KotlinPackage.<DeclarationDescriptor>setOf(
300                    getBuiltInClassByName("ByteRange"),
301                    getBuiltInClassByName("ShortRange"),
302                    getBuiltInClassByName("CharRange"),
303                    getBuiltInClassByName("IntRange")
304            );
305        }
306    
307        @NotNull
308        public ClassDescriptor getArray() {
309            return getBuiltInClassByName("Array");
310        }
311    
312        @NotNull
313        public ClassDescriptor getPrimitiveArrayClassDescriptor(@NotNull PrimitiveType type) {
314            return getBuiltInClassByName(type.getArrayTypeName().asString());
315        }
316    
317        @NotNull
318        public ClassDescriptor getNumber() {
319            return getBuiltInClassByName("Number");
320        }
321    
322        @NotNull
323        public ClassDescriptor getUnit() {
324            return getBuiltInClassByName("Unit");
325        }
326    
327        @NotNull
328        public ClassDescriptor getFunction(int parameterCount) {
329            return getBuiltInClassByName("Function" + parameterCount);
330        }
331    
332        @NotNull
333        public ClassDescriptor getExtensionFunction(int parameterCount) {
334            return getBuiltInClassByName("ExtensionFunction" + parameterCount);
335        }
336    
337        @NotNull
338        public ClassDescriptor getThrowable() {
339            return getBuiltInClassByName("Throwable");
340        }
341    
342        @NotNull
343        public ClassDescriptor getCloneable() {
344            return getBuiltInClassByName("Cloneable");
345        }
346    
347        @NotNull
348        public ClassDescriptor getDataClassAnnotation() {
349            return getBuiltInClassByName("data");
350        }
351    
352        @NotNull
353        public static FqName getNoinlineClassAnnotationFqName() {
354            return FQ_NAMES.noinline;
355        }
356    
357        @NotNull
358        public ClassDescriptor getInlineClassAnnotation() {
359            return getBuiltInClassByName("inline");
360        }
361    
362        @NotNull
363        public ClassDescriptor getInlineOptionsClassAnnotation() {
364            return getBuiltInClassByName("inlineOptions");
365        }
366    
367        @NotNull
368        public ClassDescriptor getDeprecatedAnnotation() {
369            return getBuiltInClassByName("deprecated");
370        }
371    
372        @NotNull
373        public ClassDescriptor getString() {
374            return getBuiltInClassByName("String");
375        }
376    
377        @NotNull
378        public ClassDescriptor getCharSequence() {
379            return getBuiltInClassByName("CharSequence");
380        }
381    
382        @NotNull
383        public ClassDescriptor getComparable() {
384            return getBuiltInClassByName("Comparable");
385        }
386    
387        @NotNull
388        public ClassDescriptor getEnum() {
389            return getBuiltInClassByName("Enum");
390        }
391    
392        @NotNull
393        public ClassDescriptor getAnnotation() {
394            return getBuiltInClassByName("Annotation");
395        }
396    
397        @NotNull
398        public ClassDescriptor getIterator() {
399            return getBuiltInClassByName("Iterator");
400        }
401    
402        @NotNull
403        public ClassDescriptor getIterable() {
404            return getBuiltInClassByName("Iterable");
405        }
406    
407        @NotNull
408        public ClassDescriptor getMutableIterable() {
409            return getBuiltInClassByName("MutableIterable");
410        }
411    
412        @NotNull
413        public ClassDescriptor getMutableIterator() {
414            return getBuiltInClassByName("MutableIterator");
415        }
416    
417        @NotNull
418        public ClassDescriptor getCollection() {
419            return getBuiltInClassByName("Collection");
420        }
421    
422        @NotNull
423        public ClassDescriptor getMutableCollection() {
424            return getBuiltInClassByName("MutableCollection");
425        }
426    
427        @NotNull
428        public ClassDescriptor getList() {
429            return getBuiltInClassByName("List");
430        }
431    
432        @NotNull
433        public ClassDescriptor getMutableList() {
434            return getBuiltInClassByName("MutableList");
435        }
436    
437        @NotNull
438        public ClassDescriptor getSet() {
439            return getBuiltInClassByName("Set");
440        }
441    
442        @NotNull
443        public ClassDescriptor getMutableSet() {
444            return getBuiltInClassByName("MutableSet");
445        }
446    
447        @NotNull
448        public ClassDescriptor getMap() {
449            return getBuiltInClassByName("Map");
450        }
451    
452        @NotNull
453        public ClassDescriptor getMutableMap() {
454            return getBuiltInClassByName("MutableMap");
455        }
456    
457        @NotNull
458        public ClassDescriptor getMapEntry() {
459            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMap(), "Entry");
460            assert classDescriptor != null : "Can't find Map.Entry";
461            return classDescriptor;
462        }
463    
464        @NotNull
465        public ClassDescriptor getMutableMapEntry() {
466            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getMutableMap(), "MutableEntry");
467            assert classDescriptor != null : "Can't find MutableMap.MutableEntry";
468            return classDescriptor;
469        }
470    
471        @NotNull
472        public ClassDescriptor getListIterator() {
473            return getBuiltInClassByName("ListIterator");
474        }
475    
476        @NotNull
477        public ClassDescriptor getMutableListIterator() {
478            return getBuiltInClassByName("MutableListIterator");
479        }
480    
481        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
482    
483        // GET TYPE
484    
485        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
486    
487        @NotNull
488        private JetType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
489            return getBuiltInClassByName(classSimpleName).getDefaultType();
490        }
491    
492        // Special
493    
494        @NotNull
495        public JetType getNothingType() {
496            return getNothing().getDefaultType();
497        }
498    
499        @NotNull
500        public JetType getNullableNothingType() {
501            return TypeUtils.makeNullable(getNothingType());
502        }
503    
504        @NotNull
505        public JetType getAnyType() {
506            return getAny().getDefaultType();
507        }
508    
509        @NotNull
510        public JetType getNullableAnyType() {
511            return TypeUtils.makeNullable(getAnyType());
512        }
513    
514        // Primitive
515    
516        @NotNull
517        public JetType getPrimitiveJetType(@NotNull PrimitiveType type) {
518            return getPrimitiveClassDescriptor(type).getDefaultType();
519        }
520    
521        @NotNull
522        public JetType getNullablePrimitiveJetType(@NotNull PrimitiveType primitiveType) {
523            return primitiveTypeToNullableJetType.get(primitiveType);
524        }
525    
526        @NotNull
527        public JetType getByteType() {
528            return getPrimitiveJetType(BYTE);
529        }
530    
531        @NotNull
532        public JetType getShortType() {
533            return getPrimitiveJetType(SHORT);
534        }
535    
536        @NotNull
537        public JetType getIntType() {
538            return getPrimitiveJetType(INT);
539        }
540    
541        @NotNull
542        public JetType getLongType() {
543            return getPrimitiveJetType(LONG);
544        }
545    
546        @NotNull
547        public JetType getFloatType() {
548            return getPrimitiveJetType(FLOAT);
549        }
550    
551        @NotNull
552        public JetType getDoubleType() {
553            return getPrimitiveJetType(DOUBLE);
554        }
555    
556        @NotNull
557        public JetType getCharType() {
558            return getPrimitiveJetType(CHAR);
559        }
560    
561        @NotNull
562        public JetType getBooleanType() {
563            return getPrimitiveJetType(BOOLEAN);
564        }
565    
566        // Recognized
567    
568        @NotNull
569        public JetType getUnitType() {
570            return getUnit().getDefaultType();
571        }
572    
573        @NotNull
574        public JetType getStringType() {
575            return getString().getDefaultType();
576        }
577    
578        @NotNull
579        public JetType getArrayElementType(@NotNull JetType arrayType) {
580            if (isArray(arrayType)) {
581                if (arrayType.getArguments().size() != 1) {
582                    throw new IllegalStateException();
583                }
584                return arrayType.getArguments().get(0).getType();
585            }
586            JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(TypeUtils.makeNotNullable(arrayType));
587            if (primitiveType == null) {
588                throw new IllegalStateException("not array: " + arrayType);
589            }
590            return primitiveType;
591        }
592    
593        @NotNull
594        public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) {
595            return primitiveTypeToArrayJetType.get(primitiveType);
596        }
597    
598        /**
599         * @return <code>null</code> if not primitive
600         */
601        @Nullable
602        public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) {
603            return primitiveJetTypeToJetArrayType.get(jetType);
604        }
605    
606        @NotNull
607        public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
608            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
609            return new JetTypeImpl(
610                    Annotations.EMPTY,
611                    getArray().getTypeConstructor(),
612                    false,
613                    types,
614                    getArray().getMemberScope(types)
615            );
616        }
617    
618        @NotNull
619        public JetType getEnumType(@NotNull JetType argument) {
620            Variance projectionType = Variance.INVARIANT;
621            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
622            return new JetTypeImpl(
623                    Annotations.EMPTY,
624                    getEnum().getTypeConstructor(),
625                    false,
626                    types,
627                    getEnum().getMemberScope(types)
628            );
629        }
630    
631        @NotNull
632        public JetType getAnnotationType() {
633            return getAnnotation().getDefaultType();
634        }
635    
636        @NotNull
637        public ClassDescriptor getPropertyMetadata() {
638            return getBuiltInClassByName("PropertyMetadata");
639        }
640    
641        @NotNull
642        public ClassDescriptor getPropertyMetadataImpl() {
643            return getBuiltInClassByName("PropertyMetadataImpl");
644        }
645    
646        @NotNull
647        public JetType getFunctionType(
648                @NotNull Annotations annotations,
649                @Nullable JetType receiverType,
650                @NotNull List<JetType> parameterTypes,
651                @NotNull JetType returnType
652        ) {
653            List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType);
654            int size = parameterTypes.size();
655            ClassDescriptor classDescriptor = receiverType == null ? getFunction(size) : getExtensionFunction(size);
656            TypeConstructor constructor = classDescriptor.getTypeConstructor();
657    
658            return new JetTypeImpl(annotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments));
659        }
660    
661        @NotNull
662        public static List<TypeProjection> getFunctionTypeArgumentProjections(
663                @Nullable JetType receiverType,
664                @NotNull List<JetType> parameterTypes,
665                @NotNull JetType returnType
666        ) {
667            List<TypeProjection> arguments = new ArrayList<TypeProjection>();
668            if (receiverType != null) {
669                arguments.add(defaultProjection(receiverType));
670            }
671            for (JetType parameterType : parameterTypes) {
672                arguments.add(defaultProjection(parameterType));
673            }
674            arguments.add(defaultProjection(returnType));
675            return arguments;
676        }
677    
678        private static TypeProjection defaultProjection(JetType returnType) {
679            return new TypeProjectionImpl(Variance.INVARIANT, returnType);
680        }
681    
682        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
683    
684        // IS TYPE
685    
686        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
687    
688        public static boolean isArray(@NotNull JetType type) {
689            return isConstructedFromGivenClass(type, FQ_NAMES.array);
690        }
691    
692        public static boolean isPrimitiveArray(@NotNull JetType type) {
693            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
694            return descriptor != null && FQ_NAMES.primitiveArrays.contains(DescriptorUtils.getFqName(descriptor));
695        }
696    
697        public static boolean isPrimitiveType(@NotNull JetType type) {
698            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
699            return !type.isMarkedNullable() && descriptor != null && FQ_NAMES.primitiveTypes.contains(DescriptorUtils.getFqName(descriptor));
700        }
701    
702        // Functions
703    
704        public static boolean isFunctionOrExtensionFunctionType(@NotNull JetType type) {
705            return isFunctionType(type) || isExtensionFunctionType(type);
706        }
707    
708        public static boolean isFunctionType(@NotNull JetType type) {
709            if (isExactFunctionType(type)) return true;
710    
711            for (JetType superType : type.getConstructor().getSupertypes()) {
712                if (isFunctionType(superType)) return true;
713            }
714    
715            return false;
716        }
717    
718        public static boolean isExtensionFunctionType(@NotNull JetType type) {
719            if (isExactExtensionFunctionType(type)) return true;
720    
721            for (JetType superType : type.getConstructor().getSupertypes()) {
722                if (isExtensionFunctionType(superType)) return true;
723            }
724    
725            return false;
726        }
727    
728        public static boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) {
729            return isExactFunctionType(type) || isExactExtensionFunctionType(type);
730        }
731    
732        public static boolean isExactFunctionType(@NotNull JetType type) {
733            return isTypeConstructorFqNameInSet(type, FQ_NAMES.functionClasses);
734        }
735    
736        public static boolean isExactExtensionFunctionType(@NotNull JetType type) {
737            return isTypeConstructorFqNameInSet(type, FQ_NAMES.extensionFunctionClasses);
738        }
739    
740        public static boolean isExactFunctionType(@NotNull FqNameUnsafe fqName) {
741            return FQ_NAMES.functionClasses.contains(fqName);
742        }
743    
744        public static boolean isExactExtensionFunctionType(@NotNull FqNameUnsafe fqName) {
745            return FQ_NAMES.extensionFunctionClasses.contains(fqName);
746        }
747    
748        private static boolean isTypeConstructorFqNameInSet(@NotNull JetType type, @NotNull Set<FqNameUnsafe> classes) {
749            ClassifierDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
750    
751            if (declarationDescriptor == null) return false;
752    
753            FqNameUnsafe fqName = DescriptorUtils.getFqName(declarationDescriptor);
754            return classes.contains(fqName);
755        }
756    
757        @Nullable
758        public static JetType getReceiverType(@NotNull JetType type) {
759            assert isFunctionOrExtensionFunctionType(type) : type;
760            if (isExtensionFunctionType(type)) {
761                return type.getArguments().get(0).getType();
762            }
763            return null;
764        }
765    
766        @NotNull
767        public static List<ValueParameterDescriptor> getValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull JetType type) {
768            assert isFunctionOrExtensionFunctionType(type);
769            List<TypeProjection> parameterTypes = getParameterTypeProjectionsFromFunctionType(type);
770            List<ValueParameterDescriptor> valueParameters = new ArrayList<ValueParameterDescriptor>(parameterTypes.size());
771            for (int i = 0; i < parameterTypes.size(); i++) {
772                TypeProjection parameterType = parameterTypes.get(i);
773                ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
774                        functionDescriptor, null, i, Annotations.EMPTY,
775                        Name.identifier("p" + (i + 1)), parameterType.getType(), false, null, SourceElement.NO_SOURCE
776                );
777                valueParameters.add(valueParameterDescriptor);
778            }
779            return valueParameters;
780        }
781    
782        @NotNull
783        public static JetType getReturnTypeFromFunctionType(@NotNull JetType type) {
784            assert isFunctionOrExtensionFunctionType(type);
785            List<TypeProjection> arguments = type.getArguments();
786            return arguments.get(arguments.size() - 1).getType();
787        }
788    
789        @NotNull
790        public static List<TypeProjection> getParameterTypeProjectionsFromFunctionType(@NotNull JetType type) {
791            assert isFunctionOrExtensionFunctionType(type);
792            List<TypeProjection> arguments = type.getArguments();
793            int first = isExtensionFunctionType(type) ? 1 : 0;
794            int last = arguments.size() - 2;
795            List<TypeProjection> parameterTypes = new ArrayList<TypeProjection>(last - first + 1);
796            for (int i = first; i <= last; i++) {
797                parameterTypes.add(arguments.get(i));
798            }
799            return parameterTypes;
800        }
801    
802        // Recognized & special
803    
804        private static boolean isConstructedFromGivenClass(@NotNull JetType type, @NotNull FqNameUnsafe fqName) {
805            ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor();
806            return descriptor != null && fqName.equals(DescriptorUtils.getFqName(descriptor));
807        }
808    
809        private static boolean isNotNullConstructedFromGivenClass(@NotNull JetType type, @NotNull FqNameUnsafe fqName) {
810            return !type.isMarkedNullable() && isConstructedFromGivenClass(type, fqName);
811        }
812    
813        public static boolean isSpecialClassWithNoSupertypes(@NotNull ClassDescriptor descriptor) {
814            FqNameUnsafe fqName = DescriptorUtils.getFqName(descriptor);
815            return FQ_NAMES.any.equals(fqName) || FQ_NAMES.nothing.equals(fqName);
816        }
817    
818        public static boolean isAny(@NotNull ClassDescriptor descriptor) {
819            return isAny(DescriptorUtils.getFqName(descriptor));
820        }
821    
822        public static boolean isAny(@NotNull FqNameUnsafe fqName) {
823            return FQ_NAMES.any.equals(fqName);
824        }
825    
826        public static boolean isNothing(@NotNull JetType type) {
827            return isNothingOrNullableNothing(type)
828                   && !type.isMarkedNullable();
829        }
830    
831        public static boolean isNullableNothing(@NotNull JetType type) {
832            return isNothingOrNullableNothing(type)
833                   && type.isMarkedNullable();
834        }
835    
836        public static boolean isNothingOrNullableNothing(@NotNull JetType type) {
837            return isConstructedFromGivenClass(type, FQ_NAMES.nothing);
838        }
839    
840        public static boolean isAnyOrNullableAny(@NotNull JetType type) {
841            return isConstructedFromGivenClass(type, FQ_NAMES.any);
842        }
843    
844        public static boolean isNullableAny(@NotNull JetType type) {
845            return isAnyOrNullableAny(type) && type.isMarkedNullable();
846        }
847    
848        public static boolean isUnit(@NotNull JetType type) {
849            return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit);
850        }
851    
852        public boolean isBooleanOrSubtype(@NotNull JetType type) {
853            return JetTypeChecker.DEFAULT.isSubtypeOf(type, getBooleanType());
854        }
855    
856        public static boolean isString(@Nullable JetType type) {
857            return type != null && isNotNullConstructedFromGivenClass(type, FQ_NAMES.string);
858        }
859    
860        public static boolean isCloneable(@NotNull ClassDescriptor descriptor) {
861            return FQ_NAMES.cloneable.equals(DescriptorUtils.getFqName(descriptor));
862        }
863    
864        public static boolean isData(@NotNull ClassDescriptor classDescriptor) {
865            return containsAnnotation(classDescriptor, FQ_NAMES.data);
866        }
867    
868        public static boolean isDeprecated(@NotNull DeclarationDescriptor declarationDescriptor) {
869            return containsAnnotation(declarationDescriptor, FQ_NAMES.deprecated);
870        }
871    
872        public static boolean isTailRecursive(@NotNull DeclarationDescriptor declarationDescriptor) {
873            return containsAnnotation(declarationDescriptor, FQ_NAMES.tailRecursive);
874        }
875    
876        public static boolean isSuppressAnnotation(@NotNull AnnotationDescriptor annotationDescriptor) {
877            return isConstructedFromGivenClass(annotationDescriptor.getType(), FQ_NAMES.suppress);
878        }
879    
880        static boolean containsAnnotation(DeclarationDescriptor descriptor, FqName annotationClassFqName) {
881            return descriptor.getOriginal().getAnnotations().findAnnotation(annotationClassFqName) != null;
882        }
883    
884        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
885    
886        @NotNull
887        public JetType getDefaultBound() {
888            return getNullableAnyType();
889        }
890    
891        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
892    
893        // GET FUNCTION
894    
895        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
896    
897        @NotNull
898        public FunctionDescriptor getIdentityEquals() {
899            return KotlinPackage.first(getBuiltInsPackageFragment().getMemberScope().getFunctions(Name.identifier("identityEquals")));
900        }
901    }