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.resolve.DescriptorUtils;
031    import org.jetbrains.jet.lang.resolve.name.FqName;
032    import org.jetbrains.jet.lang.resolve.name.Name;
033    import org.jetbrains.jet.lang.resolve.name.SpecialNames;
034    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
035    import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler;
036    import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
037    import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
038    import org.jetbrains.jet.lang.types.*;
039    import org.jetbrains.jet.storage.LockBasedStorageManager;
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(), SpecialNames.ROOT_NAMESPACE);
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 getHashable() {
339            return getBuiltInClassByName("Hashable");
340        }
341    
342        @NotNull
343        public ClassDescriptor getUnit() {
344            return getBuiltInClassByName("Unit");
345        }
346    
347        @NotNull
348        public ClassDescriptor getFunction(int parameterCount) {
349            return getBuiltInClassByName("Function" + parameterCount);
350        }
351    
352        @NotNull
353        public ClassDescriptor getExtensionFunction(int parameterCount) {
354            return getBuiltInClassByName("ExtensionFunction" + parameterCount);
355        }
356    
357        @NotNull
358        public ClassDescriptor getKFunction(int parameterCount) {
359            return getBuiltInClassByName("KFunction" + parameterCount);
360        }
361    
362        @NotNull
363        public ClassDescriptor getKMemberFunction(int parameterCount) {
364            return getBuiltInClassByName("KMemberFunction" + parameterCount);
365        }
366    
367        @NotNull
368        public ClassDescriptor getKExtensionFunction(int parameterCount) {
369            return getBuiltInClassByName("KExtensionFunction" + parameterCount);
370        }
371    
372        @NotNull
373        public ClassDescriptor getThrowable() {
374            return getBuiltInClassByName("Throwable");
375        }
376    
377        @NotNull
378        public ClassDescriptor getDataClassAnnotation() {
379            return getBuiltInClassByName("data");
380        }
381    
382        @NotNull
383        public ClassDescriptor getSuppressAnnotationClass() {
384            return getBuiltInClassByName("suppress");
385        }
386    
387        @NotNull
388        public ClassDescriptor getVolatileAnnotationClass() {
389            return getBuiltInClassByName("volatile");
390        }
391    
392        @NotNull
393        public ClassDescriptor getDeprecatedAnnotation() {
394            return getBuiltInClassByName("deprecated");
395        }
396    
397        @NotNull
398        public ClassDescriptor getString() {
399            return getBuiltInClassByName("String");
400        }
401    
402        @NotNull
403        public ClassDescriptor getCharSequence() {
404            return getBuiltInClassByName("CharSequence");
405        }
406    
407        @NotNull
408        public ClassDescriptor getComparable() {
409            return getBuiltInClassByName("Comparable");
410        }
411    
412        @NotNull
413        public ClassDescriptor getEnum() {
414            return getBuiltInClassByName("Enum");
415        }
416    
417        @NotNull
418        public ClassDescriptor getAnnotation() {
419            return getBuiltInClassByName("Annotation");
420        }
421    
422        @NotNull
423        public ClassDescriptor getIterator() {
424            return getBuiltInClassByName("Iterator");
425        }
426    
427        @NotNull
428        public ClassDescriptor getIterable() {
429            return getBuiltInClassByName("Iterable");
430        }
431    
432        @NotNull
433        public ClassDescriptor getMutableIterable() {
434            return getBuiltInClassByName("MutableIterable");
435        }
436    
437        @NotNull
438        public ClassDescriptor getMutableIterator() {
439            return getBuiltInClassByName("MutableIterator");
440        }
441    
442        @NotNull
443        public ClassDescriptor getCollection() {
444            return getBuiltInClassByName("Collection");
445        }
446    
447        @NotNull
448        public ClassDescriptor getMutableCollection() {
449            return getBuiltInClassByName("MutableCollection");
450        }
451    
452        @NotNull
453        public ClassDescriptor getList() {
454            return getBuiltInClassByName("List");
455        }
456    
457        @NotNull
458        public ClassDescriptor getMutableList() {
459            return getBuiltInClassByName("MutableList");
460        }
461    
462        @NotNull
463        public ClassDescriptor getSet() {
464            return getBuiltInClassByName("Set");
465        }
466    
467        @NotNull
468        public ClassDescriptor getMutableSet() {
469            return getBuiltInClassByName("MutableSet");
470        }
471    
472        @NotNull
473        public ClassDescriptor getMap() {
474            return getBuiltInClassByName("Map");
475        }
476    
477        @NotNull
478        public ClassDescriptor getMutableMap() {
479            return getBuiltInClassByName("MutableMap");
480        }
481    
482        @NotNull
483        public ClassDescriptor getMapEntry() {
484            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getBuiltInClassByName("Map"), "Entry");
485            assert classDescriptor != null : "Can't find Map.Entry";
486            return classDescriptor;
487        }
488    
489        @NotNull
490        public ClassDescriptor getMutableMapEntry() {
491            ClassDescriptor classDescriptor = DescriptorUtils.getInnerClassByName(getBuiltInClassByName("MutableMap"), "MutableEntry");
492            assert classDescriptor != null : "Can't find MutableMap.MutableEntry";
493            return classDescriptor;
494        }
495    
496        @NotNull
497        public ClassDescriptor getListIterator() {
498            return getBuiltInClassByName("ListIterator");
499        }
500    
501        @NotNull
502        public ClassDescriptor getMutableListIterator() {
503            return getBuiltInClassByName("MutableListIterator");
504        }
505    
506        /**
507         * Classes that only exist for the Kotlin compiler: they are erased at runtime.
508         * As a consequence they, for example, shouldn't be referred to by other languages
509         * (e.g. Java).
510         */
511        @NotNull
512        public Set<ClassDescriptor> getNonPhysicalClasses() {
513            return nonPhysicalClasses;
514        }
515    
516        @NotNull
517        private ImmutableSet<ClassDescriptor> computeNonPhysicalClasses() {
518            ImmutableSet.Builder<ClassDescriptor> nonPhysical = ImmutableSet.builder();
519            nonPhysical.add(
520                    getAny(),
521                    getNothing(),
522    
523                    getNumber(),
524                    getString(),
525                    getCharSequence(),
526                    getThrowable(),
527                    getBuiltInClassByName("Hashable"),
528    
529                    getIterator(),
530                    getIterable(),
531                    getCollection(),
532                    getList(),
533                    getListIterator(),
534                    getSet(),
535                    getMap(),
536                    getMapEntry(),
537    
538                    getMutableIterator(),
539                    getMutableIterable(),
540                    getMutableCollection(),
541                    getMutableList(),
542                    getMutableListIterator(),
543                    getMutableSet(),
544                    getMutableMap(),
545                    getMutableMapEntry(),
546    
547                    getVolatileAnnotationClass(),
548                    getDataClassAnnotation(),
549                    getAnnotation(),
550                    getComparable(),
551                    getEnum(),
552                    getArray()
553            );
554    
555            for (PrimitiveType primitiveType : values()) {
556                nonPhysical.add(getPrimitiveClassDescriptor(primitiveType));
557                nonPhysical.add(getPrimitiveArrayClassDescriptor(primitiveType));
558            }
559    
560            return nonPhysical.build();
561        }
562    
563        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
564    
565        // GET TYPE
566    
567        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
568    
569        @NotNull
570        private JetType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
571            // TODO
572            return new JetTypeImpl(getBuiltInClassByName(classSimpleName));
573        }
574    
575        // Special
576    
577        @NotNull
578        public JetType getNothingType() {
579            return getBuiltInTypeByClassName("Nothing");
580        }
581    
582        @NotNull
583        public JetType getNullableNothingType() {
584            // TODO
585            return TypeUtils.makeNullable(getNothingType());
586        }
587    
588        @NotNull
589        public JetType getAnyType() {
590            return getBuiltInTypeByClassName("Any");
591        }
592    
593        @NotNull
594        public JetType getNullableAnyType() {
595            // TODO
596            return TypeUtils.makeNullable(getAnyType());
597        }
598    
599        // Primitive
600    
601        @NotNull
602        public JetType getPrimitiveJetType(@NotNull PrimitiveType type) {
603            // TODO
604            return new JetTypeImpl(getPrimitiveClassDescriptor(type));
605        }
606    
607        @NotNull
608        public JetType getNullablePrimitiveJetType(@NotNull PrimitiveType primitiveType) {
609            return primitiveTypeToNullableJetType.get(primitiveType);
610        }
611    
612        @NotNull
613        public JetType getByteType() {
614            return getPrimitiveJetType(BYTE);
615        }
616    
617        @NotNull
618        public JetType getShortType() {
619            return getPrimitiveJetType(SHORT);
620        }
621    
622        @NotNull
623        public JetType getIntType() {
624            return getPrimitiveJetType(INT);
625        }
626    
627        @NotNull
628        public JetType getLongType() {
629            return getPrimitiveJetType(LONG);
630        }
631    
632        @NotNull
633        public JetType getFloatType() {
634            return getPrimitiveJetType(FLOAT);
635        }
636    
637        @NotNull
638        public JetType getDoubleType() {
639            return getPrimitiveJetType(DOUBLE);
640        }
641    
642        @NotNull
643        public JetType getCharType() {
644            return getPrimitiveJetType(CHAR);
645        }
646    
647        @NotNull
648        public JetType getBooleanType() {
649            return getPrimitiveJetType(BOOLEAN);
650        }
651    
652        // Recognized
653    
654        @NotNull
655        public JetType getUnitType() {
656            return getBuiltInTypeByClassName("Unit");
657        }
658    
659        @NotNull
660        public JetType getStringType() {
661            return getBuiltInTypeByClassName("String");
662        }
663    
664        @NotNull
665        public JetType getArrayElementType(@NotNull JetType arrayType) {
666            if (arrayType.getConstructor().getDeclarationDescriptor() == getArray()) {
667                if (arrayType.getArguments().size() != 1) {
668                    throw new IllegalStateException();
669                }
670                return arrayType.getArguments().get(0).getType();
671            }
672            JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(TypeUtils.makeNotNullable(arrayType));
673            if (primitiveType == null) {
674                throw new IllegalStateException("not array: " + arrayType);
675            }
676            return primitiveType;
677        }
678    
679        @NotNull
680        public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) {
681            return primitiveTypeToArrayJetType.get(primitiveType);
682        }
683    
684        /**
685         * @return <code>null</code> if not primitive
686         */
687        @Nullable
688        public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) {
689            return primitiveJetTypeToJetArrayType.get(jetType);
690        }
691    
692        @NotNull
693        public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
694            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
695            return new JetTypeImpl(
696                    Collections.<AnnotationDescriptor>emptyList(),
697                    getArray().getTypeConstructor(),
698                    false,
699                    types,
700                    getArray().getMemberScope(types)
701            );
702        }
703    
704        @NotNull
705        public JetType getArrayType(@NotNull JetType argument) {
706            return getArrayType(Variance.INVARIANT, argument);
707        }
708    
709        @NotNull
710        public JetType getEnumType(@NotNull JetType argument) {
711            Variance projectionType = Variance.INVARIANT;
712            List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
713            return new JetTypeImpl(
714                    Collections.<AnnotationDescriptor>emptyList(),
715                    getEnum().getTypeConstructor(),
716                    false,
717                    types,
718                    getEnum().getMemberScope(types)
719            );
720        }
721    
722        @NotNull
723        public JetType getAnnotationType() {
724            return getBuiltInTypeByClassName("Annotation");
725        }
726    
727        @NotNull
728        public ClassDescriptor getPropertyMetadata() {
729            return getBuiltInClassByName("PropertyMetadata");
730        }
731    
732        @NotNull
733        public ClassDescriptor getPropertyMetadataImpl() {
734            return getBuiltInClassByName("PropertyMetadataImpl");
735        }
736    
737        @NotNull
738        public JetType getFunctionType(
739                @NotNull List<AnnotationDescriptor> annotations,
740                @Nullable JetType receiverType,
741                @NotNull List<JetType> parameterTypes,
742                @NotNull JetType returnType
743        ) {
744            List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType);
745            int size = parameterTypes.size();
746            ClassDescriptor classDescriptor = receiverType == null ? getFunction(size) : getExtensionFunction(size);
747            TypeConstructor constructor = classDescriptor.getTypeConstructor();
748    
749            return new JetTypeImpl(annotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments));
750        }
751    
752        @NotNull
753        public JetType getKFunctionType(
754                @NotNull List<AnnotationDescriptor> annotations,
755                @Nullable JetType receiverType,
756                @NotNull List<JetType> parameterTypes,
757                @NotNull JetType returnType,
758                boolean extensionFunction
759        ) {
760            List<TypeProjection> arguments = getFunctionTypeArgumentProjections(receiverType, parameterTypes, returnType);
761            ClassDescriptor classDescriptor = getCorrespondingKFunctionClass(receiverType, extensionFunction, parameterTypes.size());
762    
763            return new JetTypeImpl(
764                    annotations,
765                    classDescriptor.getTypeConstructor(),
766                    false,
767                    arguments,
768                    classDescriptor.getMemberScope(arguments)
769            );
770        }
771    
772        @NotNull
773        private ClassDescriptor getCorrespondingKFunctionClass(
774                @Nullable JetType receiverType,
775                boolean extensionFunction,
776                int numberOfParameters
777        ) {
778            if (receiverType == null) {
779                return getKFunction(numberOfParameters);
780            }
781            else if (extensionFunction) {
782                return getKExtensionFunction(numberOfParameters);
783            }
784            else {
785                return getKMemberFunction(numberOfParameters);
786            }
787        }
788    
789        @NotNull
790        private static List<TypeProjection> getFunctionTypeArgumentProjections(
791                @Nullable JetType receiverType,
792                @NotNull List<JetType> parameterTypes,
793                @NotNull JetType returnType
794        ) {
795            List<TypeProjection> arguments = new ArrayList<TypeProjection>();
796            if (receiverType != null) {
797                arguments.add(defaultProjection(receiverType));
798            }
799            for (JetType parameterType : parameterTypes) {
800                arguments.add(defaultProjection(parameterType));
801            }
802            arguments.add(defaultProjection(returnType));
803            return arguments;
804        }
805    
806        private static TypeProjection defaultProjection(JetType returnType) {
807            return new TypeProjectionImpl(Variance.INVARIANT, returnType);
808        }
809    
810        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
811    
812        // IS TYPE
813    
814        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
815    
816        public boolean isArray(@NotNull JetType type) {
817            return getArray().equals(type.getConstructor().getDeclarationDescriptor());
818        }
819    
820        public boolean isPrimitiveArray(@NotNull JetType type) {
821            return jetArrayTypeToPrimitiveJetType.containsKey(TypeUtils.makeNotNullable(type));
822        }
823    
824        public boolean isPrimitiveType(@NotNull JetType type) {
825            return primitiveJetTypeToJetArrayType.containsKey(type);
826        }
827    
828        // Functions
829    
830        @NotNull
831        private ImmutableSet<ClassDescriptor> computeIndexedClasses(@NotNull String prefix, int count) {
832            ImmutableSet.Builder<ClassDescriptor> builder = ImmutableSet.builder();
833            for (int i = 0; i < count; i++) {
834                builder.add(getBuiltInClassByName(prefix + i));
835            }
836            return builder.build();
837        }
838    
839        public boolean isFunctionOrExtensionFunctionType(@NotNull JetType type) {
840            return isFunctionType(type) || isExtensionFunctionType(type);
841        }
842    
843        public boolean isFunctionType(@NotNull JetType type) {
844            if (setContainsClassOf(functionClassesSet, type)) return true;
845    
846            for (JetType superType : type.getConstructor().getSupertypes()) {
847                if (isFunctionType(superType)) return true;
848            }
849    
850            return false;
851        }
852    
853        public boolean isExactFunctionOrExtensionFunctionType(@NotNull JetType type) {
854            return setContainsClassOf(extensionFunctionClassesSet, type) || setContainsClassOf(functionClassesSet, type);
855        }
856    
857        public boolean isExtensionFunctionType(@NotNull JetType type) {
858            if (setContainsClassOf(extensionFunctionClassesSet, type)) return true;
859    
860            for (JetType superType : type.getConstructor().getSupertypes()) {
861                if (isExtensionFunctionType(superType)) return true;
862            }
863    
864            return false;
865        }
866    
867        @Nullable
868        public JetType getReceiverType(@NotNull JetType type) {
869            assert isFunctionOrExtensionFunctionType(type) : type;
870            if (isExtensionFunctionType(type)) {
871                return type.getArguments().get(0).getType();
872            }
873            return null;
874        }
875    
876        @NotNull
877        public List<ValueParameterDescriptor> getValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull JetType type) {
878            assert isFunctionOrExtensionFunctionType(type);
879            List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
880            List<TypeProjection> parameterTypes = getParameterTypeProjectionsFromFunctionType(type);
881            for (int i = 0; i < parameterTypes.size(); i++) {
882                TypeProjection parameterType = parameterTypes.get(i);
883                ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
884                        functionDescriptor, i, Collections.<AnnotationDescriptor>emptyList(),
885                        Name.identifier("p" + (i + 1)), parameterType.getType(), false, null);
886                valueParameters.add(valueParameterDescriptor);
887            }
888            return valueParameters;
889        }
890    
891        @NotNull
892        public JetType getReturnTypeFromFunctionType(@NotNull JetType type) {
893            assert isFunctionOrExtensionFunctionType(type);
894            List<TypeProjection> arguments = type.getArguments();
895            return arguments.get(arguments.size() - 1).getType();
896        }
897    
898        @NotNull
899        public List<TypeProjection> getParameterTypeProjectionsFromFunctionType(@NotNull JetType type) {
900            assert isFunctionOrExtensionFunctionType(type);
901            List<TypeProjection> arguments = type.getArguments();
902            int first = isExtensionFunctionType(type) ? 1 : 0;
903            int last = arguments.size() - 2;
904            List<TypeProjection> parameterTypes = Lists.newArrayList();
905            for (int i = first; i <= last; i++) {
906                parameterTypes.add(arguments.get(i));
907            }
908            return parameterTypes;
909        }
910    
911        // Recognized & special
912    
913        public boolean isNothing(@NotNull JetType type) {
914            return isNothingOrNullableNothing(type)
915                   && !type.isNullable();
916        }
917    
918        public boolean isNullableNothing(@NotNull JetType type) {
919            return isNothingOrNullableNothing(type)
920                   && type.isNullable();
921        }
922    
923        public boolean isNothingOrNullableNothing(@NotNull JetType type) {
924            return !(type instanceof NamespaceType)
925                   && type.getConstructor() == getNothing().getTypeConstructor();
926        }
927    
928        public boolean isAny(@NotNull JetType type) {
929            return !(type instanceof NamespaceType) &&
930                   type.getConstructor() == getAny().getTypeConstructor();
931        }
932    
933        public boolean isUnit(@NotNull JetType type) {
934            return !(type instanceof NamespaceType) &&
935                   type.getConstructor() == getUnitType().getConstructor();
936        }
937    
938        public boolean isData(@NotNull ClassDescriptor classDescriptor) {
939            return containsAnnotation(classDescriptor, getDataClassAnnotation());
940        }
941    
942        public boolean isDeprecated(@NotNull DeclarationDescriptor declarationDescriptor) {
943            return containsAnnotation(declarationDescriptor, getDeprecatedAnnotation());
944        }
945    
946        private static boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) {
947            List<AnnotationDescriptor> annotations = descriptor.getOriginal().getAnnotations();
948            if (annotations != null) {
949                for (AnnotationDescriptor annotation : annotations) {
950                    if (annotationClass.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) {
951                        return true;
952                    }
953                }
954            }
955            return false;
956        }
957    
958        public boolean isVolatile(@NotNull PropertyDescriptor descriptor) {
959            return containsAnnotation(descriptor, getVolatileAnnotationClass());
960        }
961    
962        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
963    
964        @NotNull
965        public JetType getDefaultBound() {
966            return getNullableAnyType();
967        }
968    
969        private static boolean setContainsClassOf(ImmutableSet<ClassDescriptor> set, JetType type) {
970            //noinspection SuspiciousMethodCalls
971            return set.contains(type.getConstructor().getDeclarationDescriptor());
972        }
973    }