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