Replace assertUnresolvedSimpleIdentifier() with textual expectations.

Change-Id: I1227edbc7935091a652dd8220b90dadb77f72b82
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294180
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov
2023-04-07 15:44:48 +00:00
committed by Commit Queue
parent 0c7c721402
commit 60d9943ce0
8 changed files with 666 additions and 713 deletions
@@ -897,45 +897,6 @@ main() {
assertType(identifier, 'Future<dynamic> Function()');
}
test_deferredImport_variable() async {
newFile('$testPackageLibPath/a.dart', 'var v = 0;');
addTestFile(r'''
import 'a.dart' deferred as a;
main() async {
a.v;
a.v = 1;
}
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var v = (import.importedLibrary!.publicNamespace.get('v')
as PropertyAccessorElement)
.variable as TopLevelVariableElement;
{
var prefixed = findNode.prefixed('a.v;');
assertElement(prefixed, v.getter);
assertType(prefixed, 'int');
assertElement(prefixed.prefix, import.prefix?.element);
assertType(prefixed.prefix, null);
assertElement(prefixed.identifier, v.getter);
assertType(prefixed.identifier, 'int');
}
{
var prefixed = findNode.prefixed('a.v = 1;');
assertElementNull(prefixed);
assertTypeNull(prefixed);
assertElement(prefixed.prefix, import.prefix?.element);
assertType(prefixed.prefix, null);
assertUnresolvedSimpleIdentifier(prefixed.identifier);
}
}
test_directive_export() async {
newFile('$testPackageLibPath/a.dart', r'''
class MyClass {}
@@ -1139,30 +1100,6 @@ class C<T> {
fElement.type, typeProvider.listType(typeParameterTypeNone(tElement)));
}
test_field_generic() async {
addTestFile(r'''
class C<T> {
T f;
}
main(C<int> c) {
c.f; // ref
c.f = 1;
}
''');
await resolveTestFile();
{
var fRef = findNode.simple('f; // ref');
assertMember(fRef, findElement.getter('f'), {'T': 'int'});
assertType(fRef, 'int');
}
{
var fRef = findNode.simple('f = 1;');
assertUnresolvedSimpleIdentifier(fRef);
}
}
test_formalParameter_functionTyped() async {
addTestFile(r'''
class A {
@@ -5125,82 +5062,6 @@ void f(int g()) {
assertElement(gRef, findElement.parameter('g'));
}
test_postfix_increment_of_postfix_increment() async {
addTestFile('''
void f(int x) {
x ++ ++;
}
''');
await resolveTestFile();
var xRef = findNode.simple('x ++');
assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_postfixExpression_local() async {
String content = r'''
main() {
int v = 0;
v++;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
VariableElement v;
{
var statement = mainStatements[0] as VariableDeclarationStatement;
v = statement.variables.variables[0].declaredElement!;
expect(v.type, typeProvider.intType);
}
{
var statement = mainStatements[1] as ExpressionStatement;
var postfix = statement.expression as PostfixExpression;
expect(postfix.operator.type, TokenType.PLUS_PLUS);
expect(postfix.staticElement!.name, '+');
expect(postfix.staticType, typeProvider.intType);
var operand = postfix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(operand, disableElementCheck: true);
}
}
test_postfixExpression_propertyAccess() async {
String content = r'''
main() {
new C().f++;
}
class C {
int f;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
{
var statement = mainStatements[0] as ExpressionStatement;
var postfix = statement.expression as PostfixExpression;
expect(postfix.operator.type, TokenType.PLUS_PLUS);
expect(postfix.staticElement!.name, '+');
expect(postfix.staticType, typeProvider.intType);
var propertyAccess = postfix.operand as PropertyAccess;
assertUnresolvedPropertyAccess(propertyAccess);
SimpleIdentifier propertyName = propertyAccess.propertyName;
assertUnresolvedSimpleIdentifier(propertyName);
}
}
test_prefix_increment_of_non_generator() async {
addTestFile('''
void f(bool x) {
@@ -5214,30 +5075,6 @@ void f(bool x) {
assertElement(xRef, findElement.parameter('x'));
}
test_prefix_increment_of_postfix_increment() async {
addTestFile('''
void f(int x) {
++x++;
}
''');
await resolveTestFile();
var xRef = findNode.simple('x++');
assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_prefix_increment_of_prefix_increment() async {
addTestFile('''
void f(int x) {
++ ++ x;
}
''');
await resolveTestFile();
var xRef = findNode.simple('x;');
assertUnresolvedSimpleIdentifier(xRef, disableElementCheck: true);
}
test_prefixedIdentifier_classInstance_instanceField() async {
String content = r'''
main() {
@@ -5332,231 +5169,6 @@ f(double computation(int p)) {
assertType(methodName.staticType, 'double Function(int)');
}
test_prefixedIdentifier_importPrefix_className() async {
newFile('$testPackageLibPath/lib.dart', '''
class MyClass {}
typedef void MyFunctionTypeAlias();
int myTopVariable;
int myTopFunction() => 0;
int get myGetter => 0;
void set mySetter(int _) {}
''');
addTestFile(r'''
import 'lib.dart' as my;
main() {
my.MyClass;
my.MyFunctionTypeAlias;
my.myTopVariable;
my.myTopFunction;
my.myTopFunction();
my.myGetter;
my.mySetter = 0;
}
''');
await resolveTestFile();
// TODO(scheglov) Uncomment and fix "unused imports" hint.
// expect(result.errors, isEmpty);
var unitElement = result.unit.declaredElement!;
final myImport = unitElement.library.libraryImports[0];
PrefixElement myPrefix = myImport.prefix!.element;
var myLibrary = myImport.importedLibrary!;
var myUnit = myLibrary.definingCompilationUnit;
var myClass = myUnit.classes.single;
var myTypeAlias = myUnit.typeAliases.single;
var myTopVariable = myUnit.topLevelVariables[0];
var myTopFunction = myUnit.functions.single;
var myGetter = myUnit.topLevelVariables[1].getter!;
var mySetter = myUnit.topLevelVariables[2].setter!;
expect(myTopVariable.name, 'myTopVariable');
expect(myGetter.displayName, 'myGetter');
expect(mySetter.displayName, 'mySetter');
List<Statement> statements = _getMainStatements(result);
void assertPrefix(SimpleIdentifier identifier) {
expect(identifier.staticElement, same(myPrefix));
expect(identifier.staticType, isNull);
}
void assertPrefixedIdentifier(
int statementIndex, Element expectedElement, DartType expectedType) {
var statement = statements[statementIndex] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
assertPrefix(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(expectedElement));
expect(prefixed.identifier.staticType, expectedType);
}
assertPrefixedIdentifier(0, myClass, typeProvider.typeType);
assertPrefixedIdentifier(1, myTypeAlias, typeProvider.typeType);
assertPrefixedIdentifier(2, myTopVariable.getter!, typeProvider.intType);
{
var statement = statements[3] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
assertPrefix(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(myTopFunction));
expect(prefixed.identifier.staticType, isNotNull);
}
{
var statement = statements[4] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
assertPrefix(invocation.target as SimpleIdentifier);
expect(invocation.methodName.staticElement, same(myTopFunction));
expect(invocation.methodName.staticType, isNotNull);
}
assertPrefixedIdentifier(5, myGetter, typeProvider.intType);
{
var statement = statements[6] as ExpressionStatement;
var assignment = statement.expression as AssignmentExpression;
var left = assignment.leftHandSide as PrefixedIdentifier;
assertPrefix(left.prefix);
assertUnresolvedSimpleIdentifier(left.identifier);
}
}
test_prefixExpression_local() async {
String content = r'''
main() {
int v = 0;
++v;
~v;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
VariableElement v;
{
var statement = mainStatements[0] as VariableDeclarationStatement;
v = statement.variables.variables[0].declaredElement!;
expect(v.type, typeProvider.intType);
}
{
var statement = mainStatements[1] as ExpressionStatement;
var prefix = statement.expression as PrefixExpression;
expect(prefix.operator.type, TokenType.PLUS_PLUS);
expect(prefix.staticElement!.name, '+');
expect(prefix.staticType, typeProvider.intType);
var operand = prefix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(operand, disableElementCheck: true);
}
{
var statement = mainStatements[2] as ExpressionStatement;
var prefix = statement.expression as PrefixExpression;
expect(prefix.operator.type, TokenType.TILDE);
expect(prefix.staticElement!.name, '~');
expect(prefix.staticType, typeProvider.intType);
var operand = prefix.operand as SimpleIdentifier;
expect(operand.staticElement, same(v));
expect(operand.staticType, typeProvider.intType);
}
}
test_prefixExpression_local_not() async {
String content = r'''
main() {
bool v = true;
!v;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
VariableElement v;
{
var statement = mainStatements[0] as VariableDeclarationStatement;
v = statement.variables.variables[0].declaredElement!;
expect(v.type, typeProvider.boolType);
}
{
var statement = mainStatements[1] as ExpressionStatement;
var prefix = statement.expression as PrefixExpression;
expect(prefix.operator.type, TokenType.BANG);
expect(prefix.staticElement, isNull);
expect(prefix.staticType, typeProvider.boolType);
var operand = prefix.operand as SimpleIdentifier;
expect(operand.staticElement, same(v));
expect(operand.staticType, typeProvider.boolType);
}
}
test_prefixExpression_propertyAccess() async {
String content = r'''
main() {
++new C().f;
~new C().f;
}
class C {
int f;
}
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
ClassElement cClassElement = cClassDeclaration.declaredElement!;
FieldElement fElement = cClassElement.getField('f')!;
List<Statement> mainStatements = _getMainStatements(result);
{
var statement = mainStatements[0] as ExpressionStatement;
var prefix = statement.expression as PrefixExpression;
expect(prefix.operator.type, TokenType.PLUS_PLUS);
expect(prefix.staticElement!.name, '+');
expect(prefix.staticType, typeProvider.intType);
var propertyAccess = prefix.operand as PropertyAccess;
assertUnresolvedPropertyAccess(propertyAccess);
SimpleIdentifier propertyName = propertyAccess.propertyName;
assertUnresolvedSimpleIdentifier(propertyName);
}
{
var statement = mainStatements[1] as ExpressionStatement;
var prefix = statement.expression as PrefixExpression;
expect(prefix.operator.type, TokenType.TILDE);
expect(prefix.staticElement!.name, '~');
expect(prefix.staticType, typeProvider.intType);
var propertyAccess = prefix.operand as PropertyAccess;
expect(propertyAccess.staticType, typeProvider.intType);
SimpleIdentifier propertyName = propertyAccess.propertyName;
expect(propertyName.staticElement, same(fElement.getter));
expect(propertyName.staticType, typeProvider.intType);
}
}
test_propertyAccess_field() async {
String content = r'''
main() {
@@ -5731,236 +5343,6 @@ void main() {
expect(result.errors, isEmpty);
}
test_super() async {
String content = r'''
class A {
void method(int p) {}
int get getter => 0;
void set setter(int p) {}
int operator+(int p) => 0;
}
class B extends A {
void test() {
method(1);
super.method(2);
getter;
super.getter;
setter = 3;
super.setter = 4;
this + 5;
}
}
''';
addTestFile(content);
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
var bNode = result.unit.declarations[1] as ClassDeclaration;
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
aNode.members[1].declaredElement as PropertyAccessorElement;
var operatorElement = aNode.members[3].declaredElement as MethodElement;
var testNode = bNode.members[0] as MethodDeclaration;
var testBody = testNode.body as BlockFunctionBody;
List<Statement> testStatements = testBody.block.statements;
// method(1);
{
var statement = testStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.target, isNull);
expect(invocation.methodName.staticElement, same(methodElement));
}
// super.method(2);
{
var statement = testStatements[1] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
var target = invocation.target as SuperExpression;
expect(
target.staticType, interfaceTypeNone(bNode.declaredElement!)); // raw
expect(invocation.methodName.staticElement, same(methodElement));
}
// getter;
{
var statement = testStatements[2] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(getterElement));
expect(identifier.staticType, typeProvider.intType);
}
// super.getter;
{
var statement = testStatements[3] as ExpressionStatement;
var propertyAccess = statement.expression as PropertyAccess;
expect(propertyAccess.staticType, typeProvider.intType);
var target = propertyAccess.target as SuperExpression;
expect(
target.staticType, interfaceTypeNone(bNode.declaredElement!)); // raw
expect(propertyAccess.propertyName.staticElement, same(getterElement));
expect(propertyAccess.propertyName.staticType, typeProvider.intType);
}
// setter = 3;
{
var statement = testStatements[4] as ExpressionStatement;
var assignment = statement.expression as AssignmentExpression;
var identifier = assignment.leftHandSide as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(identifier);
}
// this.setter = 4;
{
var statement = testStatements[5] as ExpressionStatement;
var assignment = statement.expression as AssignmentExpression;
var propertyAccess = assignment.leftHandSide as PropertyAccess;
var target = propertyAccess.target as SuperExpression;
expect(
target.staticType, interfaceTypeNone(bNode.declaredElement!)); // raw
assertUnresolvedSimpleIdentifier(propertyAccess.propertyName);
}
// super + 5;
{
var statement = testStatements[6] as ExpressionStatement;
var binary = statement.expression as BinaryExpression;
var target = binary.leftOperand as ThisExpression;
expect(
target.staticType, interfaceTypeNone(bNode.declaredElement!)); // raw
expect(binary.staticElement, same(operatorElement));
expect(binary.staticType, typeProvider.intType);
}
}
test_this() async {
String content = r'''
class A {
void method(int p) {}
int get getter => 0;
void set setter(int p) {}
int operator+(int p) => 0;
void test() {
method(1);
this.method(2);
getter;
this.getter;
setter = 3;
this.setter = 4;
this + 5;
}
}
''';
addTestFile(content);
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
aNode.members[1].declaredElement as PropertyAccessorElement;
var operatorElement = aNode.members[3].declaredElement as MethodElement;
var testNode = aNode.members[4] as MethodDeclaration;
var testBody = testNode.body as BlockFunctionBody;
List<Statement> testStatements = testBody.block.statements;
var elementA = findElement.class_('A');
var thisTypeA = interfaceTypeNone(elementA);
// method(1);
{
var statement = testStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.target, isNull);
expect(invocation.methodName.staticElement, same(methodElement));
}
// this.method(2);
{
var statement = testStatements[1] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
var target = invocation.target as ThisExpression;
expect(target.staticType, thisTypeA); // raw
expect(invocation.methodName.staticElement, same(methodElement));
}
// getter;
{
var statement = testStatements[2] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(getterElement));
expect(identifier.staticType, typeProvider.intType);
}
// this.getter;
{
var statement = testStatements[3] as ExpressionStatement;
var propertyAccess = statement.expression as PropertyAccess;
expect(propertyAccess.staticType, typeProvider.intType);
var target = propertyAccess.target as ThisExpression;
expect(target.staticType, thisTypeA); // raw
expect(propertyAccess.propertyName.staticElement, same(getterElement));
expect(propertyAccess.propertyName.staticType, typeProvider.intType);
}
// setter = 3;
{
var statement = testStatements[4] as ExpressionStatement;
var assignment = statement.expression as AssignmentExpression;
var identifier = assignment.leftHandSide as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(identifier);
}
// this.setter = 4;
{
var statement = testStatements[5] as ExpressionStatement;
var assignment = statement.expression as AssignmentExpression;
var propertyAccess = assignment.leftHandSide as PropertyAccess;
var target = propertyAccess.target as ThisExpression;
expect(target.staticType, thisTypeA); // raw
assertUnresolvedSimpleIdentifier(propertyAccess.propertyName);
}
// this + 5;
{
var statement = testStatements[6] as ExpressionStatement;
var binary = statement.expression as BinaryExpression;
var target = binary.leftOperand as ThisExpression;
expect(target.staticType, thisTypeA); // raw
expect(binary.staticElement, same(operatorElement));
expect(binary.staticType, typeProvider.intType);
}
}
test_top_class_constructor_parameter_defaultValue() async {
String content = r'''
class C {
@@ -7274,78 +6656,6 @@ main() {
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_postfix_operand() async {
addTestFile(r'''
main() {
a++;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var postfix = findNode.postfix('a++');
assertElementNull(postfix);
assertTypeDynamic(postfix);
var aRef = postfix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_postfix_operator() async {
addTestFile(r'''
A a;
main() {
a++;
}
class A {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var postfix = findNode.postfix('a++');
assertElementNull(postfix);
assertType(postfix, 'A');
var aRef = postfix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefix_operand() async {
addTestFile(r'''
main() {
++a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var prefix = findNode.prefix('++a');
assertElementNull(prefix);
assertTypeDynamic(prefix);
var aRef = prefix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefix_operator() async {
addTestFile(r'''
A a;
main() {
++a;
}
class A {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var prefix = findNode.prefix('++a');
assertElementNull(prefix);
assertTypeDynamic(prefix);
var aRef = prefix.operand as SimpleIdentifier;
assertUnresolvedSimpleIdentifier(aRef);
}
test_unresolved_prefixedIdentifier_identifier() async {
addTestFile(r'''
Object foo;
@@ -206,6 +206,48 @@ SimpleIdentifier
''');
}
test_importPrefix_deferred_topLevelVariable_simple() async {
newFile('$testPackageLibPath/a.dart', '''
var v = 0;
''');
await assertNoErrorsInCode(r'''
import 'a.dart' deferred as prefix;
void f() {
prefix.v = 0;
}
''');
final node = findNode.assignment('= 0');
assertResolvedNodeText(node, r'''
AssignmentExpression
leftHandSide: PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: v
staticElement: <null>
staticType: null
staticElement: <null>
staticType: null
operator: =
rightHandSide: IntegerLiteral
literal: 0
parameter: package:test/a.dart::@setter::v::@parameter::_v
staticType: int
readElement: <null>
readType: null
writeElement: package:test/a.dart::@setter::v
writeType: int
staticElement: <null>
staticType: int
''');
}
test_indexExpression_cascade_compound() async {
await assertNoErrorsInCode(r'''
class A {
@@ -413,6 +413,66 @@ BinaryExpression
staticElement: dart:core::@class::num::@method::+
staticInvokeType: num Function(num)
staticType: int
''');
}
test_superQualifier_plus() async {
await assertNoErrorsInCode(r'''
class A {
int operator +(int other) => 0;
}
class B extends A {
int operator +(int other) => 0;
void f() {
super + 0;
}
}
''');
final node = findNode.binary('+ 0');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: SuperExpression
superKeyword: super
staticType: B
operator: +
rightOperand: IntegerLiteral
literal: 0
parameter: self::@class::A::@method::+::@parameter::other
staticType: int
staticElement: self::@class::A::@method::+
staticInvokeType: int Function(int)
staticType: int
''');
}
test_thisExpression_plus() async {
await assertNoErrorsInCode(r'''
class A {
int operator +(int other) => 0;
void f() {
this + 0;
}
}
''');
final node = findNode.binary('+ 0');
assertResolvedNodeText(node, r'''
BinaryExpression
leftOperand: ThisExpression
thisKeyword: this
staticType: A
operator: +
rightOperand: IntegerLiteral
literal: 0
parameter: self::@class::A::@method::+::@parameter::other
staticType: int
staticElement: self::@class::A::@method::+
staticInvokeType: int Function(int)
staticType: int
''');
}
}
@@ -19,6 +19,102 @@ main() {
@reflectiveTest
class PostfixExpressionResolutionTest extends PubPackageResolutionTest
with PostfixExpressionResolutionTestCases {
test_formalParameter_inc_inc() async {
await assertErrorsInCode(r'''
void f(int x) {
x ++ ++;
}
''', [
error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 23, 2),
]);
final node = findNode.postfix('++;');
assertResolvedNodeText(node, r'''
PostfixExpression
operand: PostfixExpression
operand: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: null
operator: ++
readElement: self::@function::f::@parameter::x
readType: int
writeElement: self::@function::f::@parameter::x
writeType: int
staticElement: dart:core::@class::num::@method::+
staticType: int
operator: ++
readElement: <null>
readType: dynamic
writeElement: <null>
writeType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
test_formalParameter_incUnresolved() async {
await assertErrorsInCode(r'''
class A {}
void f(A a) {
a++;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 29, 2),
]);
final node = findNode.postfix('++;');
assertResolvedNodeText(node, r'''
PostfixExpression
operand: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: null
operator: ++
readElement: self::@function::f::@parameter::a
readType: A
writeElement: self::@function::f::@parameter::a
writeType: A
staticElement: <null>
staticType: A
''');
}
test_inc_formalParameter_inc() async {
await assertErrorsInCode(r'''
void f(int x) {
++x++;
}
''', [
error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 21, 2),
]);
final node = findNode.prefix('++x');
assertResolvedNodeText(node, r'''
PrefixExpression
operator: ++
operand: PostfixExpression
operand: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: null
operator: ++
readElement: self::@function::f::@parameter::x
readType: int
writeElement: self::@function::f::@parameter::x
writeType: int
staticElement: dart:core::@class::num::@method::+
staticType: int
readElement: <null>
readType: dynamic
writeElement: <null>
writeType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
test_inc_propertyAccess_nullShorting() async {
await assertNoErrorsInCode(r'''
class A {
@@ -387,6 +483,32 @@ PostfixExpression
operator: !
staticElement: <null>
staticType: T & num
''');
}
test_unresolvedIdentifier_inc() async {
await assertErrorsInCode(r'''
void f() {
x++;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 13, 1),
]);
final node = findNode.postfix('++;');
assertResolvedNodeText(node, r'''
PostfixExpression
operand: SimpleIdentifier
token: x
staticElement: <null>
staticType: null
operator: ++
readElement: <null>
readType: dynamic
writeElement: <null>
writeType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
}
@@ -51,6 +51,68 @@ PrefixExpression
''');
}
test_formalParameter_inc_inc() async {
await assertErrorsInCode(r'''
void f(int x) {
++ ++ x;
}
''', [
error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 24, 1),
]);
final node = findNode.prefix('++ ++ x');
assertResolvedNodeText(node, r'''
PrefixExpression
operator: ++
operand: PrefixExpression
operator: ++
operand: SimpleIdentifier
token: x
staticElement: self::@function::f::@parameter::x
staticType: null
readElement: self::@function::f::@parameter::x
readType: int
writeElement: self::@function::f::@parameter::x
writeType: int
staticElement: dart:core::@class::num::@method::+
staticType: int
readElement: <null>
readType: dynamic
writeElement: <null>
writeType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
test_formalParameter_inc_unresolved() async {
await assertErrorsInCode(r'''
class A {}
void f(A a) {
++a;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 28, 2),
]);
final node = findNode.prefix('++a');
assertResolvedNodeText(node, r'''
PrefixExpression
operator: ++
operand: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: null
readElement: self::@function::f::@parameter::a
readType: A
writeElement: self::@function::f::@parameter::a
writeType: A
staticElement: <null>
staticType: dynamic
''');
}
test_minus_no_nullShorting() async {
await assertErrorsInCode(r'''
class A {
@@ -222,6 +284,32 @@ PrefixExpression
staticType: int?
staticElement: dart:core::@class::int::@method::~
staticType: int
''');
}
test_unresolvedIdentifier_inc() async {
await assertErrorsInCode(r'''
void f() {
++x;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 15, 1),
]);
final node = findNode.prefix('++x');
assertResolvedNodeText(node, r'''
PrefixExpression
operator: ++
operand: SimpleIdentifier
token: x
staticElement: <null>
staticType: null
readElement: <null>
readType: dynamic
writeElement: <null>
writeType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
}
@@ -176,6 +176,188 @@ int Function() foo() {
assertType(identifier, 'A?');
}
test_importPrefix_class() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {}
''');
await assertNoErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.A;
}
''');
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: A
staticElement: package:test/a.dart::@class::A
staticType: Type
staticElement: package:test/a.dart::@class::A
staticType: Type
''');
}
test_importPrefix_functionTypeAlias() async {
newFile('$testPackageLibPath/a.dart', r'''
typedef void F();
''');
await assertNoErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.F;
}
''');
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: F
staticElement: package:test/a.dart::@typeAlias::F
staticType: Type
staticElement: package:test/a.dart::@typeAlias::F
staticType: Type
''');
}
test_importPrefix_topLevelFunction() async {
newFile('$testPackageLibPath/a.dart', r'''
void foo() {}
''');
await assertNoErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.foo;
}
''');
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: foo
staticElement: package:test/a.dart::@function::foo
staticType: void Function()
staticElement: package:test/a.dart::@function::foo
staticType: void Function()
''');
}
test_importPrefix_topLevelGetter() async {
newFile('$testPackageLibPath/a.dart', r'''
int get foo => 0;
''');
await assertNoErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.foo;
}
''');
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: foo
staticElement: package:test/a.dart::@getter::foo
staticType: int
staticElement: package:test/a.dart::@getter::foo
staticType: int
''');
}
test_importPrefix_topLevelSetter() async {
newFile('$testPackageLibPath/a.dart', r'''
set foo(int _) {}
''');
await assertErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.foo;
}
''', [
error(CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME, 48, 3),
]);
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: foo
staticElement: <null>
staticType: dynamic
staticElement: <null>
staticType: dynamic
''');
}
test_importPrefix_topLevelVariable() async {
newFile('$testPackageLibPath/a.dart', r'''
final foo = 0;
''');
await assertNoErrorsInCode('''
import 'a.dart' as prefix;
void f() {
prefix.foo;
}
''');
final node = findNode.prefixed('prefix.');
assertResolvedNodeText(node, r'''
PrefixedIdentifier
prefix: SimpleIdentifier
token: prefix
staticElement: self::@prefix::prefix
staticType: null
period: .
identifier: SimpleIdentifier
token: foo
staticElement: package:test/a.dart::@getter::foo
staticType: int
staticElement: package:test/a.dart::@getter::foo
staticType: int
''');
}
test_read_typedef_interfaceType() async {
newFile('$testPackageLibPath/a.dart', r'''
typedef A = List<int>;
@@ -39,6 +39,178 @@ int Function() foo() {
assertType(identifier, 'A?');
}
test_inClass_superQualifier_identifier_getter() async {
await assertNoErrorsInCode('''
class A {
int get foo => 0;
}
class B extends A {
int get foo => 0;
void f() {
super.foo;
}
}
''');
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: SuperExpression
superKeyword: super
staticType: B
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: self::@class::A::@getter::foo
staticType: int
staticType: int
''');
}
test_inClass_superQualifier_identifier_method() async {
await assertNoErrorsInCode('''
class A {
void foo(int _) {}
}
class B extends A {
void foo(int _) {}
void f() {
super.foo;
}
}
''');
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: SuperExpression
superKeyword: super
staticType: B
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: self::@class::A::@method::foo
staticType: void Function(int)
staticType: void Function(int)
''');
}
test_inClass_superQualifier_identifier_setter() async {
await assertErrorsInCode('''
class A {
set foo(int _) {}
}
class B extends A {
set foo(int _) {}
void f() {
super.foo;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 97, 3),
]);
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: SuperExpression
superKeyword: super
staticType: B
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: <null>
staticType: dynamic
staticType: dynamic
''');
}
test_inClass_thisExpression_identifier_getter() async {
await assertNoErrorsInCode('''
class A {
int get foo => 0;
void f() {
this.foo;
}
}
''');
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ThisExpression
thisKeyword: this
staticType: A
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: self::@class::A::@getter::foo
staticType: int
staticType: int
''');
}
test_inClass_thisExpression_identifier_method() async {
await assertNoErrorsInCode('''
class A {
void foo(int _) {}
void f() {
this.foo;
}
}
''');
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: ThisExpression
thisKeyword: this
staticType: A
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: self::@class::A::@method::foo
staticType: void Function(int)
staticType: void Function(int)
''');
}
test_inClass_thisExpression_identifier_setter() async {
await assertErrorsInCode('''
class A {
set foo(int _) {}
void f() {
super.foo;
}
}
''', [
error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 54, 3),
]);
final node = findNode.propertyAccess('foo;');
assertResolvedNodeText(node, r'''
PropertyAccess
target: SuperExpression
superKeyword: super
staticType: A
operator: .
propertyName: SimpleIdentifier
token: foo
staticElement: <null>
staticType: dynamic
staticType: dynamic
''');
}
test_nullShorting_cascade() async {
await assertNoErrorsInCode(r'''
class A {
@@ -453,29 +453,6 @@ mixin ResolutionTest implements ResourceProviderMixin {
expect(node.staticType, isNull);
}
/// TODO(scheglov) Remove [disableElementCheck]
void assertUnresolvedPropertyAccess(
PropertyAccess node, {
bool disableElementCheck = false,
}) {
if (!disableElementCheck) {
assertElementNull(node);
}
assertTypeNull(node);
assertUnresolvedSimpleIdentifier(node.propertyName);
}
/// TODO(scheglov) Remove [disableElementCheck]
void assertUnresolvedSimpleIdentifier(
SimpleIdentifier node, {
bool disableElementCheck = false,
}) {
if (!disableElementCheck) {
assertElementNull(node);
}
assertTypeNull(node);
}
/// TODO(scheglov) Remove `?` from [declaration].
Matcher elementMatcher(
Element? declaration, {