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