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 }