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