001    /*
002     * Copyright 2010-2012 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 com.google.common.collect.ImmutableSet;
020    import com.google.common.collect.Lists;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.jet.lang.DefaultModuleConfiguration;
024    import org.jetbrains.jet.lang.ModuleConfiguration;
025    import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
026    import org.jetbrains.jet.lang.descriptors.*;
027    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
028    import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl;
029    import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
030    import org.jetbrains.jet.lang.psi.JetPsiUtil;
031    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
032    import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
033    import org.jetbrains.jet.lang.resolve.name.FqName;
034    import org.jetbrains.jet.lang.resolve.name.Name;
035    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
036    import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
037    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
038    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
039    import org.jetbrains.jet.lang.types.*;
040    
041    import java.io.IOException;
042    import java.util.*;
043    
044    import static org.jetbrains.jet.lang.types.lang.PrimitiveType.*;
045    
046    public class KotlinBuiltIns {
047        public static final JetScope STUB = JetScope.EMPTY;
048    
049        public static final String BUILT_INS_PACKAGE_NAME_STRING = "jet";
050        public static final Name BUILT_INS_PACKAGE_NAME = Name.identifier(BUILT_INS_PACKAGE_NAME_STRING);
051        public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME);
052    
053        public static final int FUNCTION_TRAIT_COUNT = 23;
054    
055        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
056    
057        private static volatile KotlinBuiltIns instance = null;
058    
059        private static volatile boolean initializing;
060        private static Throwable initializationFailed;
061    
062        private static synchronized void initialize() {
063            if (instance == null) {
064                if (initializationFailed != null) {
065                    throw new RuntimeException(
066                            "builtin library initialization failed previously: " + initializationFailed, initializationFailed);
067                }
068                if (initializing) {
069                    throw new IllegalStateException("builtin library initialization loop");
070                }
071                initializing = true;
072                try {
073                    instance = new KotlinBuiltIns();
074                    instance.doInitialize();
075                }
076                catch (Throwable e) {
077                    initializationFailed = e;
078                    throw new RuntimeException("builtin library initialization failed: " + e, e);
079                }
080                finally {
081                    initializing = false;
082                }
083            }
084        }
085    
086        @NotNull
087        public static KotlinBuiltIns getInstance() {
088            if (initializing) {
089                synchronized (KotlinBuiltIns.class) {
090                    assert instance != null : "Built-ins are not initialized (note: We are under the same lock as initializing and instance)";
091                    return instance;
092                }
093            }
094            if (instance == null) {
095                initialize();
096            }
097            return instance;
098        }
099    
100        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
101    
102        private final ModuleDescriptorImpl builtInsModule;
103    
104        private volatile ImmutableSet<ClassDescriptor> nonPhysicalClasses;
105    
106        private final ImmutableSet<ClassDescriptor> functionClassesSet;
107    
108        private final ImmutableSet<ClassDescriptor> extensionFunctionClassesSet;
109    
110        private final EnumMap<PrimitiveType, ClassDescriptor> primitiveTypeToClass;
111        private final EnumMap<PrimitiveType, ClassDescriptor> primitiveTypeToArrayClass;
112        private final EnumMap<PrimitiveType, JetType> primitiveTypeToJetType;
113        private final EnumMap<PrimitiveType, JetType> primitiveTypeToNullableJetType;
114        private final EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
115        private final Map<JetType, JetType> primitiveJetTypeToJetArrayType;
116        private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
117    
118        private final ClassDescriptor nothingClass;
119        private final ClassDescriptor arrayClass;
120        private final ClassDescriptor deprecatedAnnotationClass;
121        private final ClassDescriptor dataAnnotationClass;
122        private final ClassDescriptor[] functionClasses;
123    
124        private volatile JetType anyType;
125        private volatile JetType nullableAnyType;
126        private volatile JetType nothingType;
127        private volatile JetType nullableNothingType;
128        private volatile JetType unitType;
129        private volatile JetType stringType;
130        private volatile JetType annotationType;
131    
132        private KotlinBuiltIns() {
133            try {
134                this.builtInsModule = new ModuleDescriptorImpl(Name.special("<built-ins lazy module>"),
135                                                               DefaultModuleConfiguration.DEFAULT_JET_IMPORTS,
136                                                               PlatformToKotlinClassMap.EMPTY);
137                builtInsModule.setModuleConfiguration(ModuleConfiguration.EMPTY);
138                loadBuiltIns(builtInsModule);
139    
140                this.functionClassesSet = computeIndexedClasses("Function", FUNCTION_TRAIT_COUNT);
141                this.extensionFunctionClassesSet = computeIndexedClasses("ExtensionFunction", FUNCTION_TRAIT_COUNT);
142    
143                this.primitiveTypeToClass = new EnumMap<PrimitiveType, ClassDescriptor>(PrimitiveType.class);
144                this.primitiveTypeToJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
145                this.primitiveTypeToNullableJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
146                this.primitiveTypeToArrayClass = new EnumMap<PrimitiveType, ClassDescriptor>(PrimitiveType.class);
147                this.primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
148                this.primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
149                this.jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
150    
151                this.nothingClass = getBuiltInClassByName("Nothing");
152                this.arrayClass = getBuiltInClassByName("Array");
153                this.deprecatedAnnotationClass = getBuiltInClassByName("deprecated");
154                this.dataAnnotationClass = getBuiltInClassByName("data");
155                this.functionClasses = new ClassDescriptor[FUNCTION_TRAIT_COUNT];
156                for (int i = 0; i < functionClasses.length; i++) {
157                    functionClasses[i] = getBuiltInClassByName("Function" + i);
158                }
159            }
160            catch (IOException e) {
161                throw new IllegalStateException(e);
162            }
163        }
164    
165        private static void loadBuiltIns(@NotNull ModuleDescriptorImpl module) throws IOException {
166            NamespaceDescriptorImpl rootNamespace =
167                            new NamespaceDescriptorImpl(module, Collections.<AnnotationDescriptor>emptyList(), JetPsiUtil.ROOT_NAMESPACE_NAME);
168            rootNamespace.initialize(
169                    new WritableScopeImpl(JetScope.EMPTY, rootNamespace, RedeclarationHandler.DO_NOTHING, "members of root namespace"));
170    
171            module.setRootNamespace(rootNamespace);
172    
173            rootNamespace.getMemberScope().addNamespace(new BuiltinsNamespaceDescriptorImpl(new LockBasedStorageManager(), rootNamespace));
174            rootNamespace.getMemberScope().changeLockLevel(WritableScope.LockLevel.READING);
175        }
176    
177        private void doInitialize() {
178            anyType = getBuiltInTypeByClassName("Any");
179            nullableAnyType = TypeUtils.makeNullable(anyType);
180            nothingType = getBuiltInTypeByClassName("Nothing");
181            nullableNothingType = TypeUtils.makeNullable(nothingType);
182            unitType = getBuiltInTypeByClassName("Unit");
183            stringType = getBuiltInTypeByClassName("String");
184            annotationType = getBuiltInTypeByClassName("Annotation");
185    
186            for (PrimitiveType primitive : PrimitiveType.values()) {
187                makePrimitive(primitive);
188            }
189    
190            nonPhysicalClasses = computeNonPhysicalClasses();
191        }
192    
193        private void makePrimitive(PrimitiveType primitiveType) {
194            ClassDescriptor theClass = getBuiltInClassByName(primitiveType.getTypeName().asString());
195            JetType type = new JetTypeImpl(theClass);
196            ClassDescriptor arrayClass = getBuiltInClassByName(primitiveType.getArrayTypeName().asString());
197            JetType arrayType = new JetTypeImpl(arrayClass);
198    
199            primitiveTypeToClass.put(primitiveType, theClass);
200            primitiveTypeToJetType.put(primitiveType, type);
201            primitiveTypeToNullableJetType.put(primitiveType, TypeUtils.makeNullable(type));
202            primitiveTypeToArrayClass.put(primitiveType, arrayClass);
203            primitiveTypeToArrayJetType.put(primitiveType, arrayType);
204            primitiveJetTypeToJetArrayType.put(type, arrayType);
205            jetArrayTypeToPrimitiveJetType.put(arrayType, type);
206        }
207    
208        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209    
210        @NotNull
211        public ModuleDescriptorImpl getBuiltInsModule() {
212            return builtInsModule;
213        }
214    
215        @NotNull
216        public NamespaceDescriptor getBuiltInsPackage() {
217            NamespaceDescriptor namespace = getBuiltInsModule().getNamespace(BUILT_INS_PACKAGE_FQ_NAME);
218            assert namespace != null : "Built ins namespace not found: " + BUILT_INS_PACKAGE_FQ_NAME;
219            return namespace;
220        }
221    
222        @NotNull
223        public FqName getBuiltInsPackageFqName() {
224            return getBuiltInsPackage().getFqName();
225        }
226    
227        @NotNull
228        public JetScope getBuiltInsScope() {
229            return getBuiltInsPackage().getMemberScope();
230        }
231    
232        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
233    
234        // GET CLASS
235    
236        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
237    
238        @NotNull
239        public ClassDescriptor getBuiltInClassByName(@NotNull Name simpleName) {
240            ClassifierDescriptor classifier = getBuiltInsScope().getClassifier(simpleName);
241            assert 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 ImmutableSet.<DeclarationDescriptor>of(
314                    getBuiltInClassByName("ByteRange"),
315                    getBuiltInClassByName("ShortRange"),
316                    getBuiltInClassByName("CharRange"),
317                    getBuiltInClassByName("IntRange"),
318                    getBuiltInClassByName("LongRange")
319            );
320        }
321    
322        @NotNull
323        public ClassDescriptor getArray() {
324            return getBuiltInClassByName("Array");
325        }
326    
327        @NotNull
328        public ClassDescriptor getPrimitiveArrayClassDescriptor(@NotNull PrimitiveType type) {
329            return getBuiltInClassByName(type.getArrayTypeName().asString());
330        }
331    
332        @NotNull
333        public ClassDescriptor getNumber() {
334            return getBuiltInClassByName("Number");
335        }
336    
337        @NotNull
338        public ClassDescriptor getUnit() {
339            return getBuiltInClassByName("Unit");
340        }
341    
342        @NotNull
343        public ClassDescriptor getFunction(int parameterCount) {
344            return getBuiltInClassByName("Function" + parameterCount);
345        }
346    
347        @NotNull
348        public ClassDescriptor getExtensionFunction(int parameterCount) {
349            return getBuiltInClassByName("ExtensionFunction" + parameterCount);
350        }
351    
352        @NotNull
353        public ClassDescriptor getKFunction(int parameterCount) {
354            return getBuiltInClassByName("KFunction" + parameterCount);
355        }
356    
357        @NotNull
358        public ClassDescriptor getKMemberFunction(int parameterCount) {
359            return getBuiltInClassByName("KMemberFunction" + parameterCount);
360        }
361    
362        @NotNull
363        public ClassDescriptor getKExtensionFunction(int parameterCount) {
364            return getBuiltInClassByName("KExtensionFunction" + parameterCount);
365        }
366    
367        @NotNull
368        public ClassDescriptor getThrowable() {
369            return getBuiltInClassByName("Throwable");
370        }
371    
372        @NotNull
373        public ClassDescriptor getDataClassAnnotation() {
374            return getBuiltInClassByName("data");
375        }
376    
377        @NotNull
378        public ClassDescriptor getVolatileAnnotationClass() {
379            return getBuiltInClassByName("volatile");
380        }
381    
382        @NotNull
383        public ClassDescriptor getDeprecatedAnnotation() {
384            return getBuiltInClassByName("deprecated");
385        }
386    
387        @NotNull
388        public ClassDescriptor getString() {
389            return getBuiltInClassByName("String");
390        }
391    
392        @NotNull
393        public ClassDescriptor getCharSequence() {
394            return getBuiltInClassByName("CharSequence");
395        }
396    
397        @NotNull
398        public ClassDescriptor getComparable() {
399            return getBuiltInClassByName("Comparable");
400        }
401    
402        @NotNull
403        public ClassDescriptor getEnum() {
404            return getBuiltInClassByName("Enum");
405        }
406    
407        @NotNull
408        public ClassDescriptor getAnnotation() {
409            return getBuiltInClassByName("Annotation");
410        }
411    
412        @NotNull
413        public ClassDescriptor getIterator() {
414            return getBuiltInClassByName("Iterator");
415        }
416    
417        @NotNull
418        public ClassDescriptor getIterable() {
419            return getBuiltInClassByName("Iterable");
420        }
421    
422        @NotNull
423        public ClassDescriptor getMutableIterable() {
424            return getBuiltInClassByName("MutableIterable");
425        }
426    
427        @NotNull
428        public ClassDescriptor getMutableIterator() {
429            return getBuiltInClassByName("MutableIterator");
430        }
431    
432        @NotNull
433        public ClassDescriptor getCollection() {
434            return getBuiltInClassByName("Collection");
435        }
436    
437        @NotNull
438        public ClassDescriptor getMutableCollection() {
439            return getBuiltInClassByName("MutableCollection");
440        }
441    
442        @NotNull
443        public ClassDescriptor getList() {
444            return getBuiltInClassByName("List");
445        }
446    
447        @NotNull
448        public ClassDescriptor getMutableList() {
449            return getBuiltInClassByName("MutableList");
450        }
451    
452        @NotNull
453        public ClassDescriptor getSet() {
454            return getBuiltInClassByName("Set");
455        }
456    
457        @NotNull
458        public ClassDescriptor getMutableSet() {
459            return getBuiltInClassByName("MutableSet");
460        }
461    
462        @NotNull
463        public ClassDescriptor getMap() {
464            return getBuiltInClassByName("Map");
465        }
466    
467        @NotNull
468        public ClassDescriptor getMutableMap() {
469            return getBuiltInClassByName("MutableMap");
470        }
471    
472        @NotNull
473        public ClassDescriptor getMapEntry() {
474            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getBuiltInClassByName("Map"), "Entry");
475            assert classDescriptor != null : "Can't find Map.Entry";
476            return classDescriptor;
477        }
478    
479        @NotNull
480        public ClassDescriptor getMutableMapEntry() {
481            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getBuiltInClassByName("MutableMap"), "MutableEntry");
482            assert classDescriptor != null : "Can't find MutableMap.MutableEntry";
483            return classDescriptor;
484        }
485    
486        @NotNull
487        public ClassDescriptor getListIterator() {
488            return getBuiltInClassByName("ListIterator");
489        }
490    
491        @NotNull
492        public ClassDescriptor getMutableListIterator() {
493            return getBuiltInClassByName("MutableListIterator");
494        }
495    
496        /**
497         * Classes that only exist for the Kotlin compiler: they are erased at runtime.
498         * As a consequence they, for example, shouldn't be referred to by other languages
499         * (e.g. Java).
500         */
501        @NotNull
502        public Set<ClassDescriptor> getNonPhysicalClasses() {
503            return nonPhysicalClasses;
504        }
505    
506        @NotNull
507        private ImmutableSet<ClassDescriptor> computeNonPhysicalClasses() {
508            ImmutableSet.Builder<ClassDescriptor> nonPhysical = ImmutableSet.builder();
509            nonPhysical.add(
510                    getAny(),
511                    getNothing(),
512    
513                    getNumber(),
514                    getString(),
515                    getCharSequence(),
516                    getThrowable(),
517                    getBuiltInClassByName("Hashable"),
518    
519                    getIterator(),
520                    getIterable(),
521                    getCollection(),
522                    getList(),
523                    getListIterator(),
524                    getSet(),
525                    getMap(),
526                    getMapEntry(),
527    
528                    getMutableIterator(),
529                    getMutableIterable(),
530                    getMutableCollection(),
531                    getMutableList(),
532                    getMutableListIterator(),
533                    getMutableSet(),
534                    getMutableMap(),
535                    getMutableMapEntry(),
536    
537                    getVolatileAnnotationClass(),
538                    getDataClassAnnotation(),
539                    getAnnotation(),
540                    getComparable(),
541                    getEnum(),
542                    getArray()
543            );
544    
545            for (PrimitiveType primitiveType : values()) {
546                nonPhysical.add(getPrimitiveClassDescriptor(primitiveType));
547                nonPhysical.add(getPrimitiveArrayClassDescriptor(primitiveType));
548            }
549    
550            return nonPhysical.build();
551        }
552    
553        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
554    
555        // GET TYPE
556    
557        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
558    
559        @NotNull
560        private JetType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
561            // TODO
562            return new JetTypeImpl(getBuiltInClassByName(classSimpleName));
563        }
564    
565        // Special
566    
567        @NotNull
568        public JetType getNothingType() {
569            return getBuiltInTypeByClassName("Nothing");
570        }
571    
572        @NotNull
573        public JetType getNullableNothingType() {
574            // TODO
575            return TypeUtils.makeNullable(getNothingType());
576        }
577    
578        @NotNull
579        public JetType getAnyType() {
580            return getBuiltInTypeByClassName("Any");
581        }
582    
583        @NotNull
584        public JetType getNullableAnyType() {
585            // TODO
586            return TypeUtils.makeNullable(getAnyType());
587        }
588    
589        // Primitive
590    
591        @NotNull
592        public JetType getPrimitiveJetType(@NotNull PrimitiveType type) {
593            // TODO
594            return new JetTypeImpl(getPrimitiveClassDescriptor(type));
595        }
596    
597        @NotNull
598        public JetType getNullablePrimitiveJetType(@NotNull PrimitiveType primitiveType) {
599            return primitiveTypeToNullableJetType.get(primitiveType);
600        }
601    
602        @NotNull
603        public JetType getByteType() {
604            return getPrimitiveJetType(BYTE);
605        }
606    
607        @NotNull
608        public JetType getShortType() {
609            return getPrimitiveJetType(SHORT);
610        }
611    
612        @NotNull
613        public JetType getIntType() {
614            return getPrimitiveJetType(INT);
615        }
616    
617        @NotNull
618        public JetType getLongType() {
619            return getPrimitiveJetType(LONG);
620        }
621    
622        @NotNull
623        public JetType getFloatType() {
624            return getPrimitiveJetType(FLOAT);
625        }
626    
627        @NotNull
628        public JetType getDoubleType() {
629            return getPrimitiveJetType(DOUBLE);
630        }
631    
632        @NotNull
633        public JetType getCharType() {
634            return getPrimitiveJetType(CHAR);
635        }
636    
637        @NotNull
638        public JetType getBooleanType() {
639            return getPrimitiveJetType(BOOLEAN);
640        }
641    
642        // Recognized
643    
644        @NotNull
645        public JetType getUnitType() {
646            return getBuiltInTypeByClassName("Unit");
647        }
648    
649        @NotNull
650        public JetType getStringType() {
651            return getBuiltInTypeByClassName("String");
652        }
653    
654        @NotNull
655        public JetType getArrayElementType(@NotNull JetType arrayType) {
656            if (arrayType.getConstructor().getDeclarationDescriptor() == getArray()) {
657                if (arrayType.getArguments().size() != 1) {
658                    throw new IllegalStateException();
659                }
660                return arrayType.getArguments().get(0).getType();
661            }
662            JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(TypeUtils.makeNotNullable(arrayType));
663            if (primitiveType == null) {
664                throw new IllegalStateException("not array: " + arrayType);
665            }
666            return primitiveType;
667        }
668    
669        @NotNull
670        public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) {
671            return primitiveTypeToArrayJetType.get(primitiveType);
672        }
673    
674        /**
675         * @return <code>null</code> if not primitive
676         */
677        @Nullable
678        public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) {
679            return primitiveJetTypeToJetArrayType.get(jetType);
680        }
681    
682        @NotNull
683        public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
684            List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
685            return new JetTypeImpl(
686                    Collections.<AnnotationDescriptor>emptyList(),
687                    getArray().getTypeConstructor(),
688                    false,
689                    types,
690                    getArray().getMemberScope(types)
691            );
692        }
693    
694        @NotNull
695        public JetType getArrayType(@NotNull JetType argument) {
696            return getArrayType(Variance.INVARIANT, argument);
697        }
698    
699        @NotNull
700        public JetType getEnumType(@NotNull JetType argument) {
701            Variance projectionType = Variance.INVARIANT;
702            List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
703            return new JetTypeImpl(
704                    Collections.<AnnotationDescriptor>emptyList(),
705                    getEnum().getTypeConstructor(),
706                    false,
707                    types,
708                    getEnum().getMemberScope(types)
709            );
710        }
711    
712        @NotNull
713        public JetType getAnnotationType() {
714            return getBuiltInTypeByClassName("Annotation");
715        }
716    
717        @NotNull
718        public ClassDescriptor getPropertyMetadata() {
719            return getBuiltInClassByName("PropertyMetadata");
720        }
721    
722        @NotNull
723        public ClassDescriptor getPropertyMetadataImpl() {
724            return getBuiltInClassByName("PropertyMetadataImpl");
725        }
726    
727        @NotNull
728        public JetType getFunctionType(
729                @NotNull List<AnnotationDescriptor> annotations,
730                @Nullable JetType receiverType,
731                @NotNull List<JetType> parameterTypes,
732                @NotNull JetType returnType
733        ) {
734            List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType);
735            int size = parameterTypes.size();
736            ClassDescriptor classDescriptor = receiverType == null ? getFunction(size) : getExtensionFunction(size);
737            TypeConstructor constructor = classDescriptor.getTypeConstructor();
738    
739            return new JetTypeImpl(annotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments));
740        }
741    
742        @NotNull
743        public JetType getKFunctionType(
744                @NotNull List<AnnotationDescriptor> annotations,
745                @Nullable JetType receiverType,
746                @NotNull List<JetType> parameterTypes,
747                @NotNull JetType returnType,
748                boolean extensionFunction
749        ) {
750            List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType);
751            ClassDescriptor classDescriptor = getCorrespondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size());
752    
753            return new JetTypeImpl(
754                    annotations,
755                    classDescriptor.getTypeConstructor(),
756                    false,
757                    arguments,
758                    classDescriptor.getMemberScope(arguments)
759            );
760        }
761    
762        @NotNull
763        private ClassDescriptor getCorrespondingKFunctionClass(
764                @Nullable JetType receiverType,
765                boolean extensionFunction,
766                int numberOfParameters
767        ) {
768            if (receiverType == null) {
769                return getKFunction(numberOfParameters);
770            }
771            else if (extensionFunction) {
772                return getKExtensionFunction(numberOfParameters);
773            }
774            else {
775                return getKMemberFunction(numberOfParameters);
776            }
777        }
778    
779        @NotNull
780        private static List<TypeProjection> getFunctionTypeArgumentProjections(
781                @Nullable JetType receiverType,
782                @NotNull List<JetType> parameterTypes,
783                @NotNull JetType returnType
784        ) {
785            List<TypeProjection> arguments = new ArrayList<TypeProjection>();
786            if (receiverType != null) {
787                arguments.add(defaultProjection(receiverType));
788            }
789            for (JetType parameterType : parameterTypes) {
790                arguments.add(defaultProjection(parameterType));
791            }
792            arguments.add(defaultProjection(returnType));
793            return arguments;
794        }
795    
796        private static TypeProjection defaultProjection(JetType returnType) {
797            return new TypeProjection(Variance.INVARIANT, returnType);
798        }
799    
800        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
801    
802        // IS TYPE
803    
804        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
805    
806        public boolean isArray(@NotNull JetType type) {
807            return getArray().equals(type.getConstructor().getDeclarationDescriptor());
808        }
809    
810        public boolean isPrimitiveArray(@NotNull JetType type) {
811            return jetArrayTypeToPrimitiveJetType.containsKey(TypeUtils.makeNotNullable(type));
812        }
813    
814        public boolean isPrimitiveType(@NotNull JetType type) {
815            return primitiveJetTypeToJetArrayType.containsKey(type);
816        }
817    
818        // Functions
819    
820        @NotNull
821        private ImmutableSet<ClassDescriptor> computeIndexedClasses(@NotNull String prefix, int count) {
822            ImmutableSet.Builder<ClassDescriptor> builder = ImmutableSet.builder();
823            for (int i = 0; i < count; i++) {
824                builder.add(getBuiltInClassByName(prefix + i));
825            }
826            return builder.build();
827        }
828    
829        public boolean isFunctionOrExtensionFunctionType(@NotNull JetType type) {
830            return isFunctionType(type) || isExtensionFunctionType(type);
831        }
832    
833        public boolean isFunctionType(@NotNull JetType type) {
834            if (setContainsClassOf(functionClassesSet, type)) return true;
835    
836            for (JetType superType : type.getConstructor().getSupertypes()) {
837                if (isFunctionType(superType)) return true;
838            }
839    
840            return false;
841        }
842    
843        public boolean isExtensionFunctionType(@NotNull JetType type) {
844            if (setContainsClassOf(extensionFunctionClassesSet, type)) return true;
845    
846            for (JetType superType : type.getConstructor().getSupertypes()) {
847                if (isExtensionFunctionType(superType)) return true;
848            }
849    
850            return false;
851        }
852    
853        @Nullable
854        public JetType getReceiverType(@NotNull JetType type) {
855            assert isFunctionOrExtensionFunctionType(type) : type;
856            if (isExtensionFunctionType(type)) {
857                return type.getArguments().get(0).getType();
858            }
859            return null;
860        }
861    
862        @NotNull
863        public List<ValueParameterDescriptor> getValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull JetType type) {
864            assert isFunctionOrExtensionFunctionType(type);
865            List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
866            List<TypeProjection> parameterTypes = getParameterTypeProjectionsFromFunctionType(type);
867            for (int i = 0; i < parameterTypes.size(); i++) {
868                TypeProjection parameterType = parameterTypes.get(i);
869                ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
870                        functionDescriptor, i, Collections.<AnnotationDescriptor>emptyList(),
871                        Name.identifier("p" + (i + 1)), parameterType.getType(), false, null);
872                valueParameters.add(valueParameterDescriptor);
873            }
874            return valueParameters;
875        }
876    
877        @NotNull
878        public JetType getReturnTypeFromFunctionType(@NotNull JetType type) {
879            assert isFunctionOrExtensionFunctionType(type);
880            List<TypeProjection> arguments = type.getArguments();
881            return arguments.get(arguments.size() - 1).getType();
882        }
883    
884        @NotNull
885        public List<TypeProjection> getParameterTypeProjectionsFromFunctionType(@NotNull JetType type) {
886            assert isFunctionOrExtensionFunctionType(type);
887            List<TypeProjection> arguments = type.getArguments();
888            int first = isExtensionFunctionType(type) ? 1 : 0;
889            int last = arguments.size() - 2;
890            List<TypeProjection> parameterTypes = Lists.newArrayList();
891            for (int i = first; i <= last; i++) {
892                parameterTypes.add(arguments.get(i));
893            }
894            return parameterTypes;
895        }
896    
897        // Recognized & special
898    
899        public boolean isNothing(@NotNull JetType type) {
900            return isNothingOrNullableNothing(type)
901                   && !type.isNullable();
902        }
903    
904        public boolean isNullableNothing(@NotNull JetType type) {
905            return isNothingOrNullableNothing(type)
906                   && type.isNullable();
907        }
908    
909        public boolean isNothingOrNullableNothing(@NotNull JetType type) {
910            return !(type instanceof NamespaceType)
911                   && type.getConstructor() == getNothing().getTypeConstructor();
912        }
913    
914        public boolean isAny(@NotNull JetType type) {
915            return !(type instanceof NamespaceType) &&
916                   type.getConstructor() == getAny().getTypeConstructor();
917        }
918    
919        public boolean isUnit(@NotNull JetType type) {
920            return !(type instanceof NamespaceType) &&
921                   type.getConstructor() == getUnitType().getConstructor();
922        }
923    
924        public boolean isData(@NotNull ClassDescriptor classDescriptor) {
925            return containsAnnotation(classDescriptor, getDataClassAnnotation());
926        }
927    
928        public boolean isDeprecated(@NotNull DeclarationDescriptor declarationDescriptor) {
929            return containsAnnotation(declarationDescriptor, getDeprecatedAnnotation());
930        }
931    
932        private static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) {
933            List<AnnotationDescriptor> annotations = descriptor.getOriginal().getAnnotations();
934            if (annotations != null) {
935                for (AnnotationDescriptor annotation : annotations) {
936                    if (annotationClass.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) {
937                        return true;
938                    }
939                }
940            }
941            return false;
942        }
943    
944        public boolean isVolatile(@NotNull PropertyDescriptor descriptor) {
945            return containsAnnotation(descriptor, getVolatileAnnotationClass());
946        }
947    
948        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
949    
950        @NotNull
951        public JetType getDefaultBound() {
952            return getNullableAnyType();
953        }
954    
955        private static boolean setContainsClassOf(ImmutableSet<ClassDescriptor> set, JetType type) {
956            //noinspection SuspiciousMethodCalls
957            return set.contains(type.getConstructor().getDeclarationDescriptor());
958        }
959    }