KotlinBuiltins: a replacement for JetStandardLibrary and JetStandardClasses

This commit is contained in:
Andrey Breslav
2012-10-17 11:07:00 +04:00
parent 3f70a603a7
commit 363faaf6d5
8 changed files with 921 additions and 4 deletions
-4
View File
@@ -1,4 +0,0 @@
These files are used only for navigation from user code in IDE.
These files are not processed by Kotlin compiler. Compiler creates Any, Nothing, tuple and function
types on-the-fly.
@@ -0,0 +1,921 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.types.lang;
import com.google.common.base.Predicates;
import com.google.common.collect.*;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFileFactory;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.DefaultModuleConfiguration;
import org.jetbrains.jet.lang.ModuleConfiguration;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import static org.jetbrains.jet.lang.types.lang.PrimitiveType.*;
public class KotlinBuiltIns {
public static final Name UNIT_ALIAS = Name.identifier("Unit");
public static final JetScope STUB = JetScope.EMPTY;
private static final String BUILT_INS_PACKAGE_NAME_STRING = "jet";
private static final Name BUILT_INS_PACKAGE_NAME = Name.identifier(BUILT_INS_PACKAGE_NAME_STRING);
public static final FqName BUILT_INS_PACKAGE_FQ_NAME = FqName.topLevel(BUILT_INS_PACKAGE_NAME);
private static final List<String> LIBRARY_FILES = Arrays.asList(
"jet/Library.jet",
"jet/Numbers.jet",
"jet/Ranges.jet",
"jet/Iterables.jet",
"jet/Iterators.jet",
"jet/Arrays.jet",
"jet/Enum.jet",
"jet/Collections.jet",
"jet/Any.jet",
"jet/ExtensionFunctions.jet",
"jet/Functions.jet",
"jet/Nothing.jet",
"jet/Tuples.jet",
"jet/Unit.jet"
);
private static final Map<FqName, Name> ALIASES = ImmutableMap.<FqName, Name>builder()
.put(new FqName("jet.Unit"), Name.identifier("Tuple0"))
.build();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static volatile KotlinBuiltIns instance = null;
private static volatile boolean initializing;
private static Throwable initializationFailed;
// This method must be called at least once per application run, on any project
// before any type checking is run
public static synchronized void initialize(@NotNull Project project) {
if (instance == null) {
if (initializationFailed != null) {
throw new RuntimeException(
"builtin library initialization failed previously: " + initializationFailed, initializationFailed);
}
if (initializing) {
throw new IllegalStateException("builtin library initialization loop");
}
initializing = true;
try {
instance = new KotlinBuiltIns(project);
instance.initialize();
}
catch (Throwable e) {
initializationFailed = e;
throw new RuntimeException("builtin library initialization failed: " + e, e);
}
finally {
initializing = false;
}
}
}
@NotNull // This asserts that initialize() is called before any resolution happens
public static KotlinBuiltIns getInstance() {
if (initializing) {
synchronized (KotlinBuiltIns.class) {
assert instance != null : "We are under the same lock as initializing and instance";
return instance;
}
}
if (instance == null) {
throw new IllegalStateException("Initialize standard library first");
}
return instance;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final ResolveSession resolveSession;
private final ModuleDescriptor builtInsModule;
private final ImmutableList<ClassDescriptor> functionClasses;
private final ImmutableSet<ClassDescriptor> functionClassesSet;
private final ImmutableList<ClassDescriptor> extensionFunctionClasses;
private final ImmutableSet<ClassDescriptor> extensionFunctionClassesSet;
@Deprecated
private final ImmutableList<ClassDescriptor> tupleClasses;
@Deprecated
private final ImmutableSet<ClassDescriptor> tupleClassesSet;
private final EnumMap<PrimitiveType, ClassDescriptor> primitiveTypeToClass;
private final EnumMap<PrimitiveType, ClassDescriptor> primitiveTypeToArrayClass;
private final EnumMap<PrimitiveType, JetType> primitiveTypeToJetType;
private final EnumMap<PrimitiveType, JetType> primitiveTypeToNullableJetType;
private final EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
private final Map<JetType, JetType> primitiveJetTypeToJetArrayType;
private final Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
private KotlinBuiltIns(@NotNull Project project) {
try {
this.builtInsModule = new ModuleDescriptor(Name.special("<built-ins lazy module>"));
this.resolveSession = createLazyResolveSession(project);
this.functionClasses = computeIndexedClasses("Function", getFunctionTraitCount());
this.functionClassesSet = ImmutableSet.copyOf(functionClasses);
this.extensionFunctionClasses = computeIndexedClasses("ExtensionFunction", getFunctionTraitCount());
this.extensionFunctionClassesSet = ImmutableSet.copyOf(extensionFunctionClasses);
this.tupleClasses = computeIndexedClasses("Tuple", getFunctionTraitCount());
this.tupleClassesSet = ImmutableSet.copyOf(tupleClasses);
this.primitiveTypeToClass = new EnumMap<PrimitiveType, ClassDescriptor>(PrimitiveType.class);
this.primitiveTypeToJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
this.primitiveTypeToNullableJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
this.primitiveTypeToArrayClass = new EnumMap<PrimitiveType, ClassDescriptor>(PrimitiveType.class);
this.primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
this.primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
this.jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
}
catch (IOException e) {
throw new IllegalStateException(e);
}
catch (ProcessCanceledException e) {
throw e;
}
}
private void initialize() {
for (PrimitiveType primitive : PrimitiveType.values()) {
makePrimitive(primitive);
}
resolveSession.forceResolveAll();
}
@NotNull
private ResolveSession createLazyResolveSession(@NotNull Project project) throws IOException {
List<JetFile> files = loadResourcesAsJetFiles(project, LIBRARY_FILES);
return new ResolveSession(
project,
builtInsModule,
new SpecialModuleConfiguration(project),
new FileBasedDeclarationProviderFactory(files),
new Function<FqName, Name>() {
@Override
public Name fun(FqName name) {
return ALIASES.get(name);
}
},
Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing"))));
}
@NotNull
private List<JetFile> loadResourcesAsJetFiles(@NotNull Project project, @NotNull List<String> libraryFiles)
throws IOException, ProcessCanceledException
{
List<JetFile> files = new LinkedList<JetFile>();
for(String path : libraryFiles) {
InputStream stream = KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
if (stream == null) {
throw new IllegalStateException("Resource not found in classpath: " + path);
}
//noinspection IOResourceOpenedButNotSafelyClosed
JetFile file = (JetFile) PsiFileFactory.getInstance(project).createFileFromText(path,
JetFileType.INSTANCE, FileUtil.loadTextAndClose(new InputStreamReader(stream)));
files.add(file);
}
return files;
}
private static class SpecialModuleConfiguration implements ModuleConfiguration {
private final Project project;
private SpecialModuleConfiguration(@NotNull Project project) {
this.project = project;
}
@Override
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
for (ImportPath defaultJetImport : DefaultModuleConfiguration.DEFAULT_JET_IMPORTS) {
directives.add(JetPsiFactory.createImportDirective(project, defaultJetImport));
}
}
@Override
public void extendNamespaceScope(@NotNull BindingTrace trace,
@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull WritableScope namespaceMemberScope) {
// DO nothing
}
@NotNull
@Override
public PlatformToKotlinClassMap getPlatformToKotlinClassMap() {
return PlatformToKotlinClassMap.EMPTY;
}
}
private void makePrimitive(PrimitiveType primitiveType) {
ClassDescriptor clazz = (ClassDescriptor) getBuiltInsScope().getClassifier(primitiveType.getTypeName());
ClassDescriptor arrayClazz = (ClassDescriptor) getBuiltInsScope().getClassifier(primitiveType.getArrayTypeName());
JetTypeImpl type = new JetTypeImpl(clazz);
JetTypeImpl arrayType = new JetTypeImpl(arrayClazz);
primitiveTypeToClass.put(primitiveType, clazz);
primitiveTypeToJetType.put(primitiveType, type);
primitiveTypeToNullableJetType.put(primitiveType, TypeUtils.makeNullable(type));
primitiveTypeToArrayClass.put(primitiveType, arrayClazz);
primitiveTypeToArrayJetType.put(primitiveType, arrayType);
primitiveJetTypeToJetArrayType.put(type, arrayType);
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
public ModuleDescriptor getBuiltInsModule() {
return builtInsModule;
}
@NotNull
public NamespaceDescriptor getBuiltInsPackage() {
NamespaceDescriptor namespace = getBuiltInsModule().getRootNamespace().getMemberScope().getNamespace(BUILT_INS_PACKAGE_NAME);
assert namespace != null : "Built ins namespace not found: " + BUILT_INS_PACKAGE_NAME;
return namespace;
}
@NotNull
public FqName getBuiltInsPackageFqName() {
return getBuiltInsPackage().getQualifiedName();
}
@NotNull
public Collection<DeclarationDescriptor> getAllBuiltInClasses() {
// TODO: used once, but incorrectly in JetShortNamesCache
return getStandardClassesScope().getAllDescriptors();
}
@Deprecated
@NotNull
public JetScope getStandardClassesScope() {
// TODO: this is more than standard classes
// TODO: the only usage makes no sense for lazily loaded library
return getBuiltInsScope();
}
@NotNull
public JetScope getBuiltInsScope() {
return getBuiltInsPackage().getMemberScope();
}
public boolean isStandardClass(@NotNull FqName fqName) {
// TODO: this seems to be wrong for ranges, and will certainly be wrong upon renaming jet -> kotlin
return getBuiltInsPackageFqName().equals(fqName.parent());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GET CLASS
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private ClassDescriptor getBuiltInClassByName(@NotNull String simpleName) {
ClassifierDescriptor classifier = getBuiltInsScope().getClassifier(Name.identifier(simpleName));
assert classifier instanceof ClassDescriptor : "Must be a class descriptor " + simpleName + ", but was " + classifier;
return (ClassDescriptor) classifier;
}
// Special
@NotNull
public ClassDescriptor getAny() {
return getBuiltInClassByName("Any");
}
@NotNull
public ClassDescriptor getNothing() {
return getBuiltInClassByName("Nothing");
}
// Primitive
@NotNull
public ClassDescriptor getPrimitiveClassDescriptor(@NotNull PrimitiveType type) {
return getBuiltInClassByName(type.getTypeName().getName());
}
@NotNull
public ClassDescriptor getByte() {
return getPrimitiveClassDescriptor(BYTE);
}
@NotNull
public ClassDescriptor getShort() {
return getPrimitiveClassDescriptor(SHORT);
}
@NotNull
public ClassDescriptor getInt() {
return getPrimitiveClassDescriptor(INT);
}
@NotNull
public ClassDescriptor getLong() {
return getPrimitiveClassDescriptor(LONG);
}
@NotNull
public ClassDescriptor getFloat() {
return getPrimitiveClassDescriptor(FLOAT);
}
@NotNull
public ClassDescriptor getDouble() {
return getPrimitiveClassDescriptor(DOUBLE);
}
@NotNull
public ClassDescriptor getChar() {
return getPrimitiveClassDescriptor(CHAR);
}
@NotNull
public ClassDescriptor getBoolean() {
return getPrimitiveClassDescriptor(BOOLEAN);
}
// Recognized
@NotNull
public Set<DeclarationDescriptor> getIntegralRanges() {
return ImmutableSet.<DeclarationDescriptor>of(
getBuiltInClassByName("ByteRange"),
getBuiltInClassByName("ShortRange"),
getBuiltInClassByName("CharRange"),
getBuiltInClassByName("IntRange"),
getBuiltInClassByName("LongRange")
);
}
@NotNull
public ClassDescriptor getArray() {
return getBuiltInClassByName("Array");
}
@NotNull
public ClassDescriptor getPrimitiveArrayClassDescriptor(@NotNull PrimitiveType type) {
return getBuiltInClassByName(type.getArrayTypeName().getName());
}
@NotNull
public ClassDescriptor getNumber() {
return getBuiltInClassByName("Number");
}
@NotNull
public ClassDescriptor getFunction(int parameterCount) {
return getBuiltInClassByName("Function" + parameterCount);
}
@NotNull
public ClassDescriptor getExtensionFunction(int parameterCount) {
return getBuiltInClassByName("ExtensionFunction" + parameterCount);
}
@NotNull
public ClassDescriptor getThrowable() {
return getBuiltInClassByName("Throwable");
}
@NotNull
public ClassDescriptor getDataClassAnnotation() {
return getBuiltInClassByName("data");
}
@NotNull
public ClassDescriptor getVolatileAnnotationClass() {
return getBuiltInClassByName("volatile");
}
@NotNull
public ClassDescriptor getString() {
return getBuiltInClassByName("String");
}
@NotNull
public ClassDescriptor getCharSequence() {
return getBuiltInClassByName("CharSequence");
}
@NotNull
public ClassDescriptor getComparable() {
return getBuiltInClassByName("Comparable");
}
@NotNull
public ClassDescriptor getEnum() {
return getBuiltInClassByName("Enum");
}
@NotNull
public ClassDescriptor getAnnotation() {
return getBuiltInClassByName("Annotation");
}
@NotNull
public ClassDescriptor getIterator() {
return getBuiltInClassByName("Iterator");
}
@NotNull
public ClassDescriptor getIterable() {
return getBuiltInClassByName("Iterable");
}
@NotNull
public ClassDescriptor getMutableIterable() {
return getBuiltInClassByName("MutableIterable");
}
@NotNull
public ClassDescriptor getMutableIterator() {
return getBuiltInClassByName("MutableIterator");
}
@NotNull
public ClassDescriptor getCollection() {
return getBuiltInClassByName("Collection");
}
@NotNull
public ClassDescriptor getMutableCollection() {
return getBuiltInClassByName("MutableCollection");
}
@NotNull
public ClassDescriptor getList() {
return getBuiltInClassByName("List");
}
@NotNull
public ClassDescriptor getMutableList() {
return getBuiltInClassByName("MutableList");
}
@NotNull
public ClassDescriptor getSet() {
return getBuiltInClassByName("Set");
}
@NotNull
public ClassDescriptor getMutableSet() {
return getBuiltInClassByName("MutableSet");
}
@NotNull
public ClassDescriptor getMap() {
return getBuiltInClassByName("Map");
}
@NotNull
public ClassDescriptor getMutableMap() {
return getBuiltInClassByName("MutableMap");
}
@NotNull
public ClassDescriptor getMapEntry() {
return DescriptorUtils.getInnerClassByName(getBuiltInClassByName("Map"), "Entry");
}
@NotNull
public ClassDescriptor getMutableMapEntry() {
return DescriptorUtils.getInnerClassByName(getBuiltInClassByName("MutableMap"), "MutableEntry");
}
@NotNull
public ClassDescriptor getListIterator() {
return getBuiltInClassByName("ListIterator");
}
@NotNull
public ClassDescriptor getMutableListIterator() {
return getBuiltInClassByName("MutableListIterator");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GET TYPE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
private JetType getBuiltInTypeByClassName(@NotNull String classSimpleName) {
// TODO
return new JetTypeImpl(getBuiltInClassByName(classSimpleName));
}
// Special
@NotNull
public JetType getNothingType() {
return getBuiltInTypeByClassName("Nothing");
}
@NotNull
public JetType getNullableNothingType() {
// TODO
return TypeUtils.makeNullable(getNothingType());
}
@NotNull
public JetType getAnyType() {
return getBuiltInTypeByClassName("Any");
}
@NotNull
public JetType getNullableAnyType() {
// TODO
return TypeUtils.makeNullable(getAnyType());
}
// Primitive
@NotNull
public JetType getPrimitiveJetType(@NotNull PrimitiveType type) {
// TODO
return new JetTypeImpl(getPrimitiveClassDescriptor(type));
}
@NotNull
public JetType getNullablePrimitiveJetType(@NotNull PrimitiveType primitiveType) {
return primitiveTypeToNullableJetType.get(primitiveType);
}
@NotNull
public JetType getByteType() {
return getPrimitiveJetType(BYTE);
}
@NotNull
public JetType getShortType() {
return getPrimitiveJetType(SHORT);
}
@NotNull
public JetType getIntType() {
return getPrimitiveJetType(INT);
}
@NotNull
public JetType getLongType() {
return getPrimitiveJetType(LONG);
}
@NotNull
public JetType getFloatType() {
return getPrimitiveJetType(FLOAT);
}
@NotNull
public JetType getDoubleType() {
return getPrimitiveJetType(DOUBLE);
}
@NotNull
public JetType getCharType() {
return getPrimitiveJetType(CHAR);
}
@NotNull
public JetType getBooleanType() {
return getPrimitiveJetType(BOOLEAN);
}
// Recognized
@NotNull
public JetType getUnitType() {
return getBuiltInTypeByClassName("Unit");
}
@NotNull
public JetType getStringType() {
return getBuiltInTypeByClassName("String");
}
@NotNull
public JetType getArrayElementType(@NotNull JetType arrayType) {
// make non-null?
if (arrayType.getConstructor().getDeclarationDescriptor() == getArray()) {
if (arrayType.getArguments().size() != 1) {
throw new IllegalStateException();
}
return arrayType.getArguments().get(0).getType();
}
JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(arrayType);
if (primitiveType == null) {
throw new IllegalStateException("not array: " + arrayType);
}
return primitiveType;
}
@NotNull
public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) {
return primitiveTypeToArrayJetType.get(primitiveType);
}
/**
* @return <code>null</code> if not primitive
*/
@Nullable
public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) {
return primitiveJetTypeToJetArrayType.get(jetType);
}
@NotNull
public JetType getArrayType(@NotNull Variance projectionType, @NotNull JetType argument) {
List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getArray().getTypeConstructor(),
false,
types,
getArray().getMemberScope(types)
);
}
@NotNull
public JetType getArrayType(@NotNull JetType argument) {
return getArrayType(Variance.INVARIANT, argument);
}
@NotNull
public JetType getEnumType(@NotNull JetType argument) {
Variance projectionType = Variance.INVARIANT;
List<TypeProjection> types = Collections.singletonList(new TypeProjection(projectionType, argument));
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
getEnum().getTypeConstructor(),
false,
types,
getEnum().getMemberScope(types)
);
}
@NotNull
public JetType getAnnotationType() {
return getBuiltInTypeByClassName("Annotation");
}
@NotNull
public JetType getFunctionType(
@NotNull List<AnnotationDescriptor> annotations,
@Nullable JetType receiverType,
@NotNull List<JetType> parameterTypes,
@NotNull JetType returnType
) {
List<TypeProjection> arguments = new ArrayList<TypeProjection>();
if (receiverType != null) {
arguments.add(defaultProjection(receiverType));
}
for (JetType parameterType : parameterTypes) {
arguments.add(defaultProjection(parameterType));
}
arguments.add(defaultProjection(returnType));
int size = parameterTypes.size();
ClassDescriptor classDescriptor = receiverType == null ? getFunction(size) : getExtensionFunction(size);
TypeConstructor constructor = classDescriptor.getTypeConstructor();
return new JetTypeImpl(annotations, constructor, false, arguments, classDescriptor.getMemberScope(arguments));
}
private TypeProjection defaultProjection(JetType returnType) {
return new TypeProjection(Variance.INVARIANT, returnType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IS TYPE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public boolean isArray(@NotNull JetType type) {
return getArray().equals(type.getConstructor().getDeclarationDescriptor());
}
// Functions
public int getFunctionTraitCount() {
return 23;
}
@NotNull
private ImmutableList<ClassDescriptor> computeIndexedClasses(@NotNull String prefix, int count) {
ImmutableList.Builder<ClassDescriptor> builder = ImmutableList.builder();
for (int i = 0; i < count; i++) {
builder.add(getBuiltInClassByName(prefix + i));
}
return builder.build();
}
public boolean isFunctionType(@NotNull JetType type) {
DeclarationDescriptor constructor = type.getConstructor().getDeclarationDescriptor();
return functionClassesSet.contains(constructor) || extensionFunctionClassesSet.contains(constructor);
}
@Nullable
public JetType getReceiverType(@NotNull JetType type) {
assert isFunctionType(type) : type;
if (extensionFunctionClassesSet.contains(type.getConstructor().getDeclarationDescriptor())) {
return type.getArguments().get(0).getType();
}
return null;
}
@NotNull
public List<ValueParameterDescriptor> getValueParameters(@NotNull FunctionDescriptor functionDescriptor, @NotNull JetType type) {
assert isFunctionType(type);
List<ValueParameterDescriptor> valueParameters = Lists.newArrayList();
List<TypeProjection> parameterTypes = getParameterTypeProjectionsFromFunctionType(type);
for (int i = 0; i < parameterTypes.size(); i++) {
TypeProjection parameterType = parameterTypes.get(i);
ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
functionDescriptor, i, Collections.<AnnotationDescriptor>emptyList(),
Name.identifier("p" + (i + 1)), false, parameterType.getType(), false, null);
valueParameters.add(valueParameterDescriptor);
}
return valueParameters;
}
@NotNull
public JetType getReturnTypeFromFunctionType(@NotNull JetType type) {
assert isFunctionType(type);
List<TypeProjection> arguments = type.getArguments();
return arguments.get(arguments.size() - 1).getType();
}
@NotNull
public List<TypeProjection> getParameterTypeProjectionsFromFunctionType(@NotNull JetType type) {
assert isFunctionType(type);
List<TypeProjection> arguments = type.getArguments();
int first = extensionFunctionClassesSet.contains(type.getConstructor().getDeclarationDescriptor()) ? 1 : 0;
int last = arguments.size() - 2;
List<TypeProjection> parameterTypes = Lists.newArrayList();
for (int i = first; i <= last; i++) {
parameterTypes.add(arguments.get(i));
}
return parameterTypes;
}
// Recognized & special
public boolean isNothing(@NotNull JetType type) {
return isNothingOrNullableNothing(type)
&& !type.isNullable();
}
public boolean isNullableNothing(@NotNull JetType type) {
return isNothingOrNullableNothing(type)
&& type.isNullable();
}
public boolean isNothingOrNullableNothing(@NotNull JetType type) {
return !(type instanceof NamespaceType)
&& type.getConstructor() == getNothing().getTypeConstructor();
}
public boolean isAny(@NotNull JetType type) {
return !(type instanceof NamespaceType) &&
type.getConstructor() == getAny().getTypeConstructor();
}
public boolean isUnit(@NotNull JetType type) {
return !(type instanceof NamespaceType) &&
type.getConstructor() == getUnitType().getConstructor();
}
public boolean isData(@NotNull ClassDescriptor classDescriptor) {
return containsAnnotation(classDescriptor, getDataClassAnnotation());
}
private boolean containsAnnotation(DeclarationDescriptor descriptor, ClassDescriptor annotationClass) {
List<AnnotationDescriptor> annotations = descriptor.getOriginal().getAnnotations();
if (annotations != null) {
for (AnnotationDescriptor annotation : annotations) {
if (annotationClass.equals(annotation.getType().getConstructor().getDeclarationDescriptor())) {
return true;
}
}
}
return false;
}
public boolean isVolatile(@NotNull PropertyDescriptor descriptor) {
return containsAnnotation(descriptor, getVolatileAnnotationClass());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
public JetType getDefaultBound() {
return getNullableAnyType();
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TUPLES
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Deprecated
@NotNull
public List<JetType> getTupleElementTypes(@NotNull JetType type) {
assert isTupleType(type);
List<JetType> result = Lists.newArrayList();
for (TypeProjection typeProjection : type.getArguments()) {
result.add(typeProjection.getType());
}
return result;
}
@NotNull
@Deprecated
public ClassDescriptor getTuple(int size) {
return getBuiltInClassByName("Tuple" + size);
}
@Deprecated
public boolean isTupleType(@NotNull JetType type) {
return tupleClassesSet.contains(type.getConstructor().getDeclarationDescriptor());
}
@NotNull
@Deprecated
public JetType getTupleType(@NotNull List<JetType> arguments) {
return getTupleType(Collections.<AnnotationDescriptor>emptyList(), arguments);
}
@NotNull
@Deprecated
public JetType getTupleType(@NotNull JetType... arguments) {
return getTupleType(Collections.<AnnotationDescriptor>emptyList(), Arrays.asList(arguments));
}
@Deprecated
private JetType getTupleType(List<AnnotationDescriptor> annotations, List<JetType> arguments) {
if (annotations.isEmpty() && arguments.isEmpty()) {
return getUnitType();
}
ClassDescriptor tuple = getTuple(arguments.size());
List<TypeProjection> typeArguments = toProjections(arguments);
return new JetTypeImpl(annotations, tuple.getTypeConstructor(), false, typeArguments, tuple.getMemberScope(typeArguments));
}
private List<TypeProjection> toProjections(List<JetType> arguments) {
List<TypeProjection> result = new ArrayList<TypeProjection>();
for (JetType argument : arguments) {
result.add(new TypeProjection(Variance.OUT_VARIANCE, argument));
}
return result;
}
}