blob: cc75176d5d35c433bfd0973e199ffa04e7cdbce1 [file] [log] [blame]
// Copyright (c) 2019, 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.
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'context_collection_resolution.dart';
import 'node_text_expectations.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ExtensionOverrideResolutionTest);
defineReflectiveTests(UpdateNodeTextExpectations);
});
}
@reflectiveTest
class ExtensionOverrideResolutionTest extends PubPackageResolutionTest {
test_call_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
int call(String s) => 0;
}
void f(A a) {
E(a)('');
}
''');
var node = findNode.functionExpressionInvocation('E(a)');
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleStringLiteral
literal: ''
rightParenthesis: )
element: <testLibrary>::@extension::E::@method::call
staticInvokeType: int Function(String)
staticType: int
''');
}
test_call_noPrefix_typeArguments() async {
// The test is failing because we're not yet doing type inference.
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
int call(T s) => 0;
}
void f(A a) {
E<String>(a)('');
}
''');
var node = findNode.functionExpressionInvocation('(a)');
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: String
element2: dart:core::@class::String
type: String
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
String
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleStringLiteral
literal: ''
rightParenthesis: )
element: MethodMember
baseElement: <testLibrary>::@extension::E::@method::call
substitution: {T: String}
staticInvokeType: int Function(String)
staticType: int
''');
}
test_call_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
int call(String s) => 0;
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a)('');
}
''');
var node = findNode.functionExpressionInvocation('E(a)');
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleStringLiteral
literal: ''
rightParenthesis: )
element: package:test/lib.dart::@extension::E::@method::call
staticInvokeType: int Function(String)
staticType: int
''');
}
test_call_prefix_typeArguments() async {
// The test is failing because we're not yet doing type inference.
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
int call(T s) => 0;
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<String>(a)('');
}
''');
var node = findNode.functionExpressionInvocation('(a)');
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: String
element2: dart:core::@class::String
type: String
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
String
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleStringLiteral
literal: ''
rightParenthesis: )
element: MethodMember
baseElement: package:test/lib.dart::@extension::E::@method::call
substitution: {T: String}
staticInvokeType: int Function(String)
staticType: int
''');
}
test_getter_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
int get g => 0;
}
void f(A a) {
E(a).g;
}
''');
var node = findNode.propertyAccess('E(a)');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: g
element: <testLibraryFragment>::@extension::E::@getter::g#element
staticType: int
staticType: int
''');
}
test_getter_noPrefix_noTypeArguments_functionExpressionInvocation() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
double Function(int) get g => (b) => 2.0;
}
void f(A a) {
E(a).g(0);
}
''');
var node = findNode.functionExpressionInvocation('E(a)');
assertResolvedNodeText(node, r'''
FunctionExpressionInvocation
function: PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: g
element: <testLibraryFragment>::@extension::E::@getter::g#element
staticType: double Function(int)
staticType: double Function(int)
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
correspondingParameter: root::@parameter::#element
staticType: int
rightParenthesis: )
element: <null>
staticInvokeType: double Function(int)
staticType: double
''');
}
test_getter_noPrefix_typeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
int get g => 0;
}
void f(A a) {
E<int>(a).g;
}
''');
var node = findNode.propertyAccess('(a)');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: g
element: <testLibraryFragment>::@extension::E::@getter::g#element
staticType: int
staticType: int
''');
}
test_getter_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
int get g => 0;
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a).g;
}
''');
var node = findNode.propertyAccess('E(a)');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: g
element: package:test/lib.dart::<fragment>::@extension::E::@getter::g#element
staticType: int
staticType: int
''');
}
test_getter_prefix_typeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
int get g => 0;
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<int>(a).g;
}
''');
var node = findNode.propertyAccess('(a)');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: g
element: package:test/lib.dart::<fragment>::@extension::E::@getter::g#element
staticType: int
staticType: int
''');
}
test_indexExpression_read_nullAware() async {
await assertNoErrorsInCode('''
extension E on int {
int operator [](int index) => 0;
}
void f(int? a) {
E(a)?[0];
}
''');
assertResolvedNodeText(findNode.index('[0]'), r'''
IndexExpression
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: int?
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: int
staticType: null
question: ?
leftBracket: [
index: IntegerLiteral
literal: 0
correspondingParameter: <testLibraryFragment>::@extension::E::@method::[]::@parameter::index#element
staticType: int
rightBracket: ]
element: <testLibrary>::@extension::E::@method::[]
staticType: int?
''');
}
test_indexExpression_write_nullAware() async {
await assertNoErrorsInCode('''
extension E on int {
operator []=(int index, int value) {}
}
void f(int? a) {
E(a)?[0] = 1;
}
''');
assertResolvedNodeText(findNode.assignment('[0] ='), r'''
AssignmentExpression
leftHandSide: IndexExpression
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: int?
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: int
staticType: null
question: ?
leftBracket: [
index: IntegerLiteral
literal: 0
correspondingParameter: <testLibraryFragment>::@extension::E::@method::[]=::@parameter::index#element
staticType: int
rightBracket: ]
element: <null>
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 1
correspondingParameter: <testLibraryFragment>::@extension::E::@method::[]=::@parameter::value#element
staticType: int
readElement2: <null>
readType: null
writeElement2: <testLibrary>::@extension::E::@method::[]=
writeType: int
element: <null>
staticType: int?
''');
}
test_method_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
void m() {}
}
void f(A a) {
E(a).m();
}
''');
var node = findNode.methodInvocation('E(a)');
assertResolvedNodeText(node, r'''
MethodInvocation
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: .
methodName: SimpleIdentifier
token: m
element: <testLibrary>::@extension::E::@method::m
staticType: void Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: void Function()
staticType: void
''');
}
test_method_noPrefix_typeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
void m() {}
}
void f(A a) {
E<int>(a).m();
}
''');
var node = findNode.methodInvocation('(a)');
assertResolvedNodeText(node, r'''
MethodInvocation
target: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
methodName: SimpleIdentifier
token: m
element: <testLibrary>::@extension::E::@method::m
staticType: void Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: void Function()
staticType: void
''');
}
test_method_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
void m() {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a).m();
}
''');
var node = findNode.methodInvocation('E(a)');
assertResolvedNodeText(node, r'''
MethodInvocation
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
operator: .
methodName: SimpleIdentifier
token: m
element: package:test/lib.dart::@extension::E::@method::m
staticType: void Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: void Function()
staticType: void
''');
}
test_method_prefix_typeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
void m() {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<int>(a).m();
}
''');
var node = findNode.methodInvocation('(a)');
assertResolvedNodeText(node, r'''
MethodInvocation
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
methodName: SimpleIdentifier
token: m
element: package:test/lib.dart::@extension::E::@method::m
staticType: void Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: void Function()
staticType: void
''');
}
test_methodInvocation_nullAware() async {
await assertNoErrorsInCode('''
extension E on int {
int foo() => 0;
}
void f(int? a) {
E(a)?.foo();
}
''');
var node = findNode.methodInvocation('foo();');
assertResolvedNodeText(node, r'''
MethodInvocation
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: int?
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: int
staticType: null
operator: ?.
methodName: SimpleIdentifier
token: foo
element: <testLibrary>::@extension::E::@method::foo
staticType: int Function()
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
staticInvokeType: int Function()
staticType: int?
''');
}
test_operator_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
void operator +(int offset) {}
}
void f(A a) {
E(a) + 1;
}
''');
var node = findNode.binary('(a)');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: +
rightOperand: IntegerLiteral
literal: 1
correspondingParameter: <testLibraryFragment>::@extension::E::@method::+::@parameter::offset#element
staticType: int
element: <testLibrary>::@extension::E::@method::+
staticInvokeType: void Function(int)
staticType: void
''');
}
test_operator_noPrefix_typeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
void operator +(int offset) {}
}
void f(A a) {
E<int>(a) + 1;
}
''');
var node = findNode.binary('(a)');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: +
rightOperand: IntegerLiteral
literal: 1
correspondingParameter: <testLibraryFragment>::@extension::E::@method::+::@parameter::offset#element
staticType: int
element: <testLibrary>::@extension::E::@method::+
staticInvokeType: void Function(int)
staticType: void
''');
}
test_operator_onTearOff() async {
// https://github.com/dart-lang/sdk/issues/38653
await assertErrorsInCode(
'''
extension E on int {
v() {}
}
f(){
E(0).v++;
}
''',
[error(CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER, 45, 1)],
);
var node = findNode.postfix('++;');
assertResolvedNodeText(node, r'''
PostfixExpression
operand: PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
IntegerLiteral
literal: 0
correspondingParameter: <null>
staticType: int
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: int
staticType: null
operator: .
propertyName: SimpleIdentifier
token: v
element: <null>
staticType: null
staticType: null
operator: ++
readElement2: <testLibrary>::@extension::E::@method::v
readType: InvalidType
writeElement2: <null>
writeType: InvalidType
element: <null>
staticType: InvalidType
''');
}
test_operator_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
void operator +(int offset) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a) + 1;
}
''');
var node = findNode.binary('(a)');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
operator: +
rightOperand: IntegerLiteral
literal: 1
correspondingParameter: package:test/lib.dart::<fragment>::@extension::E::@method::+::@parameter::offset#element
staticType: int
element: package:test/lib.dart::@extension::E::@method::+
staticInvokeType: void Function(int)
staticType: void
''');
}
test_operator_prefix_typeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
void operator +(int offset) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<int>(a) + 1;
}
''');
var node = findNode.binary('(a)');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: +
rightOperand: IntegerLiteral
literal: 1
correspondingParameter: package:test/lib.dart::<fragment>::@extension::E::@method::+::@parameter::offset#element
staticType: int
element: package:test/lib.dart::@extension::E::@method::+
staticInvokeType: void Function(int)
staticType: void
''');
}
test_promotion() async {
await assertNoErrorsInCode(r'''
class C {
int f() => 0;
}
extension E on C {
int g(dynamic d) => 0;
}
void test(C? c) {
E(c)?.g(c); // `c` is promoted to `C` on the RHS of `?.`
}
''');
var node = findNode.simple('c);');
assertResolvedNodeText(node, r'''
SimpleIdentifier
token: c
correspondingParameter: <testLibraryFragment>::@extension::E::@method::g::@parameter::d#element
element: <testLibraryFragment>::@function::test::@parameter::c#element
staticType: C
''');
}
test_propertyAccess_getter_nullAware() async {
await assertNoErrorsInCode('''
extension E on int {
int get foo => 0;
}
void f(int? a) {
E(a)?.foo;
}
''');
var node = findNode.singlePropertyAccess;
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: int?
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: int
staticType: null
operator: ?.
propertyName: SimpleIdentifier
token: foo
element: <testLibraryFragment>::@extension::E::@getter::foo#element
staticType: int
staticType: int?
''');
}
test_propertyAccess_setter_nullAware() async {
await assertNoErrorsInCode('''
extension E on int {
set foo(int _) {}
}
void f(int? a) {
E(a)?.foo = 0;
}
''');
}
test_setter_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
set s(int x) {}
}
void f(A a) {
E(a).s = 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: <testLibraryFragment>::@extension::E::@setter::s::@parameter::x#element
staticType: int
readElement2: <null>
readType: null
writeElement2: <testLibraryFragment>::@extension::E::@setter::s#element
writeType: int
element: <null>
staticType: int
''');
}
test_setter_noPrefix_typeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
set s(int x) {}
}
void f(A a) {
E<int>(a).s = 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: <testLibraryFragment>::@extension::E::@setter::s::@parameter::x#element
staticType: int
readElement2: <null>
readType: null
writeElement2: <testLibraryFragment>::@extension::E::@setter::s#element
writeType: int
element: <null>
staticType: int
''');
}
test_setter_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
set s(int x) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a).s = 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: package:test/lib.dart::<fragment>::@extension::E::@setter::s::@parameter::x#element
staticType: int
readElement2: <null>
readType: null
writeElement2: package:test/lib.dart::<fragment>::@extension::E::@setter::s#element
writeType: int
element: <null>
staticType: int
''');
}
test_setter_prefix_typeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
set s(int x) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<int>(a).s = 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: package:test/lib.dart::<fragment>::@extension::E::@setter::s::@parameter::x#element
staticType: int
readElement2: <null>
readType: null
writeElement2: package:test/lib.dart::<fragment>::@extension::E::@setter::s#element
writeType: int
element: <null>
staticType: int
''');
}
test_setterAndGetter_noPrefix_noTypeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E on A {
int get s => 0;
set s(int x) {}
}
void f(A a) {
E(a).s += 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: +=
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: dart:core::<fragment>::@class::num::@method::+::@parameter::other#element
staticType: int
readElement2: <testLibraryFragment>::@extension::E::@getter::s#element
readType: int
writeElement2: <testLibraryFragment>::@extension::E::@setter::s#element
writeType: int
element: dart:core::@class::num::@method::+
staticType: int
''');
}
test_setterAndGetter_noPrefix_typeArguments() async {
await assertNoErrorsInCode('''
class A {}
extension E<T> on A {
int get s => 0;
set s(int x) {}
}
void f(A a) {
E<int>(a).s += 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: +=
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: dart:core::<fragment>::@class::num::@method::+::@parameter::other#element
staticType: int
readElement2: <testLibraryFragment>::@extension::E::@getter::s#element
readType: int
writeElement2: <testLibraryFragment>::@extension::E::@setter::s#element
writeType: int
element: dart:core::@class::num::@method::+
staticType: int
''');
}
test_setterAndGetter_prefix_noTypeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E on A {
int get s => 0;
set s(int x) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E(a).s += 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: +=
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: dart:core::<fragment>::@class::num::@method::+::@parameter::other#element
staticType: int
readElement2: package:test/lib.dart::<fragment>::@extension::E::@getter::s#element
readType: int
writeElement2: package:test/lib.dart::<fragment>::@extension::E::@setter::s#element
writeType: int
element: dart:core::@class::num::@method::+
staticType: int
''');
}
test_setterAndGetter_prefix_typeArguments() async {
newFile('$testPackageLibPath/lib.dart', '''
class A {}
extension E<T> on A {
int get s => 0;
set s(int x) {}
}
''');
await assertNoErrorsInCode('''
import 'lib.dart' as p;
void f(p.A a) {
p.E<int>(a).s += 0;
}
''');
var node = findNode.assignment('(a)');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: ExtensionOverride
importPrefix: ImportPrefixReference
name: p
period: .
element2: <testLibraryFragment>::@prefix2::p
name: E
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: int
element2: dart:core::@class::int
type: int
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: a
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::a#element
staticType: A
rightParenthesis: )
element2: package:test/lib.dart::@extension::E
extendedType: A
staticType: null
typeArgumentTypes
int
operator: .
propertyName: SimpleIdentifier
token: s
element: <null>
staticType: null
staticType: null
operator: +=
rightHandSide: IntegerLiteral
literal: 0
correspondingParameter: dart:core::<fragment>::@class::num::@method::+::@parameter::other#element
staticType: int
readElement2: package:test/lib.dart::<fragment>::@extension::E::@getter::s#element
readType: int
writeElement2: package:test/lib.dart::<fragment>::@extension::E::@setter::s#element
writeType: int
element: dart:core::@class::num::@method::+
staticType: int
''');
}
test_tearOff() async {
await assertNoErrorsInCode('''
class C {}
extension E on C {
void a(int x) {}
}
f(C c) => E(c).a;
''');
var node = findNode.propertyAccess('E(c)');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ExtensionOverride
name: E
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: c
correspondingParameter: <null>
element: <testLibraryFragment>::@function::f::@parameter::c#element
staticType: C
rightParenthesis: )
element2: <testLibrary>::@extension::E
extendedType: C
staticType: null
operator: .
propertyName: SimpleIdentifier
token: a
element: <testLibrary>::@extension::E::@method::a
staticType: void Function(int)
staticType: void Function(int)
''');
}
}