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