JS: fix some bugs:

1. Fix translation of FQN in inline lambdas
2. Fix StringBuilder.length
3. Workaround order of declaration of names for imported declarations
This commit is contained in:
Alexey Andreev
2016-10-21 18:45:13 +03:00
parent fd158a6922
commit 8eca8efae5
4 changed files with 37 additions and 71 deletions
+3 -3
View File
@@ -30,7 +30,8 @@ class StringBuilder(content: String = "") : Appendable, CharSequence {
private var string: String = content
override val length: Int = string.length
override val length: Int
get() = string.asDynamic().length
override fun get(index: Int): Char = string[index]
@@ -57,8 +58,7 @@ class StringBuilder(content: String = "") : Appendable, CharSequence {
}
fun reverse(): StringBuilder {
val nativeString: dynamic = string
string = nativeString.split("").reverse().join("")
string = string.asDynamic().split("").reverse().join("")
return this
}
@@ -53,7 +53,6 @@ import static org.jetbrains.kotlin.js.config.LibrarySourcesConfig.UNKNOWN_EXTERN
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isLibraryObject;
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn;
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getContainingDeclaration;
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSuperclass;
/**
@@ -366,7 +365,7 @@ public final class StaticContext {
}
@NotNull
public JsName getNameForPackage(@NotNull final FqName packageFqName) {
private JsName getNameForPackage(@NotNull final FqName packageFqName) {
return ContainerUtil.getOrCreate(packageNames, packageFqName, new Factory<JsName>() {
@Override
public JsName create() {
@@ -409,11 +408,26 @@ public final class StaticContext {
@NotNull
public JsName importDeclaration(@NotNull String suggestedName, @NotNull JsExpression declaration) {
JsName result = rootFunction.getScope().declareFreshName(suggestedName);
// 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
// declare all names in global scope before running translator, we would have got `foo_1` for local variable,
// since local scope inherited from global scope.
// TODO: remove prefix when problem with scopes is solved
JsName result = rootFunction.getScope().declareFreshName("imported$" + suggestedName);
importStatements.add(JsAstUtils.newVar(result, declaration));
return result;
}
@NotNull
private JsName localOrImportedName(@NotNull DeclarationDescriptor descriptor, @NotNull String suggestedName) {
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
return module != currentModule ?
importDeclaration(suggestedName, getQualifiedReference(descriptor)) :
rootFunction.getScope().declareFreshName(suggestedName);
}
private final class InnerNameGenerator extends Generator<JsName> {
public InnerNameGenerator() {
addRule(new Rule<JsName>() {
@@ -431,12 +445,7 @@ public final class StaticContext {
return getInnerNameForDescriptor(((ConstructorDescriptor) descriptor).getConstructedClass());
}
}
JsName result = rootFunction.getScope().declareFreshName(getSuggestedName(descriptor));
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
if (module != currentModule) {
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
}
return result;
return localOrImportedName(descriptor, getSuggestedName(descriptor));
}
});
}
@@ -449,12 +458,7 @@ public final class StaticContext {
@Override
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX;
JsName result = rootFunction.getScope().declareFreshName(suggested);
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
if (module != currentModule) {
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
}
return result;
return localOrImportedName(descriptor, suggested);
}
});
}
@@ -508,18 +512,6 @@ public final class StaticContext {
return suggestedName;
}
@NotNull
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name, boolean fresh) {
JsScope scope = getEnclosingScope(descriptor);
return fresh ? scope.declareFreshName(name) : scope.declareName(name);
}
@NotNull
private JsScope getEnclosingScope(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
return getScopeForDescriptor(containingDeclaration.getOriginal());
}
private final class ScopeGenerator extends Generator<JsScope> {
public ScopeGenerator() {
@@ -229,11 +229,6 @@ public class TranslationContext {
return staticContext.getNameForObjectInstance(descriptor);
}
@NotNull
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name) {
return staticContext.declarePropertyOrPropertyAccessorName(descriptor, name, false);
}
@NotNull
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof MemberDescriptor && isFromCurrentModule(descriptor) && isPublicInlineFunction()) {
@@ -620,9 +615,15 @@ public class TranslationContext {
}
public boolean isPublicInlineFunction() {
if (!(declarationDescriptor instanceof FunctionDescriptor)) return false;
FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor;
return function.isInline() && DescriptorUtilsKt.isEffectivelyPublicApi(function);
DeclarationDescriptor descriptor = declarationDescriptor;
while (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor function = (FunctionDescriptor) descriptor;
if (function.isInline() && DescriptorUtilsKt.isEffectivelyPublicApi(function)) {
return true;
}
descriptor = descriptor.getContainingDeclaration();
}
return false;
}
@NotNull
@@ -17,15 +17,14 @@
package org.jetbrains.kotlin.js.translate.utils;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.StaticContext;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.js.translate.context.Namer;
import org.jetbrains.kotlin.js.translate.context.TemporaryConstVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation;
@@ -41,7 +40,6 @@ import static com.google.dart.compiler.backend.js.ast.JsBinaryOperator.*;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDescriptorForOperationExpression;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.createDataDescriptor;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isAnonymousObject;
public final class TranslationUtils {
@@ -84,8 +82,9 @@ public final class TranslationUtils {
@NotNull
public static JsExpression translateExclForBinaryEqualLikeExpr(@NotNull JsBinaryOperation baseBinaryExpression) {
return new JsBinaryOperation(notOperator(baseBinaryExpression.getOperator()), baseBinaryExpression.getArg1(),
baseBinaryExpression.getArg2());
JsBinaryOperator negatedOperator = notOperator(baseBinaryExpression.getOperator());
assert negatedOperator != null : "Can't negate operator: " + baseBinaryExpression.getOperator();
return new JsBinaryOperation(negatedOperator, baseBinaryExpression.getArg1(), baseBinaryExpression.getArg2());
}
public static boolean isEqualLikeOperator(@NotNull JsBinaryOperator operator) {
@@ -153,8 +152,7 @@ public final class TranslationUtils {
context.getNameForDescriptor(descriptor);
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
JsName backingFieldMangledName = context.getNameForBackingField(descriptor);
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, backingFieldMangledName.getIdent());
backingFieldName = context.getNameForBackingField(descriptor);
}
JsExpression receiver;
@@ -264,31 +262,6 @@ public final class TranslationUtils {
return ensureNotNull;
}
@NotNull
public static String getSuggestedNameForInnerDeclaration(StaticContext context, DeclarationDescriptor descriptor) {
String suggestedName = "";
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
//noinspection ConstantConditions
if (containingDeclaration != null &&
!(containingDeclaration instanceof ClassOrPackageFragmentDescriptor) &&
!(containingDeclaration instanceof AnonymousFunctionDescriptor) &&
!(containingDeclaration instanceof ConstructorDescriptor && isAnonymousObject(containingDeclaration.getContainingDeclaration()))) {
suggestedName = context.getNameForDescriptor(containingDeclaration).getIdent();
}
if (!suggestedName.isEmpty() && !suggestedName.endsWith("$")) {
suggestedName += "$";
}
if (descriptor.getName().isSpecial()) {
suggestedName += "f";
}
else {
suggestedName += context.getNameForDescriptor(descriptor).getIdent();
}
return suggestedName;
}
public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) {
if (!(expression instanceof KtSimpleNameExpression)) {
return false;