Reimplemented non-trivial logic of ModuleConfiguration.

This commit is contained in:
Evgeny Gerashchenko
2013-10-30 11:37:55 +04:00
parent 19d8f1394b
commit 67f06c816b
7 changed files with 70 additions and 91 deletions
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.test.config;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.Config;
@@ -33,8 +34,9 @@ public class TestConfig extends Config {
public TestConfig create(@NotNull Project project, public TestConfig create(@NotNull Project project,
@NotNull EcmaVersion version, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull List<JetFile> files,
@NotNull BindingContext context) { @NotNull BindingContext libraryContext,
return new TestConfig(project, version, files, context, false); @NotNull ModuleDescriptor module) {
return new TestConfig(project, version, files, libraryContext, module, false);
} }
}; };
@@ -43,8 +45,9 @@ public class TestConfig extends Config {
public TestConfig create(@NotNull Project project, public TestConfig create(@NotNull Project project,
@NotNull EcmaVersion version, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull List<JetFile> files,
@NotNull BindingContext context) { @NotNull BindingContext libraryContext,
return new TestConfig(project, version, files, context, true); @NotNull ModuleDescriptor module) {
return new TestConfig(project, version, files, libraryContext, module, true);
} }
}; };
@@ -52,19 +55,29 @@ public class TestConfig extends Config {
private final List<JetFile> jsLibFiles; private final List<JetFile> jsLibFiles;
@NotNull @NotNull
private final BindingContext libraryContext; private final BindingContext libraryContext;
@NotNull
private final ModuleDescriptor libraryModule;
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version, public TestConfig(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull BindingContext context, boolean sourcemap) { @NotNull List<JetFile> files, @NotNull BindingContext libraryContext, @NotNull ModuleDescriptor module, boolean sourcemap) {
super(project, REWRITABLE_MODULE_NAME, version, sourcemap); super(project, REWRITABLE_MODULE_NAME, version, sourcemap);
jsLibFiles = files; jsLibFiles = files;
libraryContext = context; this.libraryContext = libraryContext;
libraryModule = module;
} }
@NotNull
@Override @Override
public BindingContext getLibraryBindingContext() { public BindingContext getLibraryContext() {
return libraryContext; return libraryContext;
} }
@NotNull
@Override
public ModuleDescriptor getLibraryModule() {
return libraryModule;
}
@Override @Override
@NotNull @NotNull
public List<JetFile> generateLibFiles() { public List<JetFile> generateLibFiles() {
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.test.config;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
@@ -26,5 +27,5 @@ import java.util.List;
public interface TestConfigFactory { public interface TestConfigFactory {
TestConfig create(@NotNull Project project, @NotNull EcmaVersion version, TestConfig create(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull BindingContext context); @NotNull List<JetFile> files, @NotNull BindingContext libraryContext, @NotNull ModuleDescriptor module);
} }
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.test.config;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
@@ -34,8 +35,9 @@ public class TestConfigWithUnitTests extends TestConfig {
public TestConfig create(@NotNull Project project, public TestConfig create(@NotNull Project project,
@NotNull EcmaVersion version, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull List<JetFile> files,
@NotNull BindingContext context) { @NotNull BindingContext libraryContext,
return new TestConfigWithUnitTests(project, version, files, context); @NotNull ModuleDescriptor module) {
return new TestConfigWithUnitTests(project, version, files, libraryContext, module);
} }
}; };
@@ -47,7 +49,8 @@ public class TestConfigWithUnitTests extends TestConfig {
public TestConfigWithUnitTests(@NotNull Project project, public TestConfigWithUnitTests(@NotNull Project project,
@NotNull EcmaVersion version, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull List<JetFile> files,
@NotNull BindingContext context) { @NotNull BindingContext libraryContext,
super(project, version, files, context, false); @NotNull ModuleDescriptor module) {
super(project, version, files, libraryContext, module, false);
} }
} }
@@ -27,7 +27,6 @@ import org.jetbrains.jet.OutputFileCollection;
import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage; import org.jetbrains.jet.cli.common.output.outputUtils.OutputUtilsPackage;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS; import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS;
import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.Config;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
@@ -50,7 +49,7 @@ public final class TranslationUtils {
} }
@NotNull @NotNull
private static SoftReference<BindingContext> cachedLibraryContext = new SoftReference<BindingContext>(null); private static SoftReference<AnalyzeExhaust> cachedLibraryExhaust = new SoftReference<AnalyzeExhaust>(null);
@Nullable @Nullable
private static List<JetFile> libFiles = null; private static List<JetFile> libFiles = null;
@@ -64,24 +63,23 @@ public final class TranslationUtils {
} }
@NotNull @NotNull
public static BindingContext getLibraryContext(@NotNull Project project) { public static AnalyzeExhaust getLibraryAnalyzeExhaust(@NotNull Project project) {
BindingContext context = cachedLibraryContext.get(); AnalyzeExhaust cachedModule = cachedLibraryExhaust.get();
if (context == null) { if (cachedModule != null) {
List<JetFile> allLibFiles = getAllLibFiles(project); return cachedModule;
Predicate<PsiFile> filesWithCode = new Predicate<PsiFile>() {
@Override
public boolean apply(@Nullable PsiFile file) {
assert file != null;
return isFileWithCode((JetFile) file);
}
};
AnalyzeExhaust exhaust = AnalyzerFacadeForJS
.analyzeFiles(allLibFiles, filesWithCode, Config.getEmptyConfig(project));
context = exhaust.getBindingContext();
AnalyzerFacadeForJS.checkForErrors(allLibFiles, context);
cachedLibraryContext = new SoftReference<BindingContext>(context);
} }
return context; List<JetFile> allLibFiles = getAllLibFiles(project);
Predicate<PsiFile> filesWithCode = new Predicate<PsiFile>() {
@Override
public boolean apply(@Nullable PsiFile file) {
assert file != null;
return isFileWithCode((JetFile) file);
}
};
AnalyzeExhaust exhaust = AnalyzerFacadeForJS.analyzeFiles(allLibFiles, filesWithCode, Config.getEmptyConfig(project));
AnalyzerFacadeForJS.checkForErrors(allLibFiles, exhaust.getBindingContext());
cachedLibraryExhaust = new SoftReference<AnalyzeExhaust>(exhaust);
return exhaust;
} }
private static boolean isFileWithCode(@NotNull JetFile file) { private static boolean isFileWithCode(@NotNull JetFile file) {
@@ -95,8 +93,10 @@ public final class TranslationUtils {
@NotNull @NotNull
public static Config getConfig(@NotNull Project project, @NotNull EcmaVersion version, @NotNull TestConfigFactory configFactory) { public static Config getConfig(@NotNull Project project, @NotNull EcmaVersion version, @NotNull TestConfigFactory configFactory) {
BindingContext preanalyzedContext = getLibraryContext(project); AnalyzeExhaust libraryAnalyzeExhaust = getLibraryAnalyzeExhaust(project);
return configFactory.create(project, version, getLibFilesWithCode(getAllLibFiles(project)), preanalyzedContext); return configFactory.create(
project, version, getLibFilesWithCode(getAllLibFiles(project)),
libraryAnalyzeExhaust.getBindingContext(), libraryAnalyzeExhaust.getModuleDescriptor());
} }
public static void translateFiles( public static void translateFiles(
@@ -84,14 +84,19 @@ public final class AnalyzerFacadeForJS {
TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters( TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
completely, false, false, Collections.<AnalyzerScriptParameter>emptyList()); completely, false, false, Collections.<AnalyzerScriptParameter>emptyList());
BindingContext libraryBindingContext = config.getLibraryBindingContext(); ModuleDescriptor libraryModule = config.getLibraryModule();
BindingTrace trace = libraryBindingContext == null ? if (libraryModule != null) {
new ObservableBindingTrace(new BindingTraceContext()) : owner.addFragmentProvider(libraryModule.getPackageFragmentProvider()); // "import" analyzed library module
new DelegatingBindingTrace(libraryBindingContext, "trace for analyzing library in js"); }
owner.setModuleConfiguration(new JsConfiguration(libraryBindingContext));
BindingContext libraryContext = config.getLibraryContext();
BindingTrace trace = libraryContext == null
? new BindingTraceContext()
: new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
owner.setModuleConfiguration(new JsConfiguration());
InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner); InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner);
try { try {
Collection<JetFile> allFiles = libraryBindingContext != null ? Collection<JetFile> allFiles = libraryModule != null ?
files : files :
Config.withJsLibAdded(files, config); Config.withJsLibAdded(files, config);
injector.getTopDownAnalyzer().analyzeFiles(allFiles, Collections.<AnalyzerScriptParameter>emptyList()); injector.getTopDownAnalyzer().analyzeFiles(allFiles, Collections.<AnalyzerScriptParameter>emptyList());
@@ -144,7 +149,7 @@ public final class AnalyzerFacadeForJS {
FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory( FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(
storageManager, Config.withJsLibAdded(files, config), Predicates.<FqName>alwaysFalse()); storageManager, Config.withJsLibAdded(files, config), Predicates.<FqName>alwaysFalse());
ModuleDescriptorImpl lazyModule = createJsModule("<lazy module>"); ModuleDescriptorImpl lazyModule = createJsModule("<lazy module>");
lazyModule.setModuleConfiguration(new JsConfiguration(null)); lazyModule.setModuleConfiguration(new JsConfiguration());
return new ResolveSession(config.getProject(), storageManager, lazyModule, declarationProviderFactory); return new ResolveSession(config.getProject(), storageManager, lazyModule, declarationProviderFactory);
} }
@@ -18,22 +18,14 @@ package org.jetbrains.k2js.analyze;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.jetbrains.annotations.NotNull; 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.ModuleConfiguration;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isRootNamespace;
public class JsConfiguration implements ModuleConfiguration { public class JsConfiguration implements ModuleConfiguration {
@NotNull @NotNull
@@ -43,51 +35,10 @@ public class JsConfiguration implements ModuleConfiguration {
new ImportPath(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName(), true), new ImportPath(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName(), true),
new ImportPath("kotlin.*")); new ImportPath("kotlin.*"));
/* JsConfiguration() {
* Adds a possibility to inject some preanalyzed files to speed up tests.
*/
@Nullable
private final BindingContext preanalyzedContext;
JsConfiguration(@Nullable BindingContext preanalyzedContext) {
this.preanalyzedContext = preanalyzedContext;
} }
@Override @Override
public void extendNamespaceScope(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) { public void extendNamespaceScope(@NotNull NamespaceDescriptor namespaceDescriptor, @NotNull WritableScope namespaceMemberScope) {
DefaultModuleConfiguration.INSTANCE.extendNamespaceScope(namespaceDescriptor, namespaceMemberScope);
// Extend root namespace with standard classes
if (namespaceDescriptor.getFqName().shortNameOrSpecial().equals(FqNameUnsafe.ROOT_NAME)) {
namespaceMemberScope.importScope(KotlinBuiltIns.getInstance().getBuiltInsScope());
}
if (hasPreanalyzedContextForTests()) {
extendScopeWithPreAnalyzedContextForTests(namespaceDescriptor, namespaceMemberScope);
}
}
private boolean hasPreanalyzedContextForTests() {
return preanalyzedContext != null;
}
/*NOTE: this code is wrong. Check it if you have tests failing for frontend reasons*/
@SuppressWarnings("ConstantConditions")
private void extendScopeWithPreAnalyzedContextForTests(@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull WritableScope namespaceMemberScope) {
if (isNamespaceImportedByDefault(namespaceDescriptor) || isRootNamespace(namespaceDescriptor)) {
FqName descriptorName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
NamespaceDescriptor alreadyAnalyzedNamespace = preanalyzedContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, descriptorName);
namespaceMemberScope.importScope(alreadyAnalyzedNamespace.getMemberScope());
}
}
private static boolean isNamespaceImportedByDefault(@NotNull NamespaceDescriptor namespaceDescriptor) {
for (ImportPath path : DEFAULT_IMPORT_PATHS) {
if (path.fqnPart().equals(DescriptorUtils.getFQName(namespaceDescriptor).toSafe())) {
return true;
}
}
return false;
} }
} }
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.translate.test.JSTester; import org.jetbrains.k2js.translate.test.JSTester;
@@ -190,7 +191,12 @@ public abstract class Config {
} }
@Nullable @Nullable
public BindingContext getLibraryBindingContext() { public BindingContext getLibraryContext() {
return null;
}
@Nullable
public ModuleDescriptor getLibraryModule() {
return null; return null;
} }