Deserialize built-ins

This commit is contained in:
Andrey Breslav
2013-06-04 13:54:58 +04:00
committed by Alexander Udalov
parent defbf705fc
commit b7966179f5
7 changed files with 302 additions and 104 deletions
@@ -125,7 +125,7 @@ public class JetCoreEnvironment {
JetScriptDefinitionProvider.getInstance(project).addScriptDefinitions(configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY));
KotlinBuiltIns.initialize(project, KotlinBuiltIns.InitializationMode.SINGLE_THREADED);
KotlinBuiltIns.initialize();
}
public CompilerConfiguration getConfiguration() {
+1
View File
@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/generator" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/builtins" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
@@ -0,0 +1,89 @@
package org.jetbrains.jet.descriptors.serialization.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.ClassId;
import org.jetbrains.jet.descriptors.serialization.ClassResolver;
import org.jetbrains.jet.descriptors.serialization.DescriptorDeserializer;
import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public abstract class DeserializedPackageMemberScope extends DeserializedMemberScope {
private final ClassResolver classResolver;
private final FqName packageFqName;
public DeserializedPackageMemberScope(
@NotNull NamespaceDescriptor packageDescriptor,
@NotNull DescriptorDeserializer deserializer,
@NotNull List<ProtoBuf.Callable> membersList,
ClassResolver classResolver
) {
super(packageDescriptor, deserializer, membersList);
this.classResolver = classResolver;
this.packageFqName = DescriptorUtils.getFQName(packageDescriptor).toSafe();
}
@Nullable
@Override
protected ClassifierDescriptor getClassDescriptor(@NotNull Name name) {
return findClassDescriptor(name, false);
}
@Nullable
@Override
public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
return findClassDescriptor(name, true);
}
@Nullable
private ClassDescriptor findClassDescriptor(Name name, boolean object) {
ClassDescriptor classDescriptor = classResolver.findClass(new ClassId(packageFqName, FqNameUnsafe.topLevel(name)));
if (classDescriptor == null) {
return null;
}
return classDescriptor.getKind().isObject() == object ? classDescriptor : null;
}
@Override
protected void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
findClassifiers(result, false);
}
@NotNull
@Override
protected Collection<ClassDescriptor> computeAllObjectDescriptors() {
return findClassifiers(new ArrayList<ClassDescriptor>(), true);
}
private <T extends Collection<? super ClassDescriptor>> T findClassifiers(T result, boolean object) {
for (Name className : getClassNames()) {
ClassDescriptor classDescriptor = (ClassDescriptor) getClassDescriptor(className);
assert classDescriptor != null : "Class not found: " + className;
if (classDescriptor.getKind().isObject() == object) {
result.add(classDescriptor);
}
}
return result;
}
@NotNull
protected abstract Collection<Name> getClassNames();
@Override
protected void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
// Do nothing
}
}
@@ -0,0 +1,183 @@
package org.jetbrains.jet.lang.types.lang;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.descriptors.serialization.descriptors.AnnotationDeserializer;
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.AbstractNamespaceDescriptorImpl;
import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValueImpl;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
class BuiltinsNamespaceDescriptorImpl extends AbstractNamespaceDescriptorImpl {
private final DeserializedPackageMemberScope members;
private final NameResolver nameResolver;
public BuiltinsNamespaceDescriptorImpl(@NotNull NamespaceDescriptor containingDeclaration) {
super(containingDeclaration, Collections.<AnnotationDescriptor>emptyList(), KotlinBuiltIns.BUILT_INS_PACKAGE_NAME);
try {
nameResolver =
NameSerializationUtil.deserializeNameResolver(getStream(BuiltInsSerializationUtil.getNameTableFilePath(this)));
ClassResolver classResolver = new AbstractClassResolver(AnnotationDeserializer.UNSUPPORTED) {
@Nullable
@Override
protected ClassData getClassData(@NotNull ClassId classId) {
InputStream stream = getStreamNullable(BuiltInsSerializationUtil.getClassMetadataPath(classId));
if (stream == null) {
return null;
}
try {
ProtoBuf.Class classProto = ProtoBuf.Class.parseFrom(stream);
Name expectedShortName = classId.getRelativeClassName().shortName();
Name actualShortName = nameResolver.getName(classProto.getName());
if (!actualShortName.isSpecial() && !actualShortName.equals(expectedShortName)) {
// Workaround for case-insensitive file systems,
// otherwise we'd find "Collection" for "collection" etc
return null;
}
return new ClassData(nameResolver, classProto);
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
@NotNull
@Override
protected DeclarationDescriptor getPackage(@NotNull FqName fqName) {
assert fqName.equals(KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME) : "Wrong package: " + fqName;
return BuiltinsNamespaceDescriptorImpl.this;
}
@NotNull
@Override
protected ClassId getClassId(@NotNull ClassDescriptor classDescriptor) {
return BuiltInsSerializationUtil.getClassId(classDescriptor);
}
@NotNull
@Override
protected Name getClassObjectName(@NotNull ClassDescriptor outerClass) {
return BuiltInsSerializationUtil.CLASS_OBJECT_NAME;
}
@Override
protected void classDescriptorCreated(@NotNull ClassDescriptor classDescriptor) {
// Do nothing
}
};
members = new DeserializedPackageMemberScope(
this,
DescriptorDeserializer.create(this, nameResolver, classResolver, AnnotationDeserializer.UNSUPPORTED),
loadCallables(), classResolver
) {
private final NotNullLazyValue<Collection<Name>> classNames = new NotNullLazyValueImpl<Collection<Name>>() {
@NotNull
@Override
protected Collection<Name> doCompute() {
InputStream namesStream =
getStream(BuiltInsSerializationUtil.getClassNamesFilePath(BuiltinsNamespaceDescriptorImpl.this));
List<Name> result = new ArrayList<Name>();
try {
DataInputStream data = new DataInputStream(namesStream);
while (true) {
result.add(nameResolver.getName(data.readInt()));
}
}
catch (EOFException e) {
// OK: finishing the loop
}
catch (IOException e) {
throw new IllegalStateException(e);
}
return result;
}
};
@NotNull
@Override
protected Collection<Name> getClassNames() {
return classNames.compute();
}
@Nullable
@Override
protected ReceiverParameterDescriptor getImplicitReceiver() {
return null;
}
};
}
catch (IOException e) {
throw new IllegalStateException(e);
}
}
private List<ProtoBuf.Callable> loadCallables() throws IOException {
String packageFilePath = BuiltInsSerializationUtil.getPackageFilePath(this);
InputStream stream = getStream(packageFilePath);
List<ProtoBuf.Callable> callables = new ArrayList<ProtoBuf.Callable>();
while (true) {
ProtoBuf.Callable callable = ProtoBuf.Callable.parseDelimitedFrom(stream);
if (callable == null) {
break;
}
callables.add(callable);
}
return callables;
}
@NotNull
@Override
public JetScope getMemberScope() {
return members;
}
@NotNull
@Override
public FqName getFqName() {
return KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME;
}
@NotNull
private static InputStream getStream(@NotNull String path) {
InputStream stream = getStreamNullable(path);
if (stream == null) {
throw new IllegalStateException("Resource not found in classpath: " + path);
}
return stream;
}
@Nullable
private static InputStream getStreamNullable(@NotNull String path) {
return KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* 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.
@@ -16,18 +16,12 @@
package org.jetbrains.jet.lang.types.lang;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.psi.PsiFileFactory;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,21 +31,18 @@ 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.descriptors.impl.NamespaceDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
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.RedeclarationHandler;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.utils.ExceptionUtils;
import java.io.File;
@@ -69,28 +60,9 @@ public class KotlinBuiltIns {
public static final String BUILT_INS_DIR = "jet";
public static final String BUILT_INS_PACKAGE_NAME_STRING = "jet";
private static final Name BUILT_INS_PACKAGE_NAME = Name.identifier(BUILT_INS_PACKAGE_NAME_STRING);
/* package */ 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(
BUILT_INS_DIR + "/Library.jet",
BUILT_INS_DIR + "/Numbers.jet",
BUILT_INS_DIR + "/Ranges.jet",
BUILT_INS_DIR + "/Progressions.jet",
BUILT_INS_DIR + "/Iterators.jet",
BUILT_INS_DIR + "/Arrays.jet",
BUILT_INS_DIR + "/Enum.jet",
BUILT_INS_DIR + "/Collections.jet",
BUILT_INS_DIR + "/Any.jet",
BUILT_INS_DIR + "/ExtensionFunctions.jet",
BUILT_INS_DIR + "/Functions.jet",
BUILT_INS_DIR + "/KFunctions.jet",
BUILT_INS_DIR + "/KMemberFunctions.jet",
BUILT_INS_DIR + "/KExtensionFunctions.jet",
BUILT_INS_DIR + "/Nothing.jet",
BUILT_INS_DIR + "/Unit.jet"
);
public static final int FUNCTION_TRAIT_COUNT = 23;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -100,16 +72,9 @@ public class KotlinBuiltIns {
private static volatile boolean initializing;
private static Throwable initializationFailed;
public enum InitializationMode {
// Multi-threaded mode is used in the IDE
MULTI_THREADED,
// Single-threaded mode is used in the compiler and IDE-independent tests
SINGLE_THREADED
}
// 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, @NotNull InitializationMode initializationMode) {
public static synchronized void initialize() {
if (instance == null) {
if (initializationFailed != null) {
throw new RuntimeException(
@@ -120,8 +85,8 @@ public class KotlinBuiltIns {
}
initializing = true;
try {
instance = new KotlinBuiltIns(project);
instance.initialize(initializationMode == InitializationMode.MULTI_THREADED);
instance = new KotlinBuiltIns();
instance.doInitialize();
}
catch (Throwable e) {
initializationFailed = e;
@@ -149,7 +114,6 @@ public class KotlinBuiltIns {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final KotlinCodeAnalyzer analyzer;
private final ModuleDescriptorImpl builtInsModule;
private volatile ImmutableSet<ClassDescriptor> nonPhysicalClasses;
@@ -180,13 +144,13 @@ public class KotlinBuiltIns {
private volatile JetType stringType;
private volatile JetType annotationType;
private KotlinBuiltIns(@NotNull Project project) {
private KotlinBuiltIns() {
try {
this.builtInsModule = new ModuleDescriptorImpl(Name.special("<built-ins lazy module>"),
DefaultModuleConfiguration.DEFAULT_JET_IMPORTS,
PlatformToKotlinClassMap.EMPTY);
builtInsModule.setModuleConfiguration(ModuleConfiguration.EMPTY);
this.analyzer = createLazyResolveSession(project);
loadBuiltIns(builtInsModule);
this.functionClassesSet = computeIndexedClasses("Function", FUNCTION_TRAIT_COUNT);
this.extensionFunctionClassesSet = computeIndexedClasses("ExtensionFunction", FUNCTION_TRAIT_COUNT);
@@ -213,7 +177,19 @@ public class KotlinBuiltIns {
}
}
private void initialize(boolean forceResolveAll) {
private static void loadBuiltIns(@NotNull ModuleDescriptorImpl module) throws IOException {
NamespaceDescriptorImpl rootNamespace =
new NamespaceDescriptorImpl(module, Collections.<AnnotationDescriptor>emptyList(), JetPsiUtil.ROOT_NAMESPACE_NAME);
rootNamespace.initialize(
new WritableScopeImpl(JetScope.EMPTY, rootNamespace, RedeclarationHandler.DO_NOTHING, "members of root namespace"));
module.setRootNamespace(rootNamespace);
rootNamespace.getMemberScope().addNamespace(new BuiltinsNamespaceDescriptorImpl(rootNamespace));
rootNamespace.getMemberScope().changeLockLevel(WritableScope.LockLevel.READING);
}
private void doInitialize() {
anyType = getBuiltInTypeByClassName("Any");
nullableAnyType = TypeUtils.makeNullable(anyType);
nothingType = getBuiltInTypeByClassName("Nothing");
@@ -227,42 +203,6 @@ public class KotlinBuiltIns {
}
nonPhysicalClasses = computeNonPhysicalClasses();
if (forceResolveAll) {
analyzer.forceResolveAll();
}
AnalyzingUtils.throwExceptionOnErrors(analyzer.getBindingContext());
}
@NotNull
private KotlinCodeAnalyzer createLazyResolveSession(@NotNull Project project) throws IOException {
List<JetFile> files = loadResourcesAsJetFiles(project, LIBRARY_FILES);
LockBasedStorageManager storageManager = new LockBasedStorageManager();
return new ResolveSession(
project,
storageManager,
builtInsModule,
new FileBasedDeclarationProviderFactory(storageManager, files),
ResolveSession.NO_ALIASES,
Predicates.in(Sets.newHashSet(new FqNameUnsafe("jet.Any"), new FqNameUnsafe("jet.Nothing"))),
new BindingTraceContext());
}
@NotNull
private static List<JetFile> loadResourcesAsJetFiles(@NotNull Project project, @NotNull List<String> libraryFiles)
throws IOException, ProcessCanceledException
{
List<JetFile> files = new LinkedList<JetFile>();
for(String path : libraryFiles) {
String text = loadBuiltInFileText(path);
JetFile file = (JetFile) PsiFileFactory.getInstance(project).createFileFromText(
path, JetFileType.INSTANCE, StringUtil.convertLineSeparators(text), LocalTimeCounter.currentTime(), true, false);
files.add(file);
}
return files;
}
private void makePrimitive(PrimitiveType primitiveType) {
@@ -280,21 +220,6 @@ public class KotlinBuiltIns {
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
}
private static String loadBuiltInFileText(String path) throws IOException {
InputStream stream = KotlinBuiltIns.class.getClassLoader().getResourceAsStream(path);
if (stream == null) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
//noinspection TestOnlyProblems
return FileUtil.loadFile(getInTestBuiltInPath(path));
}
throw new IllegalStateException("Resource not found in classpath: " + path);
}
//noinspection IOResourceOpenedButNotSafelyClosed
return FileUtil.loadTextAndClose(new InputStreamReader(stream));
}
@TestOnly
private static File getInTestBuiltInPath(String path) {
return new File("compiler/frontend/builtins", path);
@@ -303,7 +228,7 @@ public class KotlinBuiltIns {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@NotNull
public static URL getBuiltInsDirUrl() {
String builtInFilePath = "/" + LIBRARY_FILES.get(0);
String builtInFilePath = "/" + BUILT_INS_DIR + "/Library.jet";
URL url = KotlinBuiltIns.class.getResource(builtInFilePath);
@@ -33,7 +33,7 @@ public class BuiltInsInitializer {
// MULTI_THREADED is important not only because of threading as such: since built-ins rely on a project,
// if they are not fully initialized when a project is closed,
// they will be referencing invalid PSI upon a next request
KotlinBuiltIns.initialize(project, KotlinBuiltIns.InitializationMode.MULTI_THREADED);
KotlinBuiltIns.initialize();
}
});
}
+1 -1
View File
@@ -63,7 +63,7 @@ public class Converter {
public Converter(@NotNull Project project) {
this.project = project;
KotlinBuiltIns.initialize(project, KotlinBuiltIns.InitializationMode.MULTI_THREADED);
KotlinBuiltIns.initialize();
}
@NotNull