blob: c407766d961ff4e5ac0c9d5e9b5a37107fa1c0d7 [file] [log] [blame]
// Copyright (c) 2015, 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.
part of dart2js.semantics_visitor_test;
const Map<String, List<Test>> SEND_TESTS = const {
'Parameters': const [
// Parameters
const Test('m(o) => o;',
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#o)')),
const Test('m(o) { o = 42; }',
const Visit(VisitKind.VISIT_PARAMETER_SET,
element: 'parameter(m#o)',
rhs:'42')),
const Test('m(o) { o(null, 42); }',
const Visit(VisitKind.VISIT_PARAMETER_INVOKE,
element: 'parameter(m#o)',
arguments: '(null,42)',
selector: 'CallStructure(arity=2)')),
const Test('m(final o) { o = 42; }',
const Visit(VisitKind.VISIT_FINAL_PARAMETER_SET,
element: 'parameter(m#o)',
rhs:'42')),
],
'Local variables': const [
// Local variables
const Test('m() { var o; return o; }',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_GET,
element: 'variable(m#o)')),
const Test('m() { var o; o = 42; }',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_SET,
element: 'variable(m#o)',
rhs:'42')),
const Test('m() { var o; o(null, 42); }',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_INVOKE,
element: 'variable(m#o)',
arguments: '(null,42)',
selector: 'CallStructure(arity=2)')),
const Test('m() { final o = 0; o = 42; }',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET,
element: 'variable(m#o)',
rhs:'42')),
const Test('m() { const o = 0; o = 42; }',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET,
element: 'variable(m#o)',
rhs:'42')),
],
'Local functions': const [
// Local functions
const Test('m() { o(a, b) {}; return o; }',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_GET,
element: 'function(m#o)')),
const Test('m() { o(a, b) {}; o(null, 42); }',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_INVOKE,
element: 'function(m#o)',
arguments: '(null,42)',
selector: 'CallStructure(arity=2)')),
const Test('m() { o(a) {}; o(null, 42); }',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_INCOMPATIBLE_INVOKE,
element: 'function(m#o)',
arguments: '(null,42)',
selector: 'CallStructure(arity=2)')),
const Test('m() { o(a, b) {}; o = 42; }',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_SET,
element: 'function(m#o)',
rhs: '42')),
],
'Static fields': const [
// Static fields
const Test(
'''
class C { static var o; }
m() => C.o;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#o)')),
const Test.clazz(
'''
class C {
static var o;
m() => o;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#o)')),
const Test.clazz(
'''
class C {
static var o;
m() => C.o;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#o)')),
const Test.prefix(
'''
class C {
static var o;
}
''',
'm() => p.C.o;',
const Visit(VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#o)')),
const Test.clazz(
'''
class C {
var o;
static m() => o;
}
''',
const Visit(VisitKind.ERROR_INVALID_GET,
error: MessageKind.NO_INSTANCE_AVAILABLE)),
const Test.prefix(
'''
class C {
static var o;
}
''',
'm() => p.C.o;',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#o)'),
],
isDeferred: true),
const Test(
'''
class C {
var o;
}
m() => C.o;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Test(
'''
class C {
var o;
}
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SET,
name: 'o',
rhs: '42')),
const Test(
'''
class C {
C.o();
}
m() => C.o;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Test.prefix(
'''
''',
'm() => p.C.o;',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,
receiver: 'p.C', name: 'o'),
const Visit(VisitKind.VISIT_UNRESOLVED_GET, name: 'C'),
]),
const Test.prefix(
'''
class C {
}
''',
'm() => p.C.o;',
const Visit(VisitKind.VISIT_UNRESOLVED_GET, name: 'o')),
const Test.prefix(
'''
''',
'm() => p.C.o;',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,
receiver: 'p.C', name: 'o'),
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'C'),
],
isDeferred: true),
const Test.prefix(
'''
class C {
}
''',
'm() => p.C.o;',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o'),
],
isDeferred: true),
const Test(
'''
class C {}
m() => C.this;
''',
null),
const Test(
'''
class C {
static var o;
}
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static var o;
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static var o;
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C {
static var o;
}
''',
'm() { p.C.o = 42; }',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
var o;
static m() { o = 42; }
}
''',
const Visit(VisitKind.ERROR_INVALID_SET,
error: MessageKind.NO_INSTANCE_AVAILABLE,
rhs: '42')),
const Test(
'''
class C {
static var o;
}
m() { C.o(null, 42); }
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,
element: 'field(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static var o;
m() { o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,
element: 'field(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static var o;
m() { C.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,
element: 'field(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
var o;
static m() { o(null, 42); }
}
''',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.NO_INSTANCE_AVAILABLE,
arguments: '(null,42)')),
const Test.prefix(
'''
class C {
static var o;
}
''',
'm() { p.C.o(null, 42); }',
const Visit(VisitKind.VISIT_STATIC_FIELD_INVOKE,
element: 'field(C#o)',
arguments: '(null,42)')),
const Test(
'''
class C {}
m() => C.this(null, 42);
''',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.THIS_PROPERTY,
arguments: '(null,42)')),
const Test(
'''
class C { static final o = 0; }
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static final o = 0;
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static final o = 0;
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C {
static final o = 0;
}
''',
'm() { p.C.o = 42; }',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test(
'''
class C { static const o = 0; }
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static const o = 0;
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static const o = 0;
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C {
static const o = 0;
}
''',
'm() { p.C.o = 42; }',
const Visit(VisitKind.VISIT_FINAL_STATIC_FIELD_SET,
element: 'field(C#o)',
rhs: '42')),
],
'Static properties': const [
// Static properties
const Test(
'''
class C {
static get o => null;
}
m() => C.o;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_GET,
element: 'getter(C#o)')),
const Test.clazz(
'''
class C {
static get o => null;
m() => o;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_GET,
element: 'getter(C#o)')),
const Test.clazz(
'''
class C {
static get o => null;
m() => C.o;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_GET,
element: 'getter(C#o)')),
const Test.prefix(
'''
class C {
static get o => null;
}
''',
'm() => p.C.o;',
const Visit(VisitKind.VISIT_STATIC_GETTER_GET,
element: 'getter(C#o)')),
const Test(
'''
class C { static get o => 42; }
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SET,
element: 'getter(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static get o => 42;
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SET,
element: 'getter(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static get o => 42;
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SET,
element: 'getter(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C {
static get o => 42;
}
''',
'm() { p.C.o = 42; }',
const Visit(VisitKind.VISIT_STATIC_GETTER_SET,
element: 'getter(C#o)',
rhs: '42')),
const Test(
'''
class C {
static set o(_) {}
}
m() => C.o;
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_GET,
element: 'setter(C#o)')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() => o;
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_GET,
element: 'setter(C#o)')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() => C.o;
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_GET,
element: 'setter(C#o)')),
const Test.prefix(
'''
class C {
static set o(_) {}
}
''',
'm() => p.C.o;',
const Visit(VisitKind.VISIT_STATIC_SETTER_GET,
element: 'setter(C#o)')),
const Test(
'''
class C { static set o(_) {} }
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_SET,
element: 'setter(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_SET,
element: 'setter(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_SET,
element: 'setter(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C {
static set o(_) {}
}
''',
'm() { p.C.o = 42; }',
const Visit(VisitKind.VISIT_STATIC_SETTER_SET,
element: 'setter(C#o)',
rhs: '42')),
const Test(
'''
class C { static get o => null; }
m() => C.o(null, 42);
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,
element: 'getter(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static get o => null;
m() { o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,
element: 'getter(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static get o => null;
m() { C.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,
element: 'getter(C#o)',
arguments: '(null,42)')),
const Test.prefix(
'''
class C {
static get o => null;
}
''',
'm() { p.C.o(null, 42); }',
const Visit(VisitKind.VISIT_STATIC_GETTER_INVOKE,
element: 'getter(C#o)',
arguments: '(null,42)')),
const Test(
'''
class C { static set o(_) {} }
m() => C.o(null, 42);
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,
element: 'setter(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() { o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,
element: 'setter(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static set o(_) {}
m() { C.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,
element: 'setter(C#o)',
arguments: '(null,42)')),
const Test.prefix(
'''
class C {
static set o(_) {}
}
''',
'm() { p.C.o(null, 42); }',
const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,
element: 'setter(C#o)',
arguments: '(null,42)')),
],
'Static functions': const [
// Static functions
const Test(
'''
class C { static o(a, b) {} }
m() => C.o;
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_GET,
element: 'function(C#o)')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() => o;
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_GET,
element: 'function(C#o)')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() => C.o;
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_GET,
element: 'function(C#o)')),
const Test.prefix(
'''
class C { static o(a, b) {} }
''',
'''
m() => p.C.o;
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_GET,
element: 'function(C#o)')),
const Test(
'''
class C { static o(a, b) {} }
m() { C.o = 42; }
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_SET,
element: 'function(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() { o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_SET,
element: 'function(C#o)',
rhs: '42')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() { C.o = 42; }
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_SET,
element: 'function(C#o)',
rhs: '42')),
const Test.prefix(
'''
class C { static o(a, b) {} }
''',
'''
m() { p.C.o = 42; }
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_SET,
element: 'function(C#o)',
rhs: '42')),
const Test(
'''
class C { static o(a, b) {} }
m() => C.o(null, 42);
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_INVOKE,
element: 'function(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() { o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_INVOKE,
element: 'function(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
static o(a, b) {}
m() { C.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_INVOKE,
element: 'function(C#o)',
arguments: '(null,42)')),
const Test.prefix(
'''
class C {
static o(a, b) {}
}
''',
'm() { p.C.o(null, 42); }',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_INVOKE,
element: 'function(C#o)',
arguments: '(null,42)')),
const Test(
'''
class C { static o(a, b) {} }
m() => C.o(null);
''',
const Visit(VisitKind.VISIT_STATIC_FUNCTION_INCOMPATIBLE_INVOKE,
element: 'function(C#o)',
arguments: '(null)')),
],
'Top level fields': const [
// Top level fields
const Test(
'''
var o;
m() => o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_GET,
element: 'field(o)')),
const Test.prefix(
'''
var o;
''',
'm() => p.o;',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_GET,
element: 'field(o)')),
const Test.prefix(
'''
var o;
''',
'm() => p.o;',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_GET,
element: 'field(o)'),
],
isDeferred: true),
const Test.prefix(
'''
''',
'm() => p.o;',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Test.prefix(
'''
''',
'm() => p.o;',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o'),
],
isDeferred: true),
const Test.prefix(
'''
''',
'm() => p;',
const Visit(VisitKind.ERROR_INVALID_GET,
error: MessageKind.PREFIX_AS_EXPRESSION)),
const Test(
'''
var o;
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test.prefix(
'''
var o;
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test(
'''
final o = 0;
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test.prefix(
'''
final o = 0;
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test(
'''
const o = 0;
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test.prefix(
'''
const o = 0;
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET,
element: 'field(o)',
rhs: '42')),
const Test(
'''
var o;
m() { o(null, 42); }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_INVOKE,
element: 'field(o)',
arguments: '(null,42)')),
const Test.prefix(
'''
var o;
''',
'm() { p.o(null, 42); }',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_INVOKE,
element: 'field(o)',
arguments: '(null,42)')),
const Test(
'''
m() => o;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Test(
'''
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SET,
name: 'o',
rhs: '42')),
],
'Top level properties': const [
// Top level properties
const Test(
'''
get o => null;
m() => o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_GET,
element: 'getter(o)')),
const Test.prefix(
'''
get o => null;
''',
'''
m() => p.o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_GET,
element: 'getter(o)')),
const Test(
'''
set o(_) {}
m() => o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
element: 'setter(o)')),
const Test.prefix(
'''
set o(_) {}
''',
'''
m() => p.o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
element: 'setter(o)')),
const Test(
'''
get o => null;
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SET,
element: 'getter(o)',
rhs: '42')),
const Test.prefix(
'''
get o => null;
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SET,
element: 'getter(o)',
rhs: '42')),
const Test(
'''
set o(_) {}
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_SET,
element: 'setter(o)',
rhs: '42')),
const Test.prefix(
'''
set o(_) {}
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_SET,
element: 'setter(o)',
rhs: '42')),
const Test(
'''
get o => null;
m() => o(null, 42);
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_INVOKE,
element: 'getter(o)',
arguments: '(null,42)')),
const Test.prefix(
'''
get o => null;
''',
'm() { p.o(null, 42); }',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_INVOKE,
element: 'getter(o)',
arguments: '(null,42)')),
const Test(
'''
set o(_) {}
m() => o(null, 42);
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
element: 'setter(o)',
arguments: '(null,42)')),
const Test.prefix(
'''
set o(_) {}
''',
'm() { p.o(null, 42); }',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
element: 'setter(o)',
arguments: '(null,42)')),
],
'Top level functions': const [
// Top level functions
const Test(
'''
o(a, b) {}
m() => o;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_GET,
element: 'function(o)')),
const Test(
'''
o(a, b) {}
m() => o(null, 42);
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,
element: 'function(o)',
arguments: '(null,42)')),
const Test(
'''
o(a, b) {}
m() => o(null);
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INCOMPATIBLE_INVOKE,
element: 'function(o)',
arguments: '(null)')),
const Test.prefix(
'''
o(a, b) {}
''',
'm() { p.o(null, 42); }',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,
element: 'function(o)',
arguments: '(null,42)')),
const Test(
'''
m() => o(null, 42);
''',
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
name: 'o',
arguments: '(null,42)')),
const Test.prefix(
'''
o(a, b) {}
''',
'm() => p.o(null, 42);',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,
element: 'function(o)',
arguments: '(null,42)'),
],
isDeferred: true),
const Test.prefix(
'''
''',
'm() => p.o(null, 42);',
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
name: 'o',
arguments: '(null,42)')),
const Test.prefix(
'''
''',
'm() => p.o(null, 42);',
const [
const Visit(VisitKind.PREVISIT_DEFERRED_ACCESS,
element: 'prefix(p)'),
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
name: 'o',
arguments: '(null,42)'),
],
isDeferred: true),
const Test.prefix(
'''
''',
'm() => p(null, 42);',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.PREFIX_AS_EXPRESSION,
arguments: '(null,42)')),
const Test(
'''
o(a, b) {}
m() { o = 42; }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_SET,
element: 'function(o)',
rhs: '42')),
const Test.prefix(
'''
o(a, b) {}
''',
'm() { p.o = 42; }',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_SET,
element: 'function(o)',
rhs: '42')),
],
'Dynamic properties': const [
// Dynamic properties
const Test('m(o) => o.foo;',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,
receiver: 'o',
name: 'foo'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#o)'),
]),
const Test('m(o) { o.foo = 42; }',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_SET,
receiver: 'o',
name: 'foo',
rhs: '42'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#o)'),
]),
const Test('m(o) { o.foo(null, 42); }',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_INVOKE,
receiver: 'o',
name: 'foo',
arguments: '(null,42)'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#o)'),
]),
],
'This access': const [
// This access
const Test.clazz(
'''
class C {
m() => this;
}
''',
const Visit(VisitKind.VISIT_THIS_GET)),
const Test.clazz(
'''
class C {
call(a, b) {}
m() { this(null, 42); }
}
''',
const Visit(VisitKind.VISIT_THIS_INVOKE,
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
call(a, b) {}
static m() { this(null, 42); }
}
''',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.NO_THIS_AVAILABLE,
arguments: '(null,42)')),
],
'This properties': const [
// This properties
const Test.clazz(
'''
class C {
var foo;
m() => foo;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_GET,
name: 'foo')),
const Test.clazz(
'''
class C {
var foo;
m() => this.foo;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_GET,
name: 'foo')),
const Test.clazz(
'''
class C {
get foo => null;
m() => foo;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_GET,
name: 'foo')),
const Test.clazz(
'''
class C {
var foo;
static m() => this.foo;
}
''',
const Visit(VisitKind.ERROR_INVALID_GET,
error: MessageKind.NO_THIS_AVAILABLE)),
const Test.clazz(
'''
class C {
get foo => null;
m() => this.foo;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_GET,
name: 'foo')),
const Test.clazz(
'''
class C {
var foo;
m() { foo = 42; }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET,
name: 'foo',
rhs: '42')),
const Test.clazz(
'''
class C {
var foo;
m() { this.foo = 42; }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET,
name: 'foo',
rhs: '42')),
const Test.clazz(
'''
class C {
set foo(_) {}
m() { foo = 42; }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET,
name: 'foo',
rhs: '42')),
const Test.clazz(
'''
class C {
set foo(_) {}
m() { this.foo = 42; }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET,
name: 'foo',
rhs: '42')),
const Test.clazz(
'''
class C {
var foo;
m() { foo(null, 42); }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_INVOKE,
name: 'foo',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
var foo;
m() { this.foo(null, 42); }
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_INVOKE,
name: 'foo',
arguments: '(null,42)')),
const Test.clazz(
'''
class C {
var foo;
static m() { this.foo(null, 42); }
}
''',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.NO_THIS_AVAILABLE,
arguments: '(null,42)')),
],
'Super fields': const [
// Super fields
const Test.clazz(
'''
class B {
var o;
}
class C extends B {
m() => super.o;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_GET,
element: 'field(B#o)')),
const Test.clazz(
'''
class B {
var o;
}
class C extends B {
m() { super.o = 42; }
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SET,
element: 'field(B#o)',
rhs: '42')),
const Test.clazz(
'''
class B {
final o = 0;
}
class C extends B {
m() { super.o = 42; }
}
''',
const Visit(VisitKind.VISIT_FINAL_SUPER_FIELD_SET,
element: 'field(B#o)',
rhs: '42')),
const Test.clazz(
'''
class B {
var o;
}
class C extends B {
m() { super.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_INVOKE,
element: 'field(B#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super.o;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GET)),
],
'Super properties': const [
// Super properties
const Test.clazz(
'''
class B {
get o => null;
}
class C extends B {
m() => super.o;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_GET,
element: 'getter(B#o)')),
const Test.clazz(
'''
class B {
set o(_) {}
}
class C extends B {
m() => super.o;
}
''',
const Visit(VisitKind.VISIT_SUPER_SETTER_GET,
element: 'setter(B#o)')),
const Test.clazz(
'''
class B {
get o => 0;
}
class C extends B {
m() { super.o = 42; }
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SET,
element: 'getter(B#o)',
rhs: '42')),
const Test.clazz(
'''
class B {
set o(_) {}
}
class C extends B {
m() { super.o = 42; }
}
''',
const Visit(VisitKind.VISIT_SUPER_SETTER_SET,
element: 'setter(B#o)',
rhs: '42')),
const Test.clazz(
'''
class B {
get o => null;
}
class C extends B {
m() { super.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_INVOKE,
element: 'getter(B#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class B {
set o(_) {}
}
class C extends B {
m() { super.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_SUPER_SETTER_INVOKE,
element: 'setter(B#o)',
arguments: '(null,42)')),
],
'Super methods': const [
// Super methods
const Test.clazz(
'''
class B {
o(a, b) {}
}
class C extends B {
m() => super.o;
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_GET,
element: 'function(B#o)')),
const Test.clazz(
'''
class B {
o(a, b) {}
}
class C extends B {
m() { super.o = 42; }
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_SET,
element: 'function(B#o)',
rhs: '42')),
const Test.clazz(
'''
class B {
o(a, b) {}
}
class C extends B {
m() { super.o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_INVOKE,
element: 'function(B#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
class B {
o(a, b) {}
}
class C extends B {
m() { super.o(null); }
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_INCOMPATIBLE_INVOKE,
element: 'function(B#o)',
arguments: '(null)')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super.o(null, 42);
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INVOKE,
arguments: '(null,42)')),
],
'Expression invoke': const [
// Expression invoke
const Test('m() => (a, b){}(null, 42);',
const Visit(VisitKind.VISIT_EXPRESSION_INVOKE,
receiver: '(a,b){}',
arguments: '(null,42)')),
],
'Class type literals': const [
// Class type literals
const Test(
'''
class C {}
m() => C;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,
constant: 'C')),
const Test(
'''
class C {}
m() => C(null, 42);
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_INVOKE,
constant: 'C',
arguments: '(null,42)')),
const Test(
'''
class C {}
m() => C = 42;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_SET,
constant: 'C',
rhs: '42')),
const Test(
'''
class C {}
m() => C += 42;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_COMPOUND,
constant: 'C',
operator: '+=',
rhs: '42')),
const Test(
'''
class C {}
m() => C ??= 42;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_SET_IF_NULL,
constant: 'C',
rhs: '42')),
const Test(
'''
class C {}
m() => ++C;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_PREFIX,
constant: 'C',
operator: '++')),
const Test(
'''
class C {}
m() => C--;
''',
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_POSTFIX,
constant: 'C',
operator: '--')),
const Test(
'''
class C {}
m() => (C).hashCode;
''',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_GET,
receiver: '(C)', name: 'hashCode'),
const Visit(VisitKind.VISIT_CLASS_TYPE_LITERAL_GET,
constant: 'C'),
]),
],
'Typedef type literals': const [
// Typedef type literals
const Test(
'''
typedef F();
m() => F;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_GET,
constant: 'F')),
const Test(
'''
typedef F();
m() => F(null, 42);
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_INVOKE,
constant: 'F',
arguments: '(null,42)')),
const Test(
'''
typedef F();
m() => F = 42;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET,
constant: 'F',
rhs: '42')),
const Test(
'''
typedef F();
m() => F += 42;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_COMPOUND,
constant: 'F',
operator: '+=',
rhs: '42')),
const Test(
'''
typedef F();
m() => F ??= 42;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET_IF_NULL,
constant: 'F',
rhs: '42')),
const Test(
'''
typedef F();
m() => ++F;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_PREFIX,
constant: 'F',
operator: '++')),
const Test(
'''
typedef F();
m() => F--;
''',
const Visit(VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_POSTFIX,
constant: 'F',
operator: '--')),
],
'Type variable type literals': const [
// Type variable type literals
const Test.clazz(
'''
class C<T> {
m() => T;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_GET,
element: 'type_variable(C#T)')),
const Test.clazz(
'''
class C<T> {
m() => T(null, 42);
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_INVOKE,
element: 'type_variable(C#T)',
arguments: '(null,42)')),
const Test.clazz(
'''
class C<T> {
m() => T = 42;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET,
element: 'type_variable(C#T)',
rhs: '42')),
const Test.clazz(
'''
class C<T> {
m() => T += 42;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_COMPOUND,
element: 'type_variable(C#T)',
operator: '+=',
rhs: '42')),
const Test.clazz(
'''
class C<T> {
m() => T ??= 42;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET_IF_NULL,
element: 'type_variable(C#T)',
rhs: '42')),
const Test.clazz(
'''
class C<T> {
m() => ++T;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_PREFIX,
element: 'type_variable(C#T)',
operator: '++')),
const Test.clazz(
'''
class C<T> {
m() => T--;
}
''',
const Visit(VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_POSTFIX,
element: 'type_variable(C#T)',
operator: '--')),
const Test.clazz(
'''
class C<T> {
static m() => T;
}
''',
const Visit(VisitKind.ERROR_INVALID_GET,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER)),
const Test.clazz(
'''
class C<T> {
static m() => T(null, 42);
}
''',
const Visit(VisitKind.ERROR_INVALID_INVOKE,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
arguments: '(null,42)')),
const Test.clazz(
'''
class C<T> {
static m() => T ??= 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_SET_IF_NULL,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
rhs: '42')),
const Test.clazz(
'''
class C<T> {
static m() => T ??= 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_SET_IF_NULL,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
rhs: '42')),
const Test.clazz(
'''
class C<T> {
static m() => ++T;
}
''',
const Visit(VisitKind.ERROR_INVALID_PREFIX,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
operator: '++')),
const Test.clazz(
'''
class C<T> {
static m() => T--;
}
''',
const Visit(VisitKind.ERROR_INVALID_POSTFIX,
error: MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
operator: '--')),
],
'Dynamic type literals': const [
// Dynamic type literals
const Test(
'''
m() => dynamic;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_GET,
constant: 'dynamic')),
// TODO(johnniwinther): Update these to expect the constant to be `dynamic`
// instead of `Type`. Currently the compile time constant evaluator cannot
// detect `dynamic` as a constant subexpression.
const Test(
'''
m() { dynamic(null, 42); }
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_INVOKE,
constant: 'Type',
arguments: '(null,42)')),
const Test(
'''
m() => dynamic = 42;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET,
constant: 'dynamic',
rhs: '42')),
const Test(
'''
m() => dynamic += 42;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_COMPOUND,
constant: 'dynamic',
operator: '+=',
rhs: '42')),
const Test(
'''
m() => dynamic ??= 42;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET_IF_NULL,
constant: 'dynamic',
rhs: '42')),
const Test(
'''
m() => ++dynamic;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_PREFIX,
constant: 'dynamic',
operator: '++')),
const Test(
'''
m() => dynamic--;
''',
const Visit(VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_POSTFIX,
constant: 'dynamic',
operator: '--')),
],
'Assert': const [
// Assert
const Test(
'''
m() { assert(m()); }
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FUNCTION_INVOKE,
element: 'function(m)',
arguments: '()')),
],
'Logical and': const [
// Logical and
const Test(
'''
m() => true && false;
''',
const Visit(VisitKind.VISIT_LOGICAL_AND, left: 'true', right: 'false')),
],
'Logical or': const [
// Logical or
const Test(
'''
m() => true || false;
''',
const Visit(VisitKind.VISIT_LOGICAL_OR, left: 'true', right: 'false')),
],
'Is test': const [
// Is test
const Test(
'''
class C {}
m() => 0 is C;
''',
const Visit(VisitKind.VISIT_IS, expression: '0', type: 'C')),
],
'Is not test': const [
// Is not test
const Test(
'''
class C {}
m() => 0 is! C;
''',
const Visit(VisitKind.VISIT_IS_NOT, expression: '0', type: 'C')),
],
'As test': const [
// As test
const Test(
'''
class C {}
m() => 0 as C;
''',
const Visit(VisitKind.VISIT_AS, expression: '0', type: 'C')),
],
'Binary operators': const [
// Binary operators
const Test(
'''
m() => 2 + 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '+', right: '3')),
const Test(
'''
m() => 2 - 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '-', right: '3')),
const Test(
'''
m() => 2 * 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '*', right: '3')),
const Test(
'''
m() => 2 / 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '/', right: '3')),
const Test(
'''
m() => 2 ~/ 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '~/', right: '3')),
const Test(
'''
m() => 2 % 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '%', right: '3')),
const Test(
'''
m() => 2 << 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '<<', right: '3')),
const Test(
'''
m() => 2 >> 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '>>', right: '3')),
const Test(
'''
m() => 2 <= 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '<=', right: '3')),
const Test(
'''
m() => 2 < 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '<', right: '3')),
const Test(
'''
m() => 2 >= 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '>=', right: '3')),
const Test(
'''
m() => 2 > 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '>', right: '3')),
const Test(
'''
m() => 2 & 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '&', right: '3')),
const Test(
'''
m() => 2 | 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '|', right: '3')),
const Test(
'''
m() => 2 ^ 3;
''',
const Visit(VisitKind.VISIT_BINARY,
left: '2', operator: '^', right: '3')),
const Test.clazz(
'''
class B {
operator +(_) => null;
}
class C extends B {
m() => super + 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_BINARY,
element: 'function(B#+)',
operator: '+',
right: '42')),
const Test.clazz(
'''
class B {}
class C extends B {
m() => super + 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_BINARY,
operator: '+',
right: '42')),
const Test(
'''
m() => 2 === 3;
''',
const Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,
left: '2', operator: '===', right: '3')),
const Test(
'''
m() => 2 !== 3;
''',
const Visit(VisitKind.ERROR_UNDEFINED_BINARY_EXPRESSION,
left: '2', operator: '!==', right: '3')),
const Test.clazz(
'''
class B {
operator +(_) => null;
}
class C extends B {
static m() => super + 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_BINARY,
error: MessageKind.NO_SUPER_IN_STATIC,
operator: '+',
right: '42')),
],
'Index': const [
// Index
const Test(
'''
m() => 2[3];
''',
const Visit(VisitKind.VISIT_INDEX,
receiver: '2', index: '3')),
const Test(
'''
m() => --2[3];
''',
const Visit(VisitKind.VISIT_INDEX_PREFIX,
receiver: '2', index: '3', operator: '--')),
const Test(
'''
m() => 2[3]++;
''',
const Visit(VisitKind.VISIT_INDEX_POSTFIX,
receiver: '2', index: '3', operator: '++')),
const Test.clazz(
'''
class B {
operator [](_) => null;
}
class C extends B {
m() => super[42];
}
''',
const Visit(VisitKind.VISIT_SUPER_INDEX,
element: 'function(B#[])',
index: '42')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super[42];
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INDEX,
index: '42')),
const Test.clazz(
'''
class B {
operator [](_) => null;
}
class C extends B {
static m() => super[42];
}
''',
const Visit(VisitKind.ERROR_INVALID_INDEX,
error: MessageKind.NO_SUPER_IN_STATIC,
index: '42')),
const Test.clazz(
'''
class B {
operator [](_) => null;
operator []=(a, b) {}
}
class C extends B {
m() => ++super[42];
}
''',
const Visit(VisitKind.VISIT_SUPER_INDEX_PREFIX,
getter: 'function(B#[])',
setter: 'function(B#[]=)',
index: '42',
operator: '++')),
const Test.clazz(
'''
class B {
operator []=(a, b) {}
}
class C extends B {
m() => ++super[42];
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_INDEX_PREFIX,
setter: 'function(B#[]=)',
index: '42',
operator: '++')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => ++super[42];
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INDEX_PREFIX,
index: '42',
operator: '++')),
const Test.clazz(
'''
class B {
operator [](_) => null;
}
class C extends B {
m() => ++super[42];
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_INDEX_PREFIX,
getter: 'function(B#[])',
index: '42',
operator: '++')),
const Test.clazz(
'''
class B {
operator [](_) => null;
operator []=(a, b) {}
}
class C extends B {
static m() => ++super[42];
}
''',
const Visit(VisitKind.ERROR_INVALID_INDEX_PREFIX,
error: MessageKind.NO_SUPER_IN_STATIC,
index: '42',
operator: '++')),
const Test.clazz(
'''
class B {
operator [](_) => null;
operator []=(a, b) {}
}
class C extends B {
m() => super[42]--;
}
''',
const Visit(VisitKind.VISIT_SUPER_INDEX_POSTFIX,
getter: 'function(B#[])',
setter: 'function(B#[]=)',
index: '42',
operator: '--')),
const Test.clazz(
'''
class B {
operator []=(a, b) {}
}
class C extends B {
m() => super[42]--;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_INDEX_POSTFIX,
setter: 'function(B#[]=)',
index: '42',
operator: '--')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super[42]--;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INDEX_POSTFIX,
index: '42',
operator: '--')),
const Test.clazz(
'''
class B {
operator [](_) => null;
}
class C extends B {
m() => super[42]--;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_INDEX_POSTFIX,
getter: 'function(B#[])',
index: '42',
operator: '--')),
const Test.clazz(
'''
class B {
operator [](_) => null;
operator []=(a, b) {}
}
class C extends B {
static m() => super[42]--;
}
''',
const Visit(VisitKind.ERROR_INVALID_INDEX_POSTFIX,
error: MessageKind.NO_SUPER_IN_STATIC,
index: '42',
operator: '--')),
],
'Equals': const [
// Equals
const Test(
'''
m() => 2 == 3;
''',
const Visit(VisitKind.VISIT_EQUALS,
left: '2', right: '3')),
const Test.clazz(
'''
class B {
operator ==(_) => null;
}
class C extends B {
m() => super == 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_EQUALS,
element: 'function(B#==)',
right: '42')),
const Test.clazz(
'''
class B {
operator ==(_) => null;
}
class C extends B {
static m() => super == 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_EQUALS,
error: MessageKind.NO_SUPER_IN_STATIC,
right: '42')),
],
'Not equals': const [
// Not equals
const Test(
'''
m() => 2 != 3;
''',
const Visit(VisitKind.VISIT_NOT_EQUALS,
left: '2', right: '3')),
const Test.clazz(
'''
class B {
operator ==(_) => null;
}
class C extends B {
m() => super != 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_NOT_EQUALS,
element: 'function(B#==)',
right: '42')),
const Test.clazz(
'''
class B {
operator ==(_) => null;
}
class C extends B {
static m() => super != 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_NOT_EQUALS,
error: MessageKind.NO_SUPER_IN_STATIC,
right: '42')),
],
'Unary expression': const [
// Unary expression
const Test(
'''
m() => -false;
''',
const Visit(VisitKind.VISIT_UNARY,
expression: 'false', operator: '-')),
const Test(
'''
m() => ~false;
''',
const Visit(VisitKind.VISIT_UNARY,
expression: 'false', operator: '~')),
const Test.clazz(
'''
class B {
operator -() => null;
}
class C extends B {
m() => -super;
}
''',
const Visit(VisitKind.VISIT_SUPER_UNARY,
element: 'function(B#unary-)', operator: '-')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => -super;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_UNARY,
operator: '-')),
const Test.clazz(
'''
class B {
operator ~() => null;
}
class C extends B {
m() => ~super;
}
''',
const Visit(VisitKind.VISIT_SUPER_UNARY,
element: 'function(B#~)', operator: '~')),
const Test.clazz(
'''
class B {
operator -() => null;
}
class C extends B {
static m() => -super;
}
''',
const Visit(VisitKind.ERROR_INVALID_UNARY,
error: MessageKind.NO_SUPER_IN_STATIC,
operator: '-')),
const Test(
'''
m() => !0;
''',
const Visit(VisitKind.VISIT_NOT, expression: '0')),
const Test(
'''
m() => +false;
''',
// TODO(johnniwinther): Should this be an
// ERROR_UNDEFINED_UNARY_EXPRESSION? Currently the parser just skips
// the `+`.
const []),
],
'Index set': const [
// Index set
const Test(
'''
m() => 0[1] = 2;
''',
const Visit(VisitKind.VISIT_INDEX_SET,
receiver: '0', index: '1', rhs: '2')),
const Test.clazz(
'''
class B {
operator []=(a, b) {}
}
class C extends B {
m() => super[1] = 2;
}
''',
const Visit(VisitKind.VISIT_SUPER_INDEX_SET,
element: 'function(B#[]=)', index: '1', rhs: '2')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super[1] = 2;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_INDEX_SET,
index: '1', rhs: '2')),
const Test.clazz(
'''
class B {
operator []=(a, b) {}
}
class C extends B {
static m() => super[1] = 2;
}
''',
const Visit(VisitKind.ERROR_INVALID_INDEX_SET,
error: MessageKind.NO_SUPER_IN_STATIC, index: '1', rhs: '2')),
],
'Compound assignment': const [
// Compound assignment
const Test(
'''
m(a) => a.b += 42;
''',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_COMPOUND,
receiver: 'a', name: 'b', operator: '+=', rhs: '42'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)')
]),
const Test(
'''
m(a) => a += 42;
''',
const Visit(VisitKind.VISIT_PARAMETER_COMPOUND,
element: 'parameter(m#a)', operator: '+=', rhs: '42')),
const Test(
'''
m(final a) => a += 42;
''',
const Visit(VisitKind.VISIT_FINAL_PARAMETER_COMPOUND,
element: 'parameter(m#a)', operator: '+=', rhs: '42')),
const Test(
'''
m() {
var a;
a += 42;
}
''',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_COMPOUND,
element: 'variable(m#a)', operator: '+=', rhs: '42')),
const Test(
'''
m() {
final a = 0;
a += 42;
}
''',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_COMPOUND,
element: 'variable(m#a)', operator: '+=', rhs: '42')),
const Test(
'''
m() {
a() {}
a += 42;
}
''',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_COMPOUND,
element: 'function(m#a)', operator: '+=', rhs: '42')),
const Test(
'''
var a;
m() => a += 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_COMPOUND,
element: 'field(a)', operator: '+=', rhs: '42')),
const Test(
'''
get a => 0;
set a(_) {}
m() => a += 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SETTER_COMPOUND,
getter: 'getter(a)', setter: 'setter(a)',
operator: '+=', rhs: '42')),
const Test(
'''
class C {
static var a;
}
m() => C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_COMPOUND,
element: 'field(C#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static var a;
m() => C.a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_COMPOUND,
element: 'field(C#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static var a;
m() => a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_COMPOUND,
element: 'field(C#a)', operator: '+=', rhs: '42')),
const Test.prefix(
'''
class C {
static var a;
}
''',
'''
m() => p.C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_COMPOUND,
element: 'field(C#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
var o;
static m() { o += 42; }
}
''',
const Visit(VisitKind.ERROR_INVALID_COMPOUND,
error: MessageKind.NO_INSTANCE_AVAILABLE,
operator: '+=',
rhs: '42')),
const Test(
'''
class C {
static get a => 0;
static set a(_) {}
}
m() => C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_COMPOUND,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => C.a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_COMPOUND,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_COMPOUND,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.prefix(
'''
class C {
static get a => 0;
static set a(_) {}
}
''',
'''
m() => p.C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_COMPOUND,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
// TODO(johnniwinther): Enable these when dart2js supports method and setter
// with the same name.
/*const Test(
'''
class C {
static a() {}
static set a(_) {}
}
m() => C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND,
getter: 'function(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static a() {}
static set a(_) {}
m() => C.a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND,
getter: 'function(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static a() {}
static set a(_) {}
m() => a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND,
getter: 'function(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),
const Test.prefix(
'''
class C {
static a() {}
static set a(_) {}
}
''',
'''
m() => p.C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND,
getter: 'function(C#a)', setter: 'setter(C#a)',
operator: '+=', rhs: '42')),*/
const Test.clazz(
'''
class C {
var a;
m() => a += 42;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_COMPOUND,
operator: '+=', name: 'a', rhs: '42')),
const Test.clazz(
'''
class C {
var a = 0;
m() => this.a += 42;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_COMPOUND,
name: 'a', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
var a = 0;
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_COMPOUND,
element: 'field(B#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
final a = 0;
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FINAL_FIELD_COMPOUND,
element: 'field(B#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
get a => 0;
set a (_) {}
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_COMPOUND,
getter: 'getter(B#a)', setter: 'setter(B#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class A {
get a => 0;
}
class B extends A {
set a (_) {}
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_COMPOUND,
getter: 'getter(A#a)', setter: 'setter(B#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
get a => 0;
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_FIELD_COMPOUND,
getter: 'getter(B#a)', setter: 'field(A#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
set a(_) {}
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_COMPOUND,
getter: 'field(A#a)', setter: 'setter(B#a)',
operator: '+=', rhs: '42')),
// TODO(johnniwinther): Enable this when dart2js supports shadow setters.
/*const Test.clazz(
'''
class A {
var a;
}
class B extends A {
final a = 0;
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND,
getter: 'field(B#a)', setter: 'field(A#a)',
operator: '+=', rhs: '42')),*/
const Test.clazz(
'''
class B {
a() {}
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_COMPOUND,
element: 'function(B#a)',
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_COMPOUND,
operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
set a(_) {}
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_COMPOUND,
setter: 'setter(B#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
get a => 42;
}
class C extends B {
m() => super.a += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_COMPOUND,
getter: 'getter(B#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static set a(var value) { }
m() => a += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_GETTER_COMPOUND,
setter: 'setter(C#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 42;
m() => C.a += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_SETTER_COMPOUND,
getter: 'getter(C#a)', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class C {
static final a = 42;
m() => C.a += 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FINAL_FIELD_COMPOUND,
element: 'field(C#a)', operator: '+=', rhs: '42')),
const Test(
'''
class C {
static a(var value) { }
}
m() => C.a += 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_COMPOUND,
element: 'function(C#a)', operator: '+=', rhs: '42')),
const Test(
'''
set a(var value) { }
m() => a += 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_GETTER_COMPOUND,
setter: 'setter(a)', operator: '+=', rhs: '42')),
const Test(
'''
get a => 42;
m() => a += 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_SETTER_COMPOUND,
getter: 'getter(a)', operator: '+=', rhs: '42')),
const Test(
'''
a(var value) { }
m() => a += 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_METHOD_COMPOUND,
element: 'function(a)', operator: '+=', rhs: '42')),
const Test(
'''
final a = 42;
m() => a += 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FINAL_FIELD_COMPOUND,
element: 'field(a)', operator: '+=', rhs: '42')),
const Test(
'''
m() => unresolved += 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_COMPOUND,
operator: '+=', rhs: '42')),
],
'Compound index assignment': const [
// Compound index assignment
const Test(
'''
m() => 0[1] += 42;
''',
const Visit(VisitKind.VISIT_COMPOUND_INDEX_SET,
receiver: '0', index: '1', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
operator [](_) {}
operator []=(a, b) {}
}
class C extends B {
m() => super[1] += 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_COMPOUND_INDEX_SET,
getter: 'function(B#[])', setter: 'function(B#[]=)',
index: '1', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
operator []=(a, b) {}
}
class C extends B {
m() => super[1] += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_COMPOUND_INDEX_SET,
setter: 'function(B#[]=)',
index: '1', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super[1] += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_COMPOUND_INDEX_SET,
index: '1', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
operator [](_) {}
}
class C extends B {
m() => super[1] += 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_COMPOUND_INDEX_SET,
getter: 'function(B#[])',
index: '1', operator: '+=', rhs: '42')),
const Test.clazz(
'''
class B {
operator [](_) {}
operator []=(a, b) {}
}
class C extends B {
static m() => super[1] += 42;
}
''',
const Visit(VisitKind.ERROR_INVALID_COMPOUND_INDEX_SET,
error: MessageKind.NO_SUPER_IN_STATIC,
index: '1', operator: '+=', rhs: '42')),
],
'Prefix expression': const [
// Prefix expression
const Test(
'''
m(a) => --a.b;
''',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_PREFIX,
receiver: 'a', name: 'b', operator: '--'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)')
]),
const Test(
'''
m(a) => ++a;
''',
const Visit(VisitKind.VISIT_PARAMETER_PREFIX,
element: 'parameter(m#a)', operator: '++')),
const Test(
'''
m(final a) => ++a;
''',
const Visit(VisitKind.VISIT_FINAL_PARAMETER_PREFIX,
element: 'parameter(m#a)', operator: '++')),
const Test(
'''
m() {
var a;
--a;
}
''',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_PREFIX,
element: 'variable(m#a)', operator: '--')),
const Test(
'''
m() {
final a = 42;
--a;
}
''',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_PREFIX,
element: 'variable(m#a)', operator: '--')),
const Test(
'''
m() {
a() {}
--a;
}
''',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_PREFIX,
element: 'function(m#a)', operator: '--')),
const Test(
'''
var a;
m() => ++a;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_PREFIX,
element: 'field(a)', operator: '++')),
const Test(
'''
get a => 0;
set a(_) {}
m() => --a;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SETTER_PREFIX,
getter: 'getter(a)', setter: 'setter(a)',
operator: '--')),
const Test(
'''
class C {
static var a;
}
m() => ++C.a;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_PREFIX,
element: 'field(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static var a;
m() => ++C.a;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_PREFIX,
element: 'field(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static var a;
m() => --a;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_PREFIX,
element: 'field(C#a)', operator: '--')),
const Test.prefix(
'''
class C {
static var a;
}
''',
'''
m() => --p.C.a;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_PREFIX,
element: 'field(C#a)', operator: '--')),
const Test.clazz(
'''
class C {
var o;
static m() { ++o; }
}
''',
const Visit(VisitKind.ERROR_INVALID_PREFIX,
error: MessageKind.NO_INSTANCE_AVAILABLE,
operator: '++')),
const Test(
'''
class C {
static get a => 0;
static set a(_) {}
}
m() => ++C.a;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_PREFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '++')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => --C.a;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_PREFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '--')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => --a;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_PREFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '--')),
const Test.prefix(
'''
class C {
static get a => 0;
static set a(_) {}
}
''',
'''
m() => ++p.C.a;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_PREFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '++')),
const Test.clazz(
'''
class C {
var a;
m() => --a;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_PREFIX,
name: 'a', operator: '--')),
const Test.clazz(
'''
class C {
var a = 0;
m() => ++this.a;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_PREFIX,
name: 'a', operator: '++')),
const Test.clazz(
'''
class B {
var a = 0;
}
class C extends B {
m() => --super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_PREFIX,
element: 'field(B#a)', operator: '--')),
const Test.clazz(
'''
class B {
final a = 0;
}
class C extends B {
m() => --super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_FINAL_FIELD_PREFIX,
element: 'field(B#a)', operator: '--')),
const Test.clazz(
'''
class B {
get a => 0;
set a (_) {}
}
class C extends B {
m() => --super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_PREFIX,
getter: 'getter(B#a)', setter: 'setter(B#a)',
operator: '--')),
const Test.clazz(
'''
class A {
get a => 0;
}
class B extends A {
set a (_) {}
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_PREFIX,
getter: 'getter(A#a)', setter: 'setter(B#a)',
operator: '++')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
get a => 0;
}
class C extends B {
m() => --super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_FIELD_PREFIX,
getter: 'getter(B#a)', setter: 'field(A#a)',
operator: '--')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
set a(_) {}
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_PREFIX,
getter: 'field(A#a)', setter: 'setter(B#a)',
operator: '++')),
const Test.clazz(
'''
class B {
a() {}
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_PREFIX,
element: 'function(B#a)',
operator: '++')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_PREFIX,
operator: '++')),
const Test.clazz(
'''
class B {
set a(_) {}
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_PREFIX,
setter: 'setter(B#a)', operator: '++')),
const Test.clazz(
'''
class B {
get a => 42;
}
class C extends B {
m() => ++super.a;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_PREFIX,
getter: 'getter(B#a)', operator: '++')),
const Test.clazz(
'''
class C {
static set a(var value) { }
m() => ++a;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_GETTER_PREFIX,
setter: 'setter(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static get a => 42;
m() => ++C.a;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_SETTER_PREFIX,
getter: 'getter(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static final a = 42;
m() => ++C.a;
}
''',
const Visit(VisitKind.VISIT_STATIC_FINAL_FIELD_PREFIX,
element: 'field(C#a)', operator: '++')),
const Test(
'''
class C {
static a(var value) { }
}
m() => ++C.a;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_PREFIX,
element: 'function(C#a)', operator: '++')),
const Test(
'''
set a(var value) { }
m() => ++a;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_GETTER_PREFIX,
setter: 'setter(a)', operator: '++')),
const Test(
'''
get a => 42;
m() => ++a;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_SETTER_PREFIX,
getter: 'getter(a)', operator: '++')),
const Test(
'''
a(var value) { }
m() => ++a;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_METHOD_PREFIX,
element: 'function(a)', operator: '++')),
const Test(
'''
final a = 42;
m() => ++a;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FINAL_FIELD_PREFIX,
element: 'field(a)', operator: '++')),
const Test(
'''
m() => ++unresolved;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_PREFIX,
operator: '++')),
],
'Postfix expression': const [
// Postfix expression
const Test(
'''
m(a) => a.b--;
''',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_POSTFIX,
receiver: 'a', name: 'b', operator: '--'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)')
]),
const Test(
'''
m(a) => a++;
''',
const Visit(VisitKind.VISIT_PARAMETER_POSTFIX,
element: 'parameter(m#a)', operator: '++')),
const Test(
'''
m(final a) => a++;
''',
const Visit(VisitKind.VISIT_FINAL_PARAMETER_POSTFIX,
element: 'parameter(m#a)', operator: '++')),
const Test(
'''
m() {
var a;
a--;
}
''',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_POSTFIX,
element: 'variable(m#a)', operator: '--')),
const Test(
'''
m() {
final a = 42;
a--;
}
''',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_POSTFIX,
element: 'variable(m#a)', operator: '--')),
const Test(
'''
m() {
a() {}
a--;
}
''',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_POSTFIX,
element: 'function(m#a)', operator: '--')),
const Test(
'''
var a;
m() => a++;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_POSTFIX,
element: 'field(a)', operator: '++')),
const Test(
'''
get a => 0;
set a(_) {}
m() => a--;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SETTER_POSTFIX,
getter: 'getter(a)', setter: 'setter(a)',
operator: '--')),
const Test(
'''
class C {
static var a;
}
m() => C.a++;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_POSTFIX,
element: 'field(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static var a;
m() => C.a++;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_POSTFIX,
element: 'field(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static var a;
m() => a--;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_POSTFIX,
element: 'field(C#a)', operator: '--')),
const Test.prefix(
'''
class C {
static var a;
}
''',
'''
m() => p.C.a--;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_POSTFIX,
element: 'field(C#a)', operator: '--')),
const Test.clazz(
'''
class C {
var o;
static m() { o--; }
}
''',
const Visit(VisitKind.ERROR_INVALID_POSTFIX,
error: MessageKind.NO_INSTANCE_AVAILABLE,
operator: '--')),
const Test(
'''
class C {
static get a => 0;
static set a(_) {}
}
m() => C.a++;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_POSTFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '++')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => C.a--;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_POSTFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '--')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => a--;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_POSTFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '--')),
const Test.prefix(
'''
class C {
static get a => 0;
static set a(_) {}
}
''',
'''
m() => p.C.a++;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_POSTFIX,
getter: 'getter(C#a)', setter: 'setter(C#a)',
operator: '++')),
const Test.clazz(
'''
class C {
var a;
m() => a--;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_POSTFIX,
name: 'a', operator: '--')),
const Test.clazz(
'''
class C {
var a = 0;
m() => this.a++;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_POSTFIX,
name: 'a', operator: '++')),
const Test.clazz(
'''
class B {
var a = 0;
}
class C extends B {
m() => super.a--;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_POSTFIX,
element: 'field(B#a)', operator: '--')),
const Test.clazz(
'''
class B {
final a = 0;
}
class C extends B {
m() => super.a--;
}
''',
const Visit(VisitKind.VISIT_SUPER_FINAL_FIELD_POSTFIX,
element: 'field(B#a)', operator: '--')),
const Test.clazz(
'''
class B {
get a => 0;
set a (_) {}
}
class C extends B {
m() => super.a--;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_POSTFIX,
getter: 'getter(B#a)', setter: 'setter(B#a)',
operator: '--')),
const Test.clazz(
'''
class A {
get a => 0;
}
class B extends A {
set a (_) {}
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_POSTFIX,
getter: 'getter(A#a)', setter: 'setter(B#a)',
operator: '++')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
get a => 0;
}
class C extends B {
m() => super.a--;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_FIELD_POSTFIX,
getter: 'getter(B#a)', setter: 'field(A#a)',
operator: '--')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
set a(_) {}
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_POSTFIX,
getter: 'field(A#a)', setter: 'setter(B#a)',
operator: '++')),
const Test.clazz(
'''
class B {
a() {}
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_POSTFIX,
element: 'function(B#a)',
operator: '++')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_POSTFIX,
operator: '++')),
const Test.clazz(
'''
class B {
set a(_) {}
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_POSTFIX,
setter: 'setter(B#a)', operator: '++')),
const Test.clazz(
'''
class B {
get a => 42;
}
class C extends B {
m() => super.a++;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_POSTFIX,
getter: 'getter(B#a)', operator: '++')),
const Test.clazz(
'''
class C {
static set a(var value) { }
m() => a++;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_GETTER_POSTFIX,
setter: 'setter(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static get a => 42;
m() => C.a++;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_SETTER_POSTFIX,
getter: 'getter(C#a)', operator: '++')),
const Test.clazz(
'''
class C {
static final a = 42;
m() => C.a++;
}
''',
const Visit(VisitKind.VISIT_STATIC_FINAL_FIELD_POSTFIX,
element: 'field(C#a)', operator: '++')),
const Test(
'''
class C {
static a(var value) { }
}
m() => C.a++;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_POSTFIX,
element: 'function(C#a)', operator: '++')),
const Test(
'''
set a(var value) { }
m() => a++;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_GETTER_POSTFIX,
setter: 'setter(a)', operator: '++')),
const Test(
'''
get a => 42;
m() => a++;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_SETTER_POSTFIX,
getter: 'getter(a)', operator: '++')),
const Test(
'''
a(var value) { }
m() => a++;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_METHOD_POSTFIX,
element: 'function(a)', operator: '++')),
const Test(
'''
final a = 42;
m() => a++;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FINAL_FIELD_POSTFIX,
element: 'field(a)', operator: '++')),
const Test(
'''
m() => unresolved++;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_POSTFIX,
operator: '++')),
],
'Constructor invocations': const [
const Test(
'''
class Class {
const Class(a, b);
}
m() => const Class(true, 42);
''',
const Visit(VisitKind.VISIT_CONST_CONSTRUCTOR_INVOKE,
constant: 'const Class(true, 42)')),
const Test(
'''
m() => const bool.fromEnvironment('foo');
''',
const Visit(VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
constant:
'const bool.fromEnvironment("foo")')),
const Test(
'''
m() => const bool.fromEnvironment('foo', defaultValue: true);
''',
const Visit(VisitKind.VISIT_BOOL_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
constant: 'const bool.fromEnvironment("foo", defaultValue: true)')),
const Test(
'''
m() => const int.fromEnvironment('foo');
''',
const Visit(VisitKind.VISIT_INT_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
constant: 'const int.fromEnvironment("foo")')),
const Test(
'''
m() => const String.fromEnvironment('foo');
''',
const Visit(VisitKind.VISIT_STRING_FROM_ENVIRONMENT_CONSTRUCTOR_INVOKE,
constant:
'const String.fromEnvironment("foo")')),
const Test(
'''
class Class {
Class(a, b);
}
m() => const Class(true, 42);
''',
const Visit(VisitKind.ERROR_NON_CONSTANT_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {}
m() => new Class();
''',
const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '()',
type: 'Class',
selector: 'CallStructure(arity=0)')),
const Test(
'''
class Class {
Class(a, b);
}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
Class.named(a, b);
}
m() => new Class.named(true, 42);
''',
const Visit(VisitKind.VISIT_GENERATIVE_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(Class#named)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
Class(a, b) : this._(a, b);
Class._(a, b);
}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_REDIRECTING_GENERATIVE_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
Class() : this._(true, 42);
Class._(a, b);
}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,
element: 'generative_constructor(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
factory Class(a, b) => new Class._(a, b);
Class._(a, b);
}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
factory Class() => new Class._(true, 42);
Class._(a, b);
}
m() => new Class(true, 42);
''',
const Visit(VisitKind.VISIT_CONSTRUCTOR_INCOMPATIBLE_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class<T> {
factory Class(a, b) = Class<int>.a;
factory Class.a(a, b) = Class<Class<T>>.b;
Class.b(a, b);
}
m() => new Class<double>(true, 42);
''',
const Visit(VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class<double>',
target: 'generative_constructor(Class#b)',
targetType: 'Class<Class<int>>',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class<T> {
factory Class(a) = Class<int>.a;
factory Class.a(a, [b]) = Class<Class<T>>.b;
Class.b(a, [b]);
}
m() => new Class<double>(true, 42);
''',
const Visit(VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class<double>',
target: 'generative_constructor(Class#b)',
targetType: 'Class<Class<int>>',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
factory Class() = Class._;
Class._();
}
m() => new Class(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class<T> {
factory Class(a, b) = Class<int>.a;
factory Class.a(a, b) = Class<Class<T>>.b;
Class.b(a);
}
m() => new Class<double>(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class<double>',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
Class(a, b);
}
m() => new Class.unresolved(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_CONSTRUCTOR_INVOKE,
arguments: '(true,42)')),
const Test(
'''
m() => new Unresolved(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_CLASS_CONSTRUCTOR_INVOKE,
arguments: '(true,42)')),
const Test(
'''
abstract class AbstractClass {}
m() => new AbstractClass();
''',
const Visit(
VisitKind.VISIT_ABSTRACT_CLASS_CONSTRUCTOR_INVOKE,
element: 'generative_constructor(AbstractClass#)',
type: 'AbstractClass',
arguments: '()',
selector: 'CallStructure(arity=0)')),
const Test(
'''
class Class {
factory Class(a, b) = Unresolved;
}
m() => new Class(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
factory Class(a, b) = Class.named;
}
m() => new Class(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
class Class {
factory Class(a, b) = Class.named;
factory Class.named(a, b) = Class.unresolved;
}
m() => new Class(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
const Test(
'''
abstract class AbstractClass {
AbstractClass(a, b);
}
class Class {
factory Class(a, b) = AbstractClass;
}
m() => new Class(true, 42);
''',
const Visit(
VisitKind.VISIT_UNRESOLVED_REDIRECTING_FACTORY_CONSTRUCTOR_INVOKE,
element: 'function(Class#)',
arguments: '(true,42)',
type: 'Class',
selector: 'CallStructure(arity=2)')),
],
'If not null expressions': const [
const Test(
'''
m(a) => a?.b;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET,
receiver: 'a',
name: 'b'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
class C {
static var b;
}
m(a) => C?.b;
''',
const Visit(
VisitKind.VISIT_STATIC_FIELD_GET,
element: 'field(C#b)')),
const Test(
'''
m(a) => a?.b = 42;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET,
receiver: 'a',
name: 'b',
rhs: '42'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a) => a?.b(42, true);
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_INVOKE,
receiver: 'a',
arguments: '(42,true)',
selector: 'Selector(call, b, arity=2)'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a) => ++a?.b;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_PREFIX,
receiver: 'a', name: 'b', operator: '++'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a) => a?.b--;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_POSTFIX,
receiver: 'a', name: 'b', operator: '--'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a) => a?.b *= 42;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_COMPOUND,
receiver: 'a', name: 'b', operator: '*=', rhs: '42'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a) => a?.b ??= 42;
''',
const [
const Visit(
VisitKind.VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET_IF_NULL,
receiver: 'a', name: 'b', rhs: '42'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
]),
const Test(
'''
m(a, b) => a ?? b;
''',
const [
const Visit(VisitKind.VISIT_IF_NULL,
left: 'a', right: 'b'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)'),
const Visit(
VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#b)'),
]),
const Test(
'''
m(a) => a ??= 42;
''',
const Visit(
VisitKind.VISIT_PARAMETER_SET_IF_NULL,
element: 'parameter(m#a)',
rhs: '42')),
const Test.prefix(
'''
var o;
''',
'm() => p?.o;',
const Visit(VisitKind.ERROR_INVALID_GET,
error: MessageKind.PREFIX_AS_EXPRESSION)),
],
'Set if null': const [
const Test(
'''
m(a) => a.b ??= 42;
''',
const [
const Visit(VisitKind.VISIT_DYNAMIC_PROPERTY_SET_IF_NULL,
receiver: 'a', name: 'b', rhs: '42'),
const Visit(VisitKind.VISIT_PARAMETER_GET,
element: 'parameter(m#a)')
]),
const Test(
'''
m(a) => a ??= 42;
''',
const Visit(VisitKind.VISIT_PARAMETER_SET_IF_NULL,
element: 'parameter(m#a)', rhs: '42')),
const Test(
'''
m(final a) => a ??= 42;
''',
const Visit(VisitKind.VISIT_FINAL_PARAMETER_SET_IF_NULL,
element: 'parameter(m#a)', rhs: '42')),
const Test(
'''
m() {
var a;
a ??= 42;
}
''',
const Visit(VisitKind.VISIT_LOCAL_VARIABLE_SET_IF_NULL,
element: 'variable(m#a)', rhs: '42')),
const Test(
'''
m() {
final a = 0;
a ??= 42;
}
''',
const Visit(VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET_IF_NULL,
element: 'variable(m#a)', rhs: '42')),
const Test(
'''
m() {
a() {}
a ??= 42;
}
''',
const Visit(VisitKind.VISIT_LOCAL_FUNCTION_SET_IF_NULL,
element: 'function(m#a)', rhs: '42')),
const Test(
'''
var a;
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FIELD_SET_IF_NULL,
element: 'field(a)', rhs: '42')),
const Test(
'''
get a => 0;
set a(_) {}
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(a)', setter: 'setter(a)',
rhs: '42')),
const Test(
'''
class C {
static var a;
}
m() => C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET_IF_NULL,
element: 'field(C#a)', rhs: '42')),
const Test.clazz(
'''
class C {
static var a;
m() => C.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET_IF_NULL,
element: 'field(C#a)', rhs: '42')),
const Test.clazz(
'''
class C {
static var a;
m() => a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET_IF_NULL,
element: 'field(C#a)', rhs: '42')),
const Test.prefix(
'''
class C {
static var a;
}
''',
'''
m() => p.C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_FIELD_SET_IF_NULL,
element: 'field(C#a)', rhs: '42')),
const Test.clazz(
'''
class C {
var o;
static m() { o ??= 42; }
}
''',
const Visit(VisitKind.ERROR_INVALID_SET_IF_NULL,
error: MessageKind.NO_INSTANCE_AVAILABLE,
rhs: '42')),
const Test(
'''
class C {
static get a => 0;
static set a(_) {}
}
m() => C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => C.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 0;
static set a(_) {}
m() => a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.prefix(
'''
class C {
static get a => 0;
static set a(_) {}
}
''',
'''
m() => p.C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(C#a)', setter: 'setter(C#a)',
rhs: '42')),
// TODO(johnniwinther): Enable these when dart2js supports method and setter
// with the same name.
/*const Test(
'''
class C {
static a() {}
static set a(_) {}
}
m() => C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_SET_IF_NULL,
getter: 'function(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.clazz(
'''
class C {
static a() {}
static set a(_) {}
m() => C.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_SET_IF_NULL,
getter: 'function(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.clazz(
'''
class C {
static a() {}
static set a(_) {}
m() => a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_SET_IF_NULL,
getter: 'function(C#a)', setter: 'setter(C#a)',
rhs: '42')),
const Test.prefix(
'''
class C {
static a() {}
static set a(_) {}
}
''',
'''
m() => p.C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SETTER_SET_IF_NULL,
getter: 'function(C#a)', setter: 'setter(C#a)',
rhs: '42')),*/
const Test.clazz(
'''
class C {
var a;
m() => a ??= 42;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET_IF_NULL,
name: 'a', rhs: '42')),
const Test.clazz(
'''
class C {
var a = 0;
m() => this.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_THIS_PROPERTY_SET_IF_NULL,
name: 'a', rhs: '42')),
const Test.clazz(
'''
class B {
var a = 0;
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SET_IF_NULL,
element: 'field(B#a)', rhs: '42')),
const Test.clazz(
'''
class B {
final a = 0;
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FINAL_FIELD_SET_IF_NULL,
element: 'field(B#a)', rhs: '42')),
const Test.clazz(
'''
class B {
get a => 0;
set a (_) {}
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(B#a)', setter: 'setter(B#a)',
rhs: '42')),
const Test.clazz(
'''
class A {
get a => 0;
}
class B extends A {
set a (_) {}
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_SETTER_SET_IF_NULL,
getter: 'getter(A#a)', setter: 'setter(B#a)',
rhs: '42')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
get a => 0;
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_GETTER_FIELD_SET_IF_NULL,
getter: 'getter(B#a)', setter: 'field(A#a)',
rhs: '42')),
const Test.clazz(
'''
class A {
var a;
}
class B extends A {
set a(_) {}
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_SETTER_SET_IF_NULL,
getter: 'field(A#a)', setter: 'setter(B#a)',
rhs: '42')),
// TODO(johnniwinther): Enable this when dart2js supports shadow setters.
/*const Test.clazz(
'''
class A {
var a;
}
class B extends A {
final a = 0;
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_FIELD_FIELD_SET_IF_NULL,
getter: 'field(B#a)', setter: 'field(A#a)',
rhs: '42')),*/
const Test.clazz(
'''
class B {
a() {}
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_SUPER_METHOD_SET_IF_NULL,
element: 'function(B#a)',
rhs: '42')),
const Test.clazz(
'''
class B {
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SET_IF_NULL,
name: 'a', rhs: '42')),
const Test.clazz(
'''
class B {
set a(_) {}
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_GETTER_SET_IF_NULL,
setter: 'setter(B#a)', rhs: '42')),
const Test.clazz(
'''
class B {
get a => 42;
}
class C extends B {
m() => super.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SUPER_SETTER_SET_IF_NULL,
getter: 'getter(B#a)', rhs: '42')),
const Test.clazz(
'''
class C {
static set a(var value) { }
m() => a ??= 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_GETTER_SET_IF_NULL,
setter: 'setter(C#a)', rhs: '42')),
const Test.clazz(
'''
class C {
static get a => 42;
m() => C.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_STATIC_SETTER_SET_IF_NULL,
getter: 'getter(C#a)', rhs: '42')),
const Test.clazz(
'''
class C {
static final a = 42;
m() => C.a ??= 42;
}
''',
const Visit(VisitKind.VISIT_STATIC_FINAL_FIELD_SET_IF_NULL,
element: 'field(C#a)', rhs: '42')),
const Test(
'''
class C {
static a(var value) { }
}
m() => C.a ??= 42;
''',
const Visit(VisitKind.VISIT_STATIC_METHOD_SET_IF_NULL,
element: 'function(C#a)', rhs: '42')),
const Test(
'''
set a(var value) { }
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_GETTER_SET_IF_NULL,
setter: 'setter(a)', rhs: '42')),
const Test(
'''
get a => 42;
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_TOP_LEVEL_SETTER_SET_IF_NULL,
getter: 'getter(a)', rhs: '42')),
const Test(
'''
a(var value) { }
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_METHOD_SET_IF_NULL,
element: 'function(a)', rhs: '42')),
const Test(
'''
final a = 42;
m() => a ??= 42;
''',
const Visit(VisitKind.VISIT_TOP_LEVEL_FINAL_FIELD_SET_IF_NULL,
element: 'field(a)', rhs: '42')),
const Test(
'''
m() => unresolved ??= 42;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_SET_IF_NULL,
name: 'unresolved', rhs: '42')),
],
};