JS: fix absence of temporary variable in secondary constructors. See KT-16377
This commit is contained in:
committed by
Alexey Andreev
parent
3b222f13f3
commit
86d1c7b7ec
@@ -2149,6 +2149,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructorTemporaryVars.kt")
|
||||
public void testSecondaryConstructorTemporaryVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/evaluationOrder/secondaryConstructorTemporaryVars.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenAsMinusArgument.kt")
|
||||
public void testWhenAsMinusArgument() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/evaluationOrder/whenAsMinusArgument.kt");
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.test.utils;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
import org.jetbrains.kotlin.js.inline.util.CollectUtilsKt;
|
||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata;
|
||||
|
||||
import java.util.*;
|
||||
@@ -261,6 +263,28 @@ public class DirectiveTestUtils {
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler HAS_NO_CAPTURED_VARS = new DirectiveHandler("HAS_NO_CAPTURED_VARS") {
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
String functionName = arguments.getNamedArgument("function");
|
||||
|
||||
Set<String> except = new HashSet<String>();
|
||||
String exceptString = arguments.findNamedArgument("except");
|
||||
if (exceptString != null) {
|
||||
for (String exceptId : StringUtil.split(exceptString, ";")) {
|
||||
except.add(exceptId.trim());
|
||||
}
|
||||
}
|
||||
|
||||
JsFunction function = AstSearchUtil.getFunction(ast, functionName);
|
||||
Set<JsName> freeVars = CollectUtilsKt.collectFreeVariables(function);
|
||||
for (JsName freeVar : freeVars) {
|
||||
assertTrue("Function " + functionName + " captures free variable " + freeVar.getIdent(),
|
||||
except.contains(freeVar.getIdent()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static final List<DirectiveHandler> DIRECTIVE_HANDLERS = Arrays.asList(
|
||||
FUNCTION_CONTAINS_NO_CALLS,
|
||||
FUNCTION_NOT_CALLED,
|
||||
@@ -278,7 +302,8 @@ public class DirectiveTestUtils {
|
||||
COUNT_NULLS,
|
||||
NOT_REFERENCED,
|
||||
HAS_INLINE_METADATA,
|
||||
HAS_NO_INLINE_METADATA
|
||||
HAS_NO_INLINE_METADATA,
|
||||
HAS_NO_CAPTURED_VARS
|
||||
);
|
||||
|
||||
public static void processDirectives(@NotNull JsNode ast, @NotNull String sourceCode) throws Exception {
|
||||
|
||||
+2
-1
@@ -217,13 +217,14 @@ class ClassTranslator private constructor(
|
||||
val constructorInitializer = context.getFunctionObject(constructorDescriptor)
|
||||
constructorInitializer.name = context.getInnerNameForDescriptor(constructorDescriptor)
|
||||
context.addDeclarationStatement(constructorInitializer.makeStmt())
|
||||
|
||||
context = context.contextWithScope(constructorInitializer)
|
||||
context.translateAndAliasParameters(constructorDescriptor, constructorInitializer.parameters)
|
||||
.translateFunction(constructor, constructorInitializer)
|
||||
|
||||
// Translate super/this call
|
||||
val superCallGenerators = mutableListOf<(MutableList<JsStatement>) -> Unit>()
|
||||
val referenceToClass = context.getInnerReference(classDescriptor)
|
||||
context = context.contextWithScope(constructorInitializer)
|
||||
|
||||
superCallGenerators += { it += FunctionBodyTranslator.setDefaultValueForArguments(constructorDescriptor, context) }
|
||||
|
||||
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
// HAS_NO_CAPTURED_VARS: function=A_init except=Kotlin;A
|
||||
|
||||
class A() {
|
||||
var y: String? = null
|
||||
var z: Any? = null
|
||||
|
||||
constructor(x: Any) : this() {
|
||||
y = if (x == "foo") "!!!" else { z = x; ">>>" }
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A("foo")
|
||||
if (a.y != "!!!") return "fail1: ${a.y}"
|
||||
if (a.z != null) return "fail2: ${a.z}"
|
||||
|
||||
val b = A(23)
|
||||
if (b.y != ">>>") return "fail3: ${b.y}"
|
||||
if (b.z != 23) return "fail4: ${b.z}"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user