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