Skip to content

Commit cf89e24

Browse files
Alexey AndreevAlexey Andreev
authored andcommitted
JS: fix removal of unused lambdas after inlining
1 parent 40e00a6 commit cf89e24

File tree

5 files changed

+69
-8
lines changed

5 files changed

+69
-8
lines changed

js/js.inliner/src/org/jetbrains/kotlin/js/inline/clean/removeUnusedFunctionDefinitions.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,13 @@ fun removeUnusedFunctionDefinitions(root: JsNode, functions: Map<JsName, JsFunct
3737
removableFunctions
3838
}
3939

40-
NodeRemover(JsPropertyInitializer::class.java) {
41-
val function = it.valueExpr as? JsFunction
42-
function != null && function in removable
40+
NodeRemover(JsStatement::class.java) { statement ->
41+
val expression = when (statement) {
42+
is JsExpressionStatement -> statement.expression
43+
is JsVars -> if (statement.vars.size == 1) statement.vars[0].initExpression else null
44+
else -> null
45+
}
46+
expression is JsFunction && expression in removable
4347
}.accept(root)
4448
}
4549

js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4562,6 +4562,12 @@ public void testAllFilesPresentInInlineSizeReduction() throws Exception {
45624562
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/inlineSizeReduction"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.ANY, true);
45634563
}
45644564

4565+
@TestMetadata("inlineLambdaCleanup.kt")
4566+
public void testInlineLambdaCleanup() throws Exception {
4567+
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineSizeReduction/inlineLambdaCleanup.kt");
4568+
doTest(fileName);
4569+
}
4570+
45654571
@TestMetadata("inlineOrder.kt")
45664572
public void testInlineOrder() throws Exception {
45674573
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineSizeReduction/inlineOrder.kt");

js/js.tests/test/org/jetbrains/kotlin/js/test/utils/CallCounter.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,35 @@ public class CallCounter extends RecursiveJsVisitor {
2828
@NotNull
2929
private final Set<String> exceptFunctionNames;
3030

31+
@NotNull
32+
private final Set<String> exceptScopes;
33+
34+
private int excludedScopeOccurrenceCount;
35+
3136
@NotNull
3237
public static CallCounter countCalls(@NotNull JsNode node) {
3338
return countCalls(node, Collections.<String>emptySet());
3439
}
3540

3641
@NotNull
3742
public static CallCounter countCalls(@NotNull JsNode node, @NotNull Set<String> exceptFunctionNames) {
38-
CallCounter visitor = new CallCounter(new HashSet<String>(exceptFunctionNames));
43+
CallCounter visitor = new CallCounter(new HashSet<String>(exceptFunctionNames), Collections.<String>emptySet());
3944
node.accept(visitor);
4045

4146
return visitor;
4247
}
4348

44-
private CallCounter(@NotNull Set<String> exceptFunctionNames) {
49+
@NotNull
50+
public static CallCounter countCallsWithExcludedScopes(@NotNull JsNode node, @NotNull Set<String> exceptScopes) {
51+
CallCounter visitor = new CallCounter(Collections.<String>emptySet(), new HashSet<String>(exceptScopes));
52+
node.accept(visitor);
53+
54+
return visitor;
55+
}
56+
57+
private CallCounter(@NotNull Set<String> exceptFunctionNames, @NotNull Set<String> exceptScopes) {
4558
this.exceptFunctionNames = exceptFunctionNames;
59+
this.exceptScopes = exceptScopes;
4660
}
4761

4862
public int getTotalCallsCount() {
@@ -89,6 +103,28 @@ public void visitInvocation(@NotNull JsInvocation invocation) {
89103
}
90104
}
91105

106+
@Override
107+
public void visitFunction(@NotNull JsFunction x) {
108+
if (x.getName() != null && exceptScopes.contains(x.getName().getIdent())) {
109+
excludedScopeOccurrenceCount++;
110+
return;
111+
}
112+
super.visitFunction(x);
113+
}
114+
115+
@Override
116+
public void visitVars(@NotNull JsVars x) {
117+
for (JsVars.JsVar jsVar : x.getVars()) {
118+
if (jsVar.getInitExpression() == null) continue;
119+
if (!exceptScopes.contains(jsVar.getName().getIdent())) {
120+
accept(jsVar.getInitExpression());
121+
}
122+
else {
123+
excludedScopeOccurrenceCount++;
124+
}
125+
}
126+
}
127+
92128
private static boolean matchesQualifiers(JsNameRef nameRef, List<String> expectedQualifierChain) {
93129
JsExpression currentQualifier = nameRef;
94130

@@ -108,4 +144,8 @@ private static boolean matchesQualifiers(JsNameRef nameRef, List<String> expecte
108144

109145
return true;
110146
}
147+
148+
public int getExcludedScopeOccurrenceCount() {
149+
return excludedScopeOccurrenceCount;
150+
}
111151
}

js/js.tests/test/org/jetbrains/kotlin/js/test/utils/DirectiveTestUtils.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throw
4949
private static final DirectiveHandler FUNCTION_NOT_CALLED = new DirectiveHandler("CHECK_NOT_CALLED") {
5050
@Override
5151
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
52-
checkFunctionNotCalled(ast, arguments.getFirst());
52+
checkFunctionNotCalled(ast, arguments.getFirst(), arguments.findNamedArgument("except"));
5353
}
5454
};
5555

@@ -296,12 +296,16 @@ public static void checkPropertyNotUsed(JsNode node, String propertyName, boolea
296296
}
297297

298298

299-
public static void checkFunctionNotCalled(JsNode node, String functionName) throws Exception {
300-
CallCounter counter = CallCounter.countCalls(node);
299+
public static void checkFunctionNotCalled(@NotNull JsNode node, @NotNull String functionName, @Nullable String exceptFunction)
300+
throws Exception {
301+
Set<String> excludedScopes = exceptFunction != null ? Collections.singleton(exceptFunction) : Collections.<String>emptySet();
302+
303+
CallCounter counter = CallCounter.countCallsWithExcludedScopes(node, excludedScopes);
301304
int functionCalledCount = counter.getQualifiedCallsCount(functionName);
302305

303306
String errorMessage = "inline function `" + functionName + "` is called";
304307
assertEquals(errorMessage, 0, functionCalledCount);
308+
assertEquals("Not all excluded scopes found", excludedScopes.size(), counter.getExcludedScopeOccurrenceCount());
305309
}
306310

307311
public static void checkCalledInScope(
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// CHECK_NOT_CALLED: produceOK except=box
2+
3+
fun produceOK() = "OK"
4+
5+
private inline fun <T> block(f: () -> T) = f()
6+
7+
fun box(): String = block { produceOK() }

0 commit comments

Comments
 (0)