blob: 361f7e12c67890e62f9554ba8876531a8dcde251 [file] [log] [blame]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// This test exercises all the grammar constructs for which implicit tear-off of
// `call` methods should occur.
// NOTICE: This test checks the currently implemented behavior, even though the
// implemented behavior does not match the language specification. Until an
// official decision has been made about whether to change the implementation to
// match the specification, or vice versa, this regression test is intended to
// protect against inadvertent implementation changes.
import '../static_type_helper.dart';
class B {}
class C extends B {
void call() {}
void m() {}
void testThisExpression() {
context<void Function()>(this);
}
}
class D {
C operator +(other) => C();
C operator -() => C();
C instanceMethod() => C();
static C staticMethod() => C();
C get instanceGetter => C();
}
C topLevelMethod() => C();
// These are top level getters rather than local variables to avoid triggering
// flow analysis.
bool get bTrue => true;
bool get bFalse => false;
void testAsExpression() {
dynamic d = C();
context<void Function()>(d as C);
}
void testAssignmentExpression() {
B b = B(); // ignore: unused_local_variable
context<void Function()>(b = C());
}
Future<void> testAwaitExpression() async {
Future<C> fc = Future.value(C());
context<void Function()>(await fc);
}
void testBinaryExpression() {
D d = D();
context<void Function()>(d + d);
}
void testCascadeExpression() {
// Note: we don't apply implicit `.call` tear-offs to the *target* of a
// cascade, but we do apply them to the cascade expression as a whole, so
// `c..m()` is equivalent to `(c..m()).call`.
C c = C();
context<void Function()>(c..m());
}
void testConditionalExpression() {
// Note: we know from `implicit_tearoff_exceptions_test.dart` that the two
// branches of the conditional expression are *not* subject to implicit
// `.call` tearoff, so the `.call` tearoff in this case is applied to the
// whole conditional expression. In other words, `b ? c : c` desugars to
// `(b ? c : c).call` rather than `(b ? c.call : c.call)`.
C c = C();
context<void Function()>(bFalse ? c : c);
context<void Function()>(bTrue ? c : c);
}
void testFunctionExpressionInvocation() {
C c = C();
context<void Function()>((() => c)());
}
void testFunctionInvocationLocal() {
C localFunction() => C();
context<void Function()>(localFunction());
}
void testFunctionInvocationStatic() {
context<void Function()>(D.staticMethod());
}
void testFunctionInvocationTopLevel() {
context<void Function()>(topLevelMethod());
}
void testIfNullExpression() {
C? c1 = bTrue ? C() : null;
C c2 = C();
context<void Function()>(c1 ?? c2);
c1 = null;
context<void Function()>(c1 ?? c2);
}
void testIndexExpression() {
List<C> l = [C()];
context<void Function()>(l[0]);
}
void testInstanceCreationExpressionExplicit() {
context<void Function()>(new C());
}
void testInstanceCreationExpressionImplicit() {
context<void Function()>(C());
}
void testInstanceGetGeneral() {
D Function() dFunction = () => D();
context<void Function()>(dFunction().instanceGetter);
}
void testInstanceGetViaPrefixedIdentifier() {
D d = D();
context<void Function()>(d.instanceGetter);
}
void testMethodInvocation() {
context<void Function()>(D().instanceMethod());
}
void testNullCheckExpression() {
C? c = bTrue ? C() : null;
context<void Function()>(c!);
}
void testParenthesizedExpression() {
C c = C();
context<void Function()>((c));
}
void testUnaryMinusExpression() {
D d = D();
context<void Function()>(-d);
}
extension on C {
void testThisExpressionExtension() {
context<void Function()>(this);
}
}
main() async {
testAsExpression();
testAssignmentExpression();
await testAwaitExpression();
testBinaryExpression();
testCascadeExpression();
testConditionalExpression();
testFunctionExpressionInvocation();
testFunctionInvocationLocal();
testFunctionInvocationStatic();
testFunctionInvocationTopLevel();
testIfNullExpression();
testIndexExpression();
testInstanceCreationExpressionExplicit();
testInstanceCreationExpressionImplicit();
testInstanceGetGeneral();
testInstanceGetViaPrefixedIdentifier();
testMethodInvocation();
testNullCheckExpression();
testParenthesizedExpression();
testUnaryMinusExpression();
C().testThisExpression();
C().testThisExpressionExtension();
}