JS: support imports in new pipeline
This commit is contained in:
@@ -40,6 +40,7 @@ import org.jetbrains.kotlin.js.translate.declaration.ClassModelGenerator;
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics;
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.SignatureUtilsKt;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
@@ -115,6 +116,8 @@ public final class StaticContext {
|
||||
@NotNull
|
||||
private final Map<DeclarationDescriptor, JsExpression> fqnCache = new HashMap<>();
|
||||
|
||||
private final Map<DeclarationDescriptor, String> tagCache = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
private final Map<JsImportedModuleKey, JsImportedModule> importedModules = new LinkedHashMap<>();
|
||||
|
||||
@@ -123,9 +126,6 @@ public final class StaticContext {
|
||||
@NotNull
|
||||
private final JsScope rootPackageScope;
|
||||
|
||||
@NotNull
|
||||
private final List<JsStatement> importStatements = new ArrayList<>();
|
||||
|
||||
@NotNull
|
||||
private final DeclarationExporter exporter = new DeclarationExporter(this);
|
||||
|
||||
@@ -220,6 +220,19 @@ public final class StaticContext {
|
||||
return (JsNameRef) getQualifiedExpression(descriptor);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getTag(@NotNull DeclarationDescriptor descriptor) {
|
||||
String tag;
|
||||
if (!tagCache.containsKey(descriptor)) {
|
||||
tag = SignatureUtilsKt.generateSignature(descriptor);
|
||||
tagCache.put(descriptor, tag);
|
||||
}
|
||||
else {
|
||||
tag = tagCache.get(descriptor);
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsExpression getQualifiedExpression(@NotNull DeclarationDescriptor descriptor) {
|
||||
JsExpression fqn = fqnCache.computeIfAbsent(descriptor, this::buildQualifiedExpression);
|
||||
@@ -451,7 +464,7 @@ public final class StaticContext {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsName importDeclaration(@NotNull String suggestedName, @NotNull JsExpression declaration) {
|
||||
public JsName importDeclaration(@NotNull String suggestedName, @NotNull String tag, @NotNull JsExpression declaration) {
|
||||
// Adding prefix is a workaround for a problem with scopes.
|
||||
// Consider we declare name `foo` in functions's local scope, then call top-level function `foo`
|
||||
// from another module. It's imported into global scope under name `foo`. If we could somehow
|
||||
@@ -461,16 +474,25 @@ public final class StaticContext {
|
||||
|
||||
JsName result = fragment.getScope().declareTemporaryName(suggestedName);
|
||||
MetadataProperties.setImported(result, true);
|
||||
importStatements.add(JsAstUtils.newVar(result, declaration));
|
||||
fragment.getImports().put(tag, declaration);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JsName localOrImportedName(@NotNull DeclarationDescriptor descriptor, @NotNull String suggestedName) {
|
||||
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
||||
JsName name = module != currentModule ?
|
||||
importDeclaration(suggestedName, getQualifiedReference(descriptor)) :
|
||||
fragment.getScope().declareTemporaryName(suggestedName);
|
||||
JsName name;
|
||||
String tag = getTag(descriptor);
|
||||
if (module != currentModule) {
|
||||
assert tag != null : "Can't import declaration without fqname: " + descriptor;
|
||||
name = importDeclaration(suggestedName, tag, getQualifiedReference(descriptor));
|
||||
}
|
||||
else {
|
||||
name = fragment.getScope().declareTemporaryName(suggestedName);
|
||||
}
|
||||
if (tag != null) {
|
||||
fragment.getNameBindings().add(new JsNameBinding(tag, name));
|
||||
}
|
||||
MetadataProperties.setDescriptor(name, descriptor);
|
||||
return name;
|
||||
}
|
||||
@@ -672,14 +694,13 @@ public final class StaticContext {
|
||||
return suggestedName.getNames().get(0);
|
||||
}
|
||||
|
||||
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
||||
private static void applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof FunctionDescriptor ||
|
||||
descriptor instanceof PackageFragmentDescriptor ||
|
||||
descriptor instanceof ClassDescriptor
|
||||
) {
|
||||
) {
|
||||
MetadataProperties.setSideEffects(expression, SideEffectKind.PURE);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
public void putClassOrConstructorClosure(@NotNull MemberDescriptor localClass, @NotNull List<DeclarationDescriptor> closure) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.js.backend.ast.*
|
||||
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.utils.JsAstUtils
|
||||
|
||||
class Merger(private val rootFunction: JsFunction, val internalModuleName: JsName) {
|
||||
// Maps unique signature (see generateSignature) to names
|
||||
@@ -28,12 +29,20 @@ class Merger(private val rootFunction: JsFunction, val internalModuleName: JsNam
|
||||
private val declarationBlock = JsGlobalBlock()
|
||||
private val initializerBlock = JsGlobalBlock()
|
||||
private val exportBlock = JsGlobalBlock()
|
||||
private val declaredImports = mutableSetOf<String>()
|
||||
|
||||
// Add declaration and initialization statements from program fragment to resulting single program
|
||||
fun addFragment(fragment: JsProgramFragment) {
|
||||
val nameMap = buildNameMap(fragment)
|
||||
nameMap.rename(fragment)
|
||||
|
||||
for ((key, importExpr) in fragment.imports) {
|
||||
if (declaredImports.add(key)) {
|
||||
val name = nameTable[key]!!
|
||||
importBlock.statements += JsAstUtils.newVar(nameMap.rename(name), nameMap.rename(importExpr))
|
||||
}
|
||||
}
|
||||
|
||||
declarationBlock.statements += fragment.declarationBlock
|
||||
initializerBlock.statements += fragment.initializerBlock
|
||||
exportBlock.statements += fragment.exportBlock
|
||||
|
||||
@@ -262,7 +262,8 @@ public final class Translation {
|
||||
) {
|
||||
JsProgram program = new JsProgram();
|
||||
JsFunction rootFunction = new JsFunction(program.getRootScope(), new JsBlock(), "root function");
|
||||
Merger merger = new Merger(rootFunction);
|
||||
JsName internalModuleName = program.getScope().declareName("_");
|
||||
Merger merger = new Merger(rootFunction, internalModuleName);
|
||||
|
||||
List<JsProgramFragment> fragments = new ArrayList<JsProgramFragment>();
|
||||
for (KtFile file : files) {
|
||||
@@ -279,8 +280,6 @@ public final class Translation {
|
||||
|
||||
List<JsStatement> statements = rootBlock.getStatements();
|
||||
|
||||
program.getScope().declareName("_");
|
||||
|
||||
//staticContext.postProcess();
|
||||
statements.add(0, program.getStringLiteral("use strict").makeStmt());
|
||||
if (!isBuiltinModule(fragments)) {
|
||||
|
||||
+6
-5
@@ -16,11 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.intrinsic.objects
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
import org.jetbrains.kotlin.builtins.CompanionObjectMapping
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.StaticContext
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
@@ -29,10 +29,10 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
|
||||
class DefaultClassObjectIntrinsic(val staticContext: StaticContext, val fqName: FqName): ObjectIntrinsic {
|
||||
class DefaultClassObjectIntrinsic(val staticContext: StaticContext, val tag: String, val fqName: FqName): ObjectIntrinsic {
|
||||
private val innerName: JsName by lazy {
|
||||
val declaration = JsAstUtils.replaceRootReference(staticContext.getQualifiedReference(fqName), Namer.kotlinObject())
|
||||
staticContext.importDeclaration(fqName.shortName().asString(), declaration)
|
||||
staticContext.importDeclaration(fqName.shortName().asString(), tag, declaration)
|
||||
}
|
||||
|
||||
override fun apply(context: TranslationContext) = JsAstUtils.pureFqn(innerName, null)
|
||||
@@ -53,7 +53,8 @@ class ObjectIntrinsics(private val staticContext: StaticContext) {
|
||||
val containingDeclaration = classDescriptor.containingDeclaration
|
||||
val name = Name.identifier(containingDeclaration.name.asString() + "CompanionObject")
|
||||
|
||||
return DefaultClassObjectIntrinsic(staticContext, FqName("kotlin.js.internal").child(name))
|
||||
return DefaultClassObjectIntrinsic(
|
||||
staticContext, "intrinsic:kotlin.js.internal.${name.asString()}", FqName("kotlin.js.internal").child(name))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ fun generateSignature(descriptor: DeclarationDescriptor): String? {
|
||||
if (DescriptorUtils.isDescriptorWithLocalVisibility(descriptor)) return null
|
||||
if (descriptor is DeclarationDescriptorWithVisibility && descriptor.visibility == Visibilities.PRIVATE &&
|
||||
!AnnotationsUtils.isNativeObject(descriptor) && !AnnotationsUtils.isLibraryObject(descriptor)
|
||||
) {
|
||||
) {
|
||||
return null
|
||||
}
|
||||
return when (descriptor) {
|
||||
|
||||
Reference in New Issue
Block a user