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