JS/RTTI: if it's known that T <: X & Y, where T is non-reified type variable, for each a is T check that a is X && a is Y

This commit is contained in:
Alexey Andreev
2016-04-29 11:31:11 +03:00
parent 6454613b51
commit 7ff658414f
10 changed files with 213 additions and 103 deletions
@@ -59,6 +59,12 @@ public class CastTestGenerated extends AbstractCastTest {
doTest(fileName);
}
@TestMetadata("castToGenericTypeWithMultipleUpperBounds.kt")
public void testCastToGenericTypeWithMultipleUpperBounds() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/castToGenericTypeWithMultipleUpperBounds.kt");
doTest(fileName);
}
@TestMetadata("castToGenericTypeWithUpperBound.kt")
public void testCastToGenericTypeWithUpperBound() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/expression/cast/cases/castToGenericTypeWithUpperBound.kt");
@@ -56,23 +56,25 @@ public class DirectiveTestUtils {
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 {
checkCalledInScope(ast, arguments.getNamedArgument("function"), arguments.getNamedArgument("scope"));
// Be more restrictive, check qualified match by default
checkCalledInScope(ast, arguments.getNamedArgument("function"), arguments.getNamedArgument("scope"),
parseBooleanArgument(arguments, "qualified", true));
}
};
private static final DirectiveHandler FUNCTION_NOT_CALLED_IN_SCOPE = new DirectiveHandler("CHECK_NOT_CALLED_IN_SCOPE") {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
checkNotCalledInScope(ast, arguments.getNamedArgument("function"), arguments.getNamedArgument("scope"));
// Be more restrictive, check unqualified match by default
checkNotCalledInScope(ast, arguments.getNamedArgument("function"), arguments.getNamedArgument("scope"),
parseBooleanArgument(arguments, "qualified", false));
}
};
private static final DirectiveHandler METHOD_NOT_CALLED_IN_SCOPE = new DirectiveHandler("CHECK_METHOD_NOT_CALLED_IN_SCOPE") {
@Override
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
checkMethodNotCalledInScope(ast, arguments.getNamedArgument("function"), arguments.getNamedArgument("scope"));
}
};
private static boolean parseBooleanArgument(@NotNull ArgumentsHelper arguments, @NotNull String name, boolean defaultValue) {
String value = arguments.findNamedArgument(name);
return value != null ? Boolean.parseBoolean(value) : defaultValue;
}
private static final DirectiveHandler FUNCTIONS_HAVE_SAME_LINES = new DirectiveHandler("CHECK_FUNCTIONS_HAVE_SAME_LINES") {
@Override
@@ -196,7 +198,6 @@ public class DirectiveTestUtils {
FUNCTION_NOT_CALLED,
FUNCTION_CALLED_IN_SCOPE,
FUNCTION_NOT_CALLED_IN_SCOPE,
METHOD_NOT_CALLED_IN_SCOPE,
FUNCTIONS_HAVE_SAME_LINES,
COUNT_LABELS,
COUNT_VARS,
@@ -234,50 +235,38 @@ public class DirectiveTestUtils {
public static void checkCalledInScope(
@NotNull JsNode node,
@NotNull String functionName,
@NotNull String scopeFunctionName
@NotNull String scopeFunctionName,
boolean checkQualifier
) throws Exception {
String errorMessage = functionName + " is not called inside " + scopeFunctionName;
assertFalse(errorMessage, isCalledInScope(node, functionName, scopeFunctionName));
assertFalse(errorMessage, isCalledInScope(node, functionName, scopeFunctionName, checkQualifier));
}
public static void checkNotCalledInScope(
@NotNull JsNode node,
@NotNull String functionName,
@NotNull String scopeFunctionName
@NotNull String scopeFunctionName,
boolean checkQualifier
) throws Exception {
String errorMessage = functionName + " is called inside " + scopeFunctionName;
assertTrue(errorMessage, isCalledInScope(node, functionName, scopeFunctionName));
}
private static void checkMethodNotCalledInScope(
@NotNull JsNode node,
@NotNull String functionName,
@NotNull String scopeFunctionName
) throws Exception {
String errorMessage = functionName + " is called inside " + scopeFunctionName;
assertTrue(errorMessage, isMethodCalledInScope(node, functionName, scopeFunctionName));
assertTrue(errorMessage, isCalledInScope(node, functionName, scopeFunctionName, checkQualifier));
}
private static boolean isCalledInScope(
@NotNull JsNode node,
@NotNull String functionName,
@NotNull String scopeFunctionName
@NotNull String scopeFunctionName,
boolean checkQualifier
) throws Exception {
JsNode scope = AstSearchUtil.getFunction(node, scopeFunctionName);
CallCounter counter = CallCounter.countCalls(scope);
return counter.getQualifiedCallsCount(functionName) == 0;
}
private static boolean isMethodCalledInScope(
@NotNull JsNode node,
@NotNull String functionName,
@NotNull String scopeFunctionName
) throws Exception {
JsNode scope = AstSearchUtil.getFunction(node, scopeFunctionName);
CallCounter counter = CallCounter.countCalls(scope);
return counter.getUnqualifiedCallsCount(functionName) == 0;
if (checkQualifier) {
return counter.getQualifiedCallsCount(functionName) == 0;
}
else {
return counter.getUnqualifiedCallsCount(functionName) == 0;
}
}
private abstract static class DirectiveHandler {