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:
@@ -30,7 +30,8 @@ class StringBuilder(content: String = "") : Appendable, CharSequence {
|
|||||||
|
|
||||||
private var string: String = content
|
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]
|
override fun get(index: Int): Char = string[index]
|
||||||
|
|
||||||
@@ -57,8 +58,7 @@ class StringBuilder(content: String = "") : Appendable, CharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun reverse(): StringBuilder {
|
fun reverse(): StringBuilder {
|
||||||
val nativeString: dynamic = string
|
string = string.asDynamic().split("").reverse().join("")
|
||||||
string = nativeString.split("").reverse().join("")
|
|
||||||
return this
|
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.isLibraryObject;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject;
|
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.JsAstUtils.pureFqn;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getContainingDeclaration;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSuperclass;
|
import static org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getSuperclass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -366,7 +365,7 @@ public final class StaticContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName getNameForPackage(@NotNull final FqName packageFqName) {
|
private JsName getNameForPackage(@NotNull final FqName packageFqName) {
|
||||||
return ContainerUtil.getOrCreate(packageNames, packageFqName, new Factory<JsName>() {
|
return ContainerUtil.getOrCreate(packageNames, packageFqName, new Factory<JsName>() {
|
||||||
@Override
|
@Override
|
||||||
public JsName create() {
|
public JsName create() {
|
||||||
@@ -409,11 +408,26 @@ public final class StaticContext {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsName importDeclaration(@NotNull String suggestedName, @NotNull JsExpression declaration) {
|
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));
|
importStatements.add(JsAstUtils.newVar(result, declaration));
|
||||||
return result;
|
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> {
|
private final class InnerNameGenerator extends Generator<JsName> {
|
||||||
public InnerNameGenerator() {
|
public InnerNameGenerator() {
|
||||||
addRule(new Rule<JsName>() {
|
addRule(new Rule<JsName>() {
|
||||||
@@ -431,12 +445,7 @@ public final class StaticContext {
|
|||||||
return getInnerNameForDescriptor(((ConstructorDescriptor) descriptor).getConstructedClass());
|
return getInnerNameForDescriptor(((ConstructorDescriptor) descriptor).getConstructedClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JsName result = rootFunction.getScope().declareFreshName(getSuggestedName(descriptor));
|
return localOrImportedName(descriptor, getSuggestedName(descriptor));
|
||||||
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
|
||||||
if (module != currentModule) {
|
|
||||||
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -449,12 +458,7 @@ public final class StaticContext {
|
|||||||
@Override
|
@Override
|
||||||
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
|
||||||
String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX;
|
String suggested = getSuggestedName(descriptor) + Namer.OBJECT_INSTANCE_FUNCTION_SUFFIX;
|
||||||
JsName result = rootFunction.getScope().declareFreshName(suggested);
|
return localOrImportedName(descriptor, suggested);
|
||||||
ModuleDescriptor module = DescriptorUtilsKt.getModule(descriptor);
|
|
||||||
if (module != currentModule) {
|
|
||||||
importStatements.add(JsAstUtils.newVar(result, getQualifiedReference(descriptor)));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -508,18 +512,6 @@ public final class StaticContext {
|
|||||||
return suggestedName;
|
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> {
|
private final class ScopeGenerator extends Generator<JsScope> {
|
||||||
|
|
||||||
public ScopeGenerator() {
|
public ScopeGenerator() {
|
||||||
|
|||||||
+9
-8
@@ -229,11 +229,6 @@ public class TranslationContext {
|
|||||||
return staticContext.getNameForObjectInstance(descriptor);
|
return staticContext.getNameForObjectInstance(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public JsName declarePropertyOrPropertyAccessorName(@NotNull DeclarationDescriptor descriptor, @NotNull String name) {
|
|
||||||
return staticContext.declarePropertyOrPropertyAccessorName(descriptor, name, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
|
public JsNameRef getQualifiedReference(@NotNull DeclarationDescriptor descriptor) {
|
||||||
if (descriptor instanceof MemberDescriptor && isFromCurrentModule(descriptor) && isPublicInlineFunction()) {
|
if (descriptor instanceof MemberDescriptor && isFromCurrentModule(descriptor) && isPublicInlineFunction()) {
|
||||||
@@ -620,9 +615,15 @@ public class TranslationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPublicInlineFunction() {
|
public boolean isPublicInlineFunction() {
|
||||||
if (!(declarationDescriptor instanceof FunctionDescriptor)) return false;
|
DeclarationDescriptor descriptor = declarationDescriptor;
|
||||||
FunctionDescriptor function = (FunctionDescriptor) declarationDescriptor;
|
while (descriptor instanceof FunctionDescriptor) {
|
||||||
return function.isInline() && DescriptorUtilsKt.isEffectivelyPublicApi(function);
|
FunctionDescriptor function = (FunctionDescriptor) descriptor;
|
||||||
|
if (function.isInline() && DescriptorUtilsKt.isEffectivelyPublicApi(function)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
descriptor = descriptor.getContainingDeclaration();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -17,15 +17,14 @@
|
|||||||
package org.jetbrains.kotlin.js.translate.utils;
|
package org.jetbrains.kotlin.js.translate.utils;
|
||||||
|
|
||||||
import com.google.dart.compiler.backend.js.ast.*;
|
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.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
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.LocalVariableAccessorDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
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.TemporaryConstVariable;
|
||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
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.BindingUtils.getCallableDescriptorForOperationExpression;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment;
|
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.js.translate.utils.JsAstUtils.createDataDescriptor;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isAnonymousObject;
|
|
||||||
|
|
||||||
public final class TranslationUtils {
|
public final class TranslationUtils {
|
||||||
|
|
||||||
@@ -84,8 +82,9 @@ public final class TranslationUtils {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression translateExclForBinaryEqualLikeExpr(@NotNull JsBinaryOperation baseBinaryExpression) {
|
public static JsExpression translateExclForBinaryEqualLikeExpr(@NotNull JsBinaryOperation baseBinaryExpression) {
|
||||||
return new JsBinaryOperation(notOperator(baseBinaryExpression.getOperator()), baseBinaryExpression.getArg1(),
|
JsBinaryOperator negatedOperator = notOperator(baseBinaryExpression.getOperator());
|
||||||
baseBinaryExpression.getArg2());
|
assert negatedOperator != null : "Can't negate operator: " + baseBinaryExpression.getOperator();
|
||||||
|
return new JsBinaryOperation(negatedOperator, baseBinaryExpression.getArg1(), baseBinaryExpression.getArg2());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEqualLikeOperator(@NotNull JsBinaryOperator operator) {
|
public static boolean isEqualLikeOperator(@NotNull JsBinaryOperator operator) {
|
||||||
@@ -153,8 +152,7 @@ public final class TranslationUtils {
|
|||||||
context.getNameForDescriptor(descriptor);
|
context.getNameForDescriptor(descriptor);
|
||||||
|
|
||||||
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
|
if (!JsDescriptorUtils.isSimpleFinalProperty(descriptor) && !(containingDescriptor instanceof PackageFragmentDescriptor)) {
|
||||||
JsName backingFieldMangledName = context.getNameForBackingField(descriptor);
|
backingFieldName = context.getNameForBackingField(descriptor);
|
||||||
backingFieldName = context.declarePropertyOrPropertyAccessorName(descriptor, backingFieldMangledName.getIdent());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsExpression receiver;
|
JsExpression receiver;
|
||||||
@@ -264,31 +262,6 @@ public final class TranslationUtils {
|
|||||||
return ensureNotNull;
|
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) {
|
public static boolean isSimpleNameExpressionNotDelegatedLocalVar(@Nullable KtExpression expression, @NotNull TranslationContext context) {
|
||||||
if (!(expression instanceof KtSimpleNameExpression)) {
|
if (!(expression instanceof KtSimpleNameExpression)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user