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