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