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