JS: support module imports in new pipeline

This commit is contained in:
Alexey Andreev
2017-02-10 19:02:07 +03:00
parent 2354adfa22
commit a414cd64c5
4 changed files with 36 additions and 26 deletions
@@ -121,8 +121,6 @@ public final class StaticContext {
@NotNull @NotNull
private final Map<JsImportedModuleKey, JsImportedModule> importedModules = new LinkedHashMap<>(); private final Map<JsImportedModuleKey, JsImportedModule> importedModules = new LinkedHashMap<>();
private Collection<JsImportedModule> readOnlyImportedModules;
@NotNull @NotNull
private final JsScope rootPackageScope; private final JsScope rootPackageScope;
@@ -153,8 +151,7 @@ public final class StaticContext {
rootPackageScope = new JsObjectScope(rootScope, "<root package>"); rootPackageScope = new JsObjectScope(rootScope, "<root package>");
JsName kotlinName = rootScope.declareName(Namer.KOTLIN_NAME); JsName kotlinName = rootScope.declareName(Namer.KOTLIN_NAME);
importedModules.put(new JsImportedModuleKey(Namer.KOTLIN_LOWER_NAME, null), createImportedModule(new JsImportedModuleKey(Namer.KOTLIN_LOWER_NAME, null), Namer.KOTLIN_LOWER_NAME, kotlinName, null);
new JsImportedModule(Namer.KOTLIN_LOWER_NAME, kotlinName, null));
classModelGenerator = new ClassModelGenerator(this); classModelGenerator = new ClassModelGenerator(this);
} }
@@ -189,14 +186,6 @@ public final class StaticContext {
return namer; return namer;
} }
@NotNull
public Collection<JsImportedModule> getImportedModules() {
if (readOnlyImportedModules == null) {
readOnlyImportedModules = Collections.unmodifiableCollection(importedModules.values());
}
return readOnlyImportedModules;
}
@NotNull @NotNull
public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) { public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ModuleDescriptor) { if (descriptor instanceof ModuleDescriptor) {
@@ -526,7 +515,12 @@ public final class StaticContext {
public ObjectInstanceNameGenerator() { public ObjectInstanceNameGenerator() {
addRule(descriptor -> { addRule(descriptor -> {
String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX; String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX;
return localOrImportedName(descriptor, suggested); JsName result = JsScope.declareTemporaryName(suggested);
String tag = SignatureUtilsKt.generateSignature(descriptor);
if (tag != null) {
fragment.getNameBindings().add(new JsNameBinding("object:" + tag, result));
}
return result;
}); });
} }
} }
@@ -681,12 +675,18 @@ public final class StaticContext {
JsImportedModule module = importedModules.get(key); JsImportedModule module = importedModules.get(key);
if (module == null) { if (module == null) {
JsName internalName = rootScope.declareTemporaryName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName)); JsName internalName = rootScope.declareTemporaryName(Namer.LOCAL_MODULE_PREFIX + Namer.suggestedModuleName(baseName));
module = new JsImportedModule(baseName, internalName, plainName != null ? pureFqn(plainName, null) : null); module = createImportedModule(key, baseName, internalName, plainName != null ? pureFqn(plainName, null) : null);
importedModules.put(key, module);
} }
return module; return module;
} }
private JsImportedModule createImportedModule(JsImportedModuleKey key, String baseName, JsName internalName, JsExpression plainName) {
JsImportedModule module = new JsImportedModule(baseName, internalName, plainName);
importedModules.put(key, module);
fragment.getImportedModules().add(module);
return module;
}
@NotNull @NotNull
private String getPlainId(@NotNull DeclarationDescriptor declaration) { private String getPlainId(@NotNull DeclarationDescriptor declaration) {
SuggestedName suggestedName = nameSuggestion.suggest(declaration); SuggestedName suggestedName = nameSuggestion.suggest(declaration);
@@ -125,11 +125,6 @@ public class TranslationContext {
return null; return null;
} }
@NotNull
public Collection<JsImportedModule> getImportedModules() {
return staticContext.getImportedModules();
}
@Nullable @Nullable
public UsageTracker usageTracker() { public UsageTracker usageTracker() {
return usageTracker; return usageTracker;
@@ -18,19 +18,20 @@ package org.jetbrains.kotlin.js.translate.general
import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
import org.jetbrains.kotlin.js.inline.clean.resolveTemporaryNames
import org.jetbrains.kotlin.js.translate.context.Namer import org.jetbrains.kotlin.js.translate.context.Namer
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
class Merger(private val rootFunction: JsFunction, val internalModuleName: JsName) { class Merger(private val rootFunction: JsFunction, val internalModuleName: JsName) {
// Maps unique signature (see generateSignature) to names // Maps unique signature (see generateSignature) to names
private val nameTable = mutableMapOf<String, JsName>() private val nameTable = mutableMapOf<String, JsName>()
private val importedModuleTable = mutableMapOf<JsImportedModuleKey, JsName>()
private val importBlock = JsGlobalBlock() private val importBlock = JsGlobalBlock()
private val declarationBlock = JsGlobalBlock() private val declarationBlock = JsGlobalBlock()
private val initializerBlock = JsGlobalBlock() private val initializerBlock = JsGlobalBlock()
private val exportBlock = JsGlobalBlock() private val exportBlock = JsGlobalBlock()
private val declaredImports = mutableSetOf<String>() private val declaredImports = mutableSetOf<String>()
private val classes = mutableMapOf<JsName, JsClassModel>() private val classes = mutableMapOf<JsName, JsClassModel>()
private val importedModulesImpl = mutableListOf<JsImportedModule>()
// Add declaration and initialization statements from program fragment to resulting single program // Add declaration and initialization statements from program fragment to resulting single program
fun addFragment(fragment: JsProgramFragment) { fun addFragment(fragment: JsProgramFragment) {
@@ -49,6 +50,9 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
exportBlock.statements += fragment.exportBlock exportBlock.statements += fragment.exportBlock
} }
val importedModules: List<JsImportedModule>
get() = importedModulesImpl
private fun Map<JsName, JsName>.rename(name: JsName): JsName = getOrElse(name) { name } private fun Map<JsName, JsName>.rename(name: JsName): JsName = getOrElse(name) { name }
// Builds mapping to map names from different fragments into single name when they denote single declaration // Builds mapping to map names from different fragments into single name when they denote single declaration
@@ -61,6 +65,19 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
} }
fragment.scope.findName(Namer.getRootPackageName())?.let { nameMap[it] = internalModuleName } fragment.scope.findName(Namer.getRootPackageName())?.let { nameMap[it] = internalModuleName }
for (importedModule in fragment.importedModules) {
nameMap[importedModule.internalName] = importedModuleTable.getOrPut(importedModule.key) {
val scope = rootFunction.scope
val newName = importedModule.internalName.let {
if (it.isTemporary) scope.declareTemporaryName(it.ident) else scope.declareName(it.ident)
}
newName.also {
importedModulesImpl += JsImportedModule(importedModule.externalName, it, importedModule.plainReference)
it.copyMetadataFrom(importedModule.internalName)
}
}
}
return nameMap return nameMap
} }
@@ -99,7 +116,6 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
this += declarationBlock.statements this += declarationBlock.statements
this += initializerBlock.statements this += initializerBlock.statements
} }
rootFunction.body.resolveTemporaryNames()
} }
private fun addClassPrototypes(statements: MutableList<JsStatement>) { private fun addClassPrototypes(statements: MutableList<JsStatement>) {
@@ -292,14 +292,13 @@ public final class Translation {
// Invoke function passing modules as arguments // Invoke function passing modules as arguments
// This should help minifier tool to recognize references to these modules as local variables and make them shorter. // This should help minifier tool to recognize references to these modules as local variables and make them shorter.
List<JsImportedModule> importedModuleList = new ArrayList<>(); List<JsImportedModule> importedModuleList = merger.getImportedModules();
/* for (JsImportedModule importedModule : importedModuleList) {
for (JsImportedModule importedModule : staticContext.getImportedModules()) {
rootFunction.getParameters().add(new JsParameter(importedModule.getInternalName())); rootFunction.getParameters().add(new JsParameter(importedModule.getInternalName()));
importedModuleList.add(importedModule);
} }
/*
if (mainCallParameters.shouldBeGenerated()) { if (mainCallParameters.shouldBeGenerated()) {
JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments()); JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments());
if (statement != null) { if (statement != null) {