diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java index 5320a9e6591..0ccb9b9b1de 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java @@ -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() { diff --git a/compiler/frontend/frontend.iml b/compiler/frontend/frontend.iml index 0bdaedc834d..3753a2f48fa 100644 --- a/compiler/frontend/frontend.iml +++ b/compiler/frontend/frontend.iml @@ -5,6 +5,7 @@ + diff --git a/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedPackageMemberScope.java b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedPackageMemberScope.java new file mode 100644 index 00000000000..56694a82e42 --- /dev/null +++ b/compiler/frontend/serialization/src/org/jetbrains/jet/descriptors/serialization/descriptors/DeserializedPackageMemberScope.java @@ -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 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 result) { + findClassifiers(result, false); + } + + @NotNull + @Override + protected Collection computeAllObjectDescriptors() { + return findClassifiers(new ArrayList(), true); + } + + private > 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 getClassNames(); + + @Override + protected void addNonDeclaredDescriptors(@NotNull Collection result) { + // Do nothing + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/BuiltinsNamespaceDescriptorImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/BuiltinsNamespaceDescriptorImpl.java new file mode 100644 index 00000000000..4afb8819612 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/BuiltinsNamespaceDescriptorImpl.java @@ -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.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> classNames = new NotNullLazyValueImpl>() { + @NotNull + @Override + protected Collection doCompute() { + InputStream namesStream = + getStream(BuiltInsSerializationUtil.getClassNamesFilePath(BuiltinsNamespaceDescriptorImpl.this)); + List result = new ArrayList(); + 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 getClassNames() { + return classNames.compute(); + } + + @Nullable + @Override + protected ReceiverParameterDescriptor getImplicitReceiver() { + return null; + } + }; + + } + catch (IOException e) { + throw new IllegalStateException(e); + } + + + } + + private List loadCallables() throws IOException { + String packageFilePath = BuiltInsSerializationUtil.getPackageFilePath(this); + InputStream stream = getStream(packageFilePath); + + List callables = new ArrayList(); + 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); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java index 6b1e72f44e0..906a3dae8c1 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/lang/KotlinBuiltIns.java @@ -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 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 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(""), 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.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 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 loadResourcesAsJetFiles(@NotNull Project project, @NotNull List libraryFiles) - throws IOException, ProcessCanceledException - { - List files = new LinkedList(); - 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); diff --git a/idea/src/org/jetbrains/jet/plugin/BuiltInsInitializer.java b/idea/src/org/jetbrains/jet/plugin/BuiltInsInitializer.java index c1c03bd1945..736d0d3341c 100644 --- a/idea/src/org/jetbrains/jet/plugin/BuiltInsInitializer.java +++ b/idea/src/org/jetbrains/jet/plugin/BuiltInsInitializer.java @@ -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(); } }); } diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.java b/j2k/src/org/jetbrains/jet/j2k/Converter.java index f4abee3d06a..5e5b7ea357e 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.java +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.java @@ -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