JS property accessors inlining (KT-13456)
This commit is contained in:
@@ -4505,6 +4505,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/property.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/inlineMultiModule/simple.kt");
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.semantics;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/codegen/boxInline/property")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class PropertyAccessorsInlineTestsGenerated extends AbstractPropertyAccessorsInlineTests {
|
||||
public void testAllFilesPresentInProperty() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/property"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/property.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedVal.kt")
|
||||
public void testReifiedVal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/reifiedVal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedVar.kt")
|
||||
public void testReifiedVar() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/reifiedVar.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleExtension.kt")
|
||||
public void testSimpleExtension() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/property/simpleExtension.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
+2
@@ -29,6 +29,8 @@ abstract class BorrowedInlineTest(relativePath: String) : BasicBoxTest(
|
||||
|
||||
abstract class AbstractNonLocalReturnsTest : BorrowedInlineTest("nonLocalReturns/")
|
||||
|
||||
abstract class AbstractPropertyAccessorsInlineTests : BorrowedInlineTest("property/")
|
||||
|
||||
abstract class AbstractBoxJsTest() : BasicBoxTest(
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "box/",
|
||||
BasicBoxTest.TEST_DATA_DIR_PATH + "out/box/"
|
||||
|
||||
@@ -53,6 +53,27 @@ public class DirectiveTestUtils {
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler PROPERTY_NOT_USED = new DirectiveHandler("PROPERTY_NOT_USED") {
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
checkPropertyNotUsed(ast, arguments.getFirst(), false, false);
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler PROPERTY_NOT_READ_FROM = new DirectiveHandler("PROPERTY_NOT_READ_FROM") {
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
checkPropertyNotUsed(ast, arguments.getFirst(), false, true);
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler PROPERTY_NOT_WRITTEN_TO = new DirectiveHandler("PROPERTY_NOT_WRITTEN_TO") {
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
checkPropertyNotUsed(ast, arguments.getFirst(), true, false);
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler FUNCTION_CALLED_IN_SCOPE = new DirectiveHandler("CHECK_CALLED_IN_SCOPE") {
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
@@ -232,6 +253,9 @@ public class DirectiveTestUtils {
|
||||
private static final List<DirectiveHandler> DIRECTIVE_HANDLERS = Arrays.asList(
|
||||
FUNCTION_CONTAINS_NO_CALLS,
|
||||
FUNCTION_NOT_CALLED,
|
||||
PROPERTY_NOT_USED,
|
||||
PROPERTY_NOT_READ_FROM,
|
||||
PROPERTY_NOT_WRITTEN_TO,
|
||||
FUNCTION_CALLED_IN_SCOPE,
|
||||
FUNCTION_NOT_CALLED_IN_SCOPE,
|
||||
FUNCTIONS_HAVE_SAME_LINES,
|
||||
@@ -261,6 +285,17 @@ public class DirectiveTestUtils {
|
||||
assertEquals(errorMessage, 0, callsCount);
|
||||
}
|
||||
|
||||
public static void checkPropertyNotUsed(JsNode node, String propertyName, boolean isGetAllowed, boolean isSetAllowed) throws Exception {
|
||||
PropertyReferenceCollector counter = PropertyReferenceCollector.Companion.collect(node);
|
||||
if (!isGetAllowed) {
|
||||
assertFalse("inline property getter for `" + propertyName + "` is called", counter.hasUnqualifiedReads(propertyName));
|
||||
}
|
||||
if (!isSetAllowed) {
|
||||
assertFalse("inline property setter for `" + propertyName + "` is called", counter.hasUnqualifiedWrites(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void checkFunctionNotCalled(JsNode node, String functionName) throws Exception {
|
||||
CallCounter counter = CallCounter.countCalls(node);
|
||||
int functionCalledCount = counter.getQualifiedCallsCount(functionName);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.utils
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class PropertyReferenceCollector : RecursiveJsVisitor() {
|
||||
|
||||
private val identReadSet = hashSetOf<String>()
|
||||
private val identWriteSet = hashSetOf<String>()
|
||||
|
||||
fun hasUnqualifiedReads(expectedIdent: String) = expectedIdent in identReadSet
|
||||
fun hasUnqualifiedWrites(expectedIdent: String) = expectedIdent in identWriteSet
|
||||
|
||||
override fun visitNameRef(nameRef: JsNameRef) {
|
||||
super.visitNameRef(nameRef)
|
||||
identReadSet.add(nameRef.ident)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(x: JsBinaryOperation) {
|
||||
var assignmentToProperty = false
|
||||
JsAstUtils.decomposeAssignment(x)?.let { (left, right) ->
|
||||
(left as? JsNameRef)?.let { nameRef ->
|
||||
assignmentToProperty = true
|
||||
identWriteSet.add(nameRef.ident)
|
||||
nameRef.qualifier?.accept(this)
|
||||
right.accept(this)
|
||||
}
|
||||
}
|
||||
if (!assignmentToProperty) {
|
||||
super.visitBinaryExpression(x)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun collect(node: JsNode): PropertyReferenceCollector {
|
||||
val visitor = PropertyReferenceCollector()
|
||||
node.accept(visitor)
|
||||
return visitor
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user