blob: e9b5f0439fa661e313ef8d400d5b8f59f53bdf74 [file] [log] [blame]
// Copyright (c) 2018, 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/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../generated/elements_types_mixin.dart';
import '../../../utils.dart';
import '../resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisDriverResolutionTest);
});
}
final isDynamicType = TypeMatcher<DynamicTypeImpl>();
final isNeverType = TypeMatcher<NeverTypeImpl>();
final isVoidType = TypeMatcher<VoidTypeImpl>();
/// Integration tests for resolution.
@reflectiveTest
class AnalysisDriverResolutionTest extends PubPackageResolutionTest
with ElementsTypesMixin {
void assertDeclaredVariableType(SimpleIdentifier node, String expected) {
var element = node.staticElement as VariableElement;
assertType(element.type, expected);
}
/// Test that [argumentList] has exactly two type items `int` and `double`.
void assertTypeArguments(
TypeArgumentList argumentList, List<InterfaceType> expectedTypes) {
expect(argumentList.arguments, hasLength(expectedTypes.length));
for (int i = 0; i < expectedTypes.length; i++) {
_assertNamedTypeSimple(argumentList.arguments[i], expectedTypes[i]);
}
}
void assertUnresolvedInvokeType(DartType invokeType) {
expect(invokeType, isDynamicType);
}
/// Creates a function that checks that an expression is a reference to a top
/// level variable with the given [name].
void Function(Expression) checkTopVarRef(String name) {
return (Expression e) {
TopLevelVariableElement variable = _getTopLevelVariable(result, name);
SimpleIdentifier node = e as SimpleIdentifier;
expect(node.staticElement, same(variable.getter));
expect(node.staticType, variable.type);
};
}
/// Creates a function that checks that an expression is a named argument
/// that references a top level variable with the given [name], where the
/// name of the named argument is undefined.
void Function(Expression) checkTopVarUndefinedNamedRef(String name) {
return (Expression e) {
TopLevelVariableElement variable = _getTopLevelVariable(result, name);
NamedExpression named = e as NamedExpression;
expect(named.staticType, variable.type);
SimpleIdentifier nameIdentifier = named.name.label;
expect(nameIdentifier.staticElement, isNull);
expect(nameIdentifier.staticType, isNull);
var expression = named.expression as SimpleIdentifier;
expect(expression.staticElement, same(variable.getter));
expect(expression.staticType, variable.type);
};
}
test_adjacentStrings() async {
String content = r'''
void main() {
'aaa' 'bbb' 'ccc';
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var expression = statement.expression as AdjacentStrings;
expect(expression.staticType, typeProvider.stringType);
expect(expression.strings, hasLength(3));
StringLiteral literal_1 = expression.strings[0];
expect(literal_1.staticType, typeProvider.stringType);
StringLiteral literal_2 = expression.strings[1];
expect(literal_2.staticType, typeProvider.stringType);
StringLiteral literal_3 = expression.strings[2];
expect(literal_3.staticType, typeProvider.stringType);
}
test_annotation() async {
String content = r'''
const myAnnotation = 1;
@myAnnotation
class C {
@myAnnotation
int field1 = 2, field2 = 3;
@myAnnotation
C() {}
@myAnnotation
void method() {}
}
@myAnnotation
int topLevelVariable1 = 4, topLevelVariable2 = 5;
@myAnnotation
void topLevelFunction() {}
''';
addTestFile(content);
await resolveTestFile();
var myDeclaration =
result.unit.declarations[0] as TopLevelVariableDeclaration;
var myVariable = myDeclaration.variables.variables[0];
var myElement = myVariable.declaredElement as TopLevelVariableElement;
void assertMyAnnotation(AnnotatedNode node) {
Annotation annotation = node.metadata[0];
expect(annotation.element, same(myElement.getter));
var identifier_1 = annotation.name as SimpleIdentifier;
expect(identifier_1.staticElement, same(myElement.getter));
expect(identifier_1.staticType, isNull);
}
{
var classNode = result.unit.declarations[1] as ClassDeclaration;
assertMyAnnotation(classNode);
{
var node = classNode.members[0] as FieldDeclaration;
assertMyAnnotation(node);
}
{
var node = classNode.members[1] as ConstructorDeclaration;
assertMyAnnotation(node);
}
{
var node = classNode.members[2] as MethodDeclaration;
assertMyAnnotation(node);
}
}
{
var node = result.unit.declarations[2] as TopLevelVariableDeclaration;
assertMyAnnotation(node);
}
{
var node = result.unit.declarations[3] as FunctionDeclaration;
assertMyAnnotation(node);
}
}
test_annotation_onDirective_export() async {
addTestFile(r'''
@a
export 'dart:math';
const a = 1;
''');
await resolveTestFile();
var directive = findNode.export('dart:math');
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
var aRef = annotation.name as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_import() async {
addTestFile(r'''
@a
import 'dart:math';
const a = 1;
''');
await resolveTestFile();
var directive = findNode.import('dart:math');
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
var aRef = annotation.name as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_library() async {
addTestFile(r'''
@a
library test;
const a = 1;
''');
await resolveTestFile();
var directive = findNode.libraryDirective;
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
var aRef = annotation.name as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_part() async {
newFile('$testPackageLibPath/a.dart', r'''
part of 'test.dart';
''');
addTestFile(r'''
@a
part 'a.dart';
const a = 1;
''');
await resolveTestFile();
var directive = findNode.part('a.dart');
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
var aRef = annotation.name as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_partOf() async {
final a = newFile('$testPackageLibPath/a.dart', r'''
part 'test.dart';
''');
addTestFile(r'''
@a
part of 'a.dart';
const a = 1;
''');
// Make sure that the part knows its library.
contextFor(a).currentSession.getParsedUnit(a.path);
await resolveTestFile();
var directive = findNode.partOf('a.dart');
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
var aRef = annotation.name as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onFormalParameter_redirectingFactory() async {
addTestFile(r'''
class C {
factory C(@a @b x, y, {@c z}) = C.named;
C.named(int p);
}
const a = 1;
const b = 2;
const c = 2;
''');
await resolveTestFile();
void assertTopGetAnnotation(Annotation annotation, String name) {
var getter = findElement.topGet(name);
expect(annotation.element, getter);
var ref = annotation.name as SimpleIdentifier;
assertElement(ref, getter);
assertTypeNull(ref);
}
{
var parameter = findNode.simpleParameter('x, ');
expect(parameter.metadata, hasLength(2));
assertTopGetAnnotation(parameter.metadata[0], 'a');
assertTopGetAnnotation(parameter.metadata[1], 'b');
}
{
var parameter = findNode.simpleParameter('z}');
expect(parameter.metadata, hasLength(1));
assertTopGetAnnotation(parameter.metadata[0], 'c');
}
}
test_annotation_onVariableList_constructor() async {
String content = r'''
class C {
final Object x;
const C(this.x);
}
main() {
@C(C(42))
var foo = null;
}
''';
addTestFile(content);
await resolveTestFile();
var c = result.unit.declarations[0] as ClassDeclaration;
var constructor = c.members[1] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
var main = result.unit.declarations[1] as FunctionDeclaration;
var statement = (main.functionExpression.body as BlockFunctionBody)
.block
.statements[0] as VariableDeclarationStatement;
Annotation annotation = statement.variables.metadata[0];
expect(annotation.element, same(element));
var identifier_1 = annotation.name as SimpleIdentifier;
expect(identifier_1.staticElement, same(c.declaredElement));
}
test_annotation_onVariableList_topLevelVariable() async {
String content = r'''
const myAnnotation = 1;
class C {
void method() {
@myAnnotation
int var1 = 4, var2 = 5;
}
}
''';
addTestFile(content);
await resolveTestFile();
var myDeclaration =
result.unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration myVariable = myDeclaration.variables.variables[0];
var myElement = myVariable.declaredElement as TopLevelVariableElement;
var classNode = result.unit.declarations[1] as ClassDeclaration;
var node = classNode.members[0] as MethodDeclaration;
var statement = (node.body as BlockFunctionBody).block.statements[0]
as VariableDeclarationStatement;
Annotation annotation = statement.variables.metadata[0];
expect(annotation.element, same(myElement.getter));
var identifier_1 = annotation.name as SimpleIdentifier;
expect(identifier_1.staticElement, same(myElement.getter));
assertTypeNull(identifier_1);
}
test_annotation_prefixed_classField() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {
static const a = 1;
}
''');
addTestFile(r'''
import 'a.dart' as p;
@p.A.a
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final aImport = unit.declaredElement!.library.libraryImports[0];
PrefixElement aPrefix = aImport.prefix!.element;
LibraryElement aLibrary = aImport.importedLibrary!;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getClass('A')!;
var aGetter = aClass.getField('a')!.getter;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(aGetter));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aPrefix));
expect(prefixed.prefix.staticType, isNull);
expect(prefixed.identifier.staticElement, same(aClass));
expect(prefixed.prefix.staticType, isNull);
expect(annotation.constructorName!.staticElement, aGetter);
assertTypeNull(annotation.constructorName!);
expect(annotation.arguments, isNull);
}
test_annotation_prefixed_constructor() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {
const A(int a, {int b});
}
''');
addTestFile(r'''
import 'a.dart' as p;
@p.A(1, b: 2)
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final aImport = unit.declaredElement!.library.libraryImports[0];
PrefixElement aPrefix = aImport.prefix!.element;
LibraryElement aLibrary = aImport.importedLibrary!;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getClass('A')!;
ConstructorElement constructor = aClass.unnamedConstructor!;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aPrefix));
expect(prefixed.prefix.staticType, isNull);
expect(prefixed.identifier.staticElement, same(aClass));
expect(prefixed.prefix.staticType, isNull);
expect(annotation.constructorName, isNull);
var arguments = annotation.arguments!.arguments;
var parameters = constructor.parameters;
_assertArgumentToParameter(arguments[0], parameters[0]);
_assertArgumentToParameter(arguments[1], parameters[1]);
}
test_annotation_prefixed_constructor_named() async {
newFile('$testPackageLibPath/a.dart', r'''
class A {
const A.named(int a, {int b});
}
''');
addTestFile(r'''
import 'a.dart' as p;
@p.A.named(1, b: 2)
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final aImport = unit.declaredElement!.library.libraryImports[0];
PrefixElement aPrefix = aImport.prefix!.element;
LibraryElement aLibrary = aImport.importedLibrary!;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getClass('A')!;
ConstructorElement constructor = aClass.getNamedConstructor('named')!;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aPrefix));
expect(prefixed.prefix.staticType, isNull);
expect(prefixed.identifier.staticElement, same(aClass));
expect(prefixed.prefix.staticType, isNull);
var constructorName = annotation.constructorName as SimpleIdentifier;
expect(constructorName.staticElement, same(constructor));
assertTypeNull(constructorName);
var arguments = annotation.arguments!.arguments;
var parameters = constructor.parameters;
_assertArgumentToParameter(arguments[0], parameters[0]);
_assertArgumentToParameter(arguments[1], parameters[1]);
}
test_annotation_prefixed_topLevelVariable() async {
newFile('$testPackageLibPath/a.dart', r'''
const topAnnotation = 1;
''');
addTestFile(r'''
import 'a.dart' as p;
@p.topAnnotation
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final aImport = unit.declaredElement!.library.libraryImports[0];
PrefixElement aPrefix = aImport.prefix!.element;
LibraryElement aLibrary = aImport.importedLibrary!;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
var topAnnotation = aUnitElement.topLevelVariables[0].getter;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(topAnnotation));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aPrefix));
expect(prefixed.prefix.staticType, isNull);
expect(prefixed.identifier.staticElement, same(topAnnotation));
expect(prefixed.prefix.staticType, isNull);
expect(annotation.constructorName, isNull);
expect(annotation.arguments, isNull);
}
test_annotation_unprefixed_classField() async {
addTestFile(r'''
@A.a
main() {}
class A {
static const a = 1;
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getClass('A')!;
var aGetter = aClass.getField('a')!.getter;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(aGetter));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aClass));
assertTypeNull(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(aGetter));
assertTypeNull(prefixed.identifier);
expect(annotation.constructorName, isNull);
expect(annotation.arguments, isNull);
}
test_annotation_unprefixed_constructor() async {
addTestFile(r'''
@A(1, b: 2)
main() {}
class A {
const A(int a, {int b});
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getClass('A')!;
ConstructorElement constructor = aClass.unnamedConstructor!;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
var name = annotation.name as SimpleIdentifier;
expect(name.staticElement, same(aClass));
expect(annotation.constructorName, isNull);
var arguments = annotation.arguments!.arguments;
var parameters = constructor.parameters;
_assertArgumentToParameter(arguments[0], parameters[0]);
_assertArgumentToParameter(arguments[1], parameters[1]);
}
test_annotation_unprefixed_constructor_named() async {
addTestFile(r'''
@A.named(1, b: 2)
main() {}
class A {
const A.named(int a, {int b});
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getClass('A')!;
ConstructorElement constructor = aClass.constructors.single;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
var prefixed = annotation.name as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(aClass));
assertTypeNull(prefixed.prefix);
expect(prefixed.identifier.staticElement, same(constructor));
assertTypeNull(prefixed.identifier);
expect(annotation.constructorName, isNull);
var arguments = annotation.arguments!.arguments;
var parameters = constructor.parameters;
_assertArgumentToParameter(arguments[0], parameters[0]);
_assertArgumentToParameter(arguments[1], parameters[1]);
}
test_annotation_unprefixed_constructor_withNestedConstructorInvocation() async {
addTestFile('''
class C {
const C();
}
class D {
final C c;
const D(this.c);
}
@D(const C())
f() {}
''');
await resolveTestFile();
var elementC = AstFinder.getClass(result.unit, 'C').declaredElement!;
var constructorC = elementC.constructors[0];
var elementD = AstFinder.getClass(result.unit, 'D').declaredElement!;
var constructorD = elementD.constructors[0];
var atD = AstFinder.getTopLevelFunction(result.unit, 'f').metadata[0];
var constC = atD.arguments!.arguments[0] as InstanceCreationExpression;
expect(atD.name.staticElement, elementD);
expect(atD.element, constructorD);
expect(constC.staticType, interfaceTypeNone(elementC));
var constructorName = constC.constructorName;
expect(constructorName.staticElement, constructorC);
expect(constructorName.type.type, interfaceTypeNone(elementC));
}
test_annotation_unprefixed_topLevelVariable() async {
String content = r'''
const annotation_1 = 1;
const annotation_2 = 1;
@annotation_1
@annotation_2
void main() {
print(42);
}
''';
addTestFile(content);
await resolveTestFile();
var declaration_1 =
result.unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration variable_1 = declaration_1.variables.variables[0];
var element_1 = variable_1.declaredElement as TopLevelVariableElement;
var declaration_2 =
result.unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration variable_2 = declaration_2.variables.variables[0];
var element_2 = variable_2.declaredElement as TopLevelVariableElement;
var main = result.unit.declarations[2] as FunctionDeclaration;
Annotation annotation_1 = main.metadata[0];
expect(annotation_1.element, same(element_1.getter));
var identifier_1 = annotation_1.name as SimpleIdentifier;
expect(identifier_1.staticElement, same(element_1.getter));
assertTypeNull(identifier_1);
Annotation annotation_2 = main.metadata[1];
expect(annotation_2.element, same(element_2.getter));
var identifier_2 = annotation_2.name as SimpleIdentifier;
expect(identifier_2.staticElement, same(element_2.getter));
assertTypeNull(identifier_2);
}
test_asExpression() async {
await assertNoErrorsInCode(r'''
void main() {
num v = 42;
v as int;
}
''');
List<Statement> statements = _getMainStatements(result);
// num v = 42;
VariableElement vElement;
{
var statement = statements[0] as VariableDeclarationStatement;
vElement = statement.variables.variables[0].declaredElement!;
expect(vElement.type, typeProvider.numType);
}
// v as int;
{
var statement = statements[1] as ExpressionStatement;
var asExpression = statement.expression as AsExpression;
expect(asExpression.staticType, typeProvider.intType);
var target = asExpression.expression as SimpleIdentifier;
expect(target.staticElement, vElement);
expect(target.staticType, typeProvider.numType);
var intName = asExpression.type as NamedType;
expect(intName.name.staticElement, typeProvider.intType.element2);
expect(intName.name.staticType, isNull);
}
}
test_binary_operator_with_synthetic_operands() async {
addTestFile('''
void main() {
var list = *;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_binaryExpression() async {
String content = r'''
main() {
var v = 1 + 2;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as VariableDeclarationStatement;
VariableDeclaration vNode = statement.variables.variables[0];
VariableElement vElement = vNode.declaredElement!;
expect(vElement.type, typeProvider.intType);
var value = vNode.initializer as BinaryExpression;
expect(value.leftOperand.staticType, typeProvider.intType);
expect(value.rightOperand.staticType, typeProvider.intType);
expect(value.staticElement!.name, '+');
expect(value.staticType, typeProvider.intType);
}
test_binaryExpression_gtGtGt() async {
await resolveTestCode('''
class A {
A operator >>>(int amount) => this;
}
f(A a) {
a >>> 3;
}
''');
assertResolvedNodeText(findNode.binary('>>> 3'), r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: a
staticElement: self::@function::f::@parameter::a
staticType: A
operator: >>>
rightOperand: IntegerLiteral
literal: 3
parameter: self::@class::A::@method::>>>::@parameter::amount
staticType: int
staticElement: self::@class::A::@method::>>>
staticInvokeType: A Function(int)
staticType: A
''');
}
test_binaryExpression_ifNull() async {
String content = r'''
int x = 3;
main() {
1.2 ?? x;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as ExpressionStatement;
var binary = statement.expression as BinaryExpression;
expect(binary.operator.type, TokenType.QUESTION_QUESTION);
expect(binary.staticElement, isNull);
expect(binary.staticType, typeProvider.numType);
expect(binary.leftOperand.staticType, typeProvider.doubleType);
expect(binary.rightOperand.staticType, typeProvider.intType);
}
test_binaryExpression_logical() async {
addTestFile(r'''
main() {
true && true;
true || true;
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
{
var statement = statements[0] as ExpressionStatement;
var binaryExpression = statement.expression as BinaryExpression;
expect(binaryExpression.staticElement, isNull);
expect(binaryExpression.staticType, typeProvider.boolType);
}
{
var statement = statements[1] as ExpressionStatement;
var binaryExpression = statement.expression as BinaryExpression;
expect(binaryExpression.staticElement, isNull);
expect(binaryExpression.staticType, typeProvider.boolType);
}
}
test_binaryExpression_notEqual() async {
String content = r'''
main() {
1 != 2;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var expression = statement.expression as BinaryExpression;
expect(expression.operator.type, TokenType.BANG_EQ);
expect(expression.leftOperand.staticType, typeProvider.intType);
expect(expression.rightOperand.staticType, typeProvider.intType);
expect(expression.staticElement!.name, '==');
expect(expression.staticType, typeProvider.boolType);
}
test_cascade_get_with_numeric_getter_name() async {
addTestFile('''
void f(x) {
x..42;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_cascade_method_call_with_synthetic_method_name() async {
addTestFile('''
void f(x) {
x..(42);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_cascadeExpression() async {
String content = r'''
void main() {
new A()..a()..b();
}
class A {
void a() {}
void b() {}
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var expression = statement.expression as CascadeExpression;
expect(expression.target.staticType, isNotNull);
NodeList<Expression> sections = expression.cascadeSections;
var a = sections[0] as MethodInvocation;
expect(a.methodName.staticElement, isNotNull);
expect(a.staticType, isNotNull);
var b = sections[1] as MethodInvocation;
expect(b.methodName.staticElement, isNotNull);
expect(b.staticType, isNotNull);
}
test_closure() async {
addTestFile(r'''
main() {
var items = <int>[1, 2, 3];
items.forEach((item) {
item;
});
items.forEach((item) {
item;
});
}
''');
await resolveTestFile();
var mainDeclaration = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = mainDeclaration.declaredElement as FunctionElement;
var mainBody = mainDeclaration.functionExpression.body as BlockFunctionBody;
List<Statement> mainStatements = mainBody.block.statements;
var itemsStatement = mainStatements[0] as VariableDeclarationStatement;
var itemsElement = itemsStatement.variables.variables[0].declaredElement!;
// First closure.
ParameterElement itemElement1;
{
var forStatement = mainStatements[1] as ExpressionStatement;
var forInvocation = forStatement.expression as MethodInvocation;
var forTarget = forInvocation.target as SimpleIdentifier;
expect(forTarget.staticElement, itemsElement);
var closureTypeStr = 'void Function(int)';
var closure =
forInvocation.argumentList.arguments[0] as FunctionExpression;
var closureElement = closure.declaredElement as FunctionElementImpl;
expect(closureElement.enclosingElement, same(mainElement));
ParameterElement itemElement = closureElement.parameters[0];
itemElement1 = itemElement;
expect(closureElement.returnType, typeProvider.voidType);
assertType(closureElement.type, closureTypeStr);
expect(closure.staticType, same(closureElement.type));
List<FormalParameter> closureParameters = closure.parameters!.parameters;
expect(closureParameters, hasLength(1));
var itemNode = closureParameters[0] as SimpleFormalParameter;
_assertSimpleParameter(itemNode, itemElement,
name: 'item',
offset: 56,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
var closureBody = closure.body as BlockFunctionBody;
List<Statement> closureStatements = closureBody.block.statements;
var itemStatement = closureStatements[0] as ExpressionStatement;
var itemIdentifier = itemStatement.expression as SimpleIdentifier;
expect(itemIdentifier.staticElement, itemElement);
expect(itemIdentifier.staticType, typeProvider.intType);
}
// Second closure, same names, different elements.
{
var forStatement = mainStatements[2] as ExpressionStatement;
var forInvocation = forStatement.expression as MethodInvocation;
var forTarget = forInvocation.target as SimpleIdentifier;
expect(forTarget.staticElement, itemsElement);
var closureTypeStr = 'void Function(int)';
var closure =
forInvocation.argumentList.arguments[0] as FunctionExpression;
var closureElement = closure.declaredElement as FunctionElementImpl;
expect(closureElement.enclosingElement, same(mainElement));
ParameterElement itemElement = closureElement.parameters[0];
expect(itemElement, isNot(same(itemElement1)));
expect(closureElement.returnType, typeProvider.voidType);
assertType(closureElement.type, closureTypeStr);
expect(closure.staticType, same(closureElement.type));
List<FormalParameter> closureParameters = closure.parameters!.parameters;
expect(closureParameters, hasLength(1));
var itemNode = closureParameters[0] as SimpleFormalParameter;
_assertSimpleParameter(itemNode, itemElement,
name: 'item',
offset: 97,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
var closureBody = closure.body as BlockFunctionBody;
List<Statement> closureStatements = closureBody.block.statements;
var itemStatement = closureStatements[0] as ExpressionStatement;
var itemIdentifier = itemStatement.expression as SimpleIdentifier;
expect(itemIdentifier.staticElement, itemElement);
expect(itemIdentifier.staticType, typeProvider.intType);
}
}
test_closure_generic() async {
addTestFile(r'''
main() {
foo(<T>() => new List<T>(4));
}
void foo(List<T> Function<T>() createList) {}
''');
await resolveTestFile();
var closure = findNode.functionExpression('<T>() =>');
assertType(closure, 'List<T> Function<T>()');
var closureElement = closure.declaredElement as FunctionElementImpl;
expect(closureElement.enclosingElement, findElement.function('main'));
assertType(closureElement.returnType, 'List<T>');
expect(closureElement.parameters, isEmpty);
var typeParameters = closureElement.typeParameters;
expect(typeParameters, hasLength(1));
TypeParameterElement tElement = typeParameters[0];
expect(tElement.name, 'T');
expect(tElement.nameOffset, 16);
var creation = findNode.instanceCreation('new List');
assertType(creation, 'List<T>');
var tRef = findNode.simple('T>(4)');
assertElement(tRef, tElement);
}
test_closure_inField() async {
addTestFile(r'''
class C {
var v = (() => 42)();
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
var c = unit.declarations[0] as ClassDeclaration;
var declaration = c.members[0] as FieldDeclaration;
VariableDeclaration field = declaration.fields.variables[0];
var invocation = field.initializer as FunctionExpressionInvocation;
var closure = invocation.function.unParenthesized as FunctionExpression;
var closureElement = closure.declaredElement as FunctionElementImpl;
expect(closureElement, isNotNull);
}
test_closure_inTopLevelVariable() async {
addTestFile(r'''
var v = (() => 42)();
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration variable = declaration.variables.variables[0];
var invocation = variable.initializer as FunctionExpressionInvocation;
var closure = invocation.function.unParenthesized as FunctionExpression;
var closureElement = closure.declaredElement as FunctionElementImpl;
expect(closureElement, isNotNull);
}
test_conditionalExpression() async {
String content = r'''
void main() {
true ? 1 : 2.3;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var expression = statement.expression as ConditionalExpression;
expect(expression.staticType, typeProvider.numType);
expect(expression.condition.staticType, typeProvider.boolType);
expect(expression.thenExpression.staticType, typeProvider.intType);
expect(expression.elseExpression.staticType, typeProvider.doubleType);
}
test_const_constructor_calls_non_const_super() async {
addTestFile('''
class A {
final a;
A(this.a);
}
class B extends A {
const B() : super(5);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_constructor_context() async {
addTestFile(r'''
class C {
C(int p) {
p;
}
}
''');
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
var constructorNode = cNode.members[0] as ConstructorDeclaration;
ParameterElement pElement = constructorNode.declaredElement!.parameters[0];
var constructorBody = constructorNode.body as BlockFunctionBody;
var pStatement = constructorBody.block.statements[0] as ExpressionStatement;
var pIdentifier = pStatement.expression as SimpleIdentifier;
expect(pIdentifier.staticElement, same(pElement));
expect(pIdentifier.staticType, typeProvider.intType);
}
test_constructor_initializer_field() async {
addTestFile(r'''
class C {
int f;
C(int p) : f = p {
f;
}
}
''');
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
FieldElement fElement = cElement.getField('f')!;
var constructorNode = cNode.members[1] as ConstructorDeclaration;
ParameterElement pParameterElement =
constructorNode.declaredElement!.parameters[0];
{
var initializer =
constructorNode.initializers[0] as ConstructorFieldInitializer;
expect(initializer.fieldName.staticElement, same(fElement));
var expression = initializer.expression as SimpleIdentifier;
expect(expression.staticElement, same(pParameterElement));
}
}
test_constructor_initializer_super() async {
addTestFile(r'''
class A {
A(int a);
A.named(int a, {int b});
}
class B extends A {
B.one(int p) : super(p + 1);
B.two(int p) : super.named(p + 1, b: p + 2);
}
''');
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
var bNode = result.unit.declarations[1] as ClassDeclaration;
{
var constructor = bNode.members[0] as ConstructorDeclaration;
var initializer =
constructor.initializers[0] as SuperConstructorInvocation;
expect(initializer.staticElement, same(aElement.unnamedConstructor));
expect(initializer.constructorName, isNull);
}
{
var namedConstructor = aElement.getNamedConstructor('named')!;
var constructor = bNode.members[1] as ConstructorDeclaration;
var initializer =
constructor.initializers[0] as SuperConstructorInvocation;
expect(initializer.staticElement, same(namedConstructor));
var constructorName = initializer.constructorName!;
expect(constructorName.staticElement, same(namedConstructor));
expect(constructorName.staticType, isNull);
List<Expression> arguments = initializer.argumentList.arguments;
_assertArgumentToParameter(arguments[0], namedConstructor.parameters[0]);
_assertArgumentToParameter(arguments[1], namedConstructor.parameters[1]);
}
}
test_constructor_initializer_this() async {
addTestFile(r'''
class C {
C(int a, [int b]);
C.named(int a, {int b});
C.one(int p) : this(1, 2);
C.two(int p) : this.named(3, b: 4);
}
''');
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
{
var unnamedConstructor = cElement.constructors[0];
var constructor = cNode.members[2] as ConstructorDeclaration;
var initializer =
constructor.initializers[0] as RedirectingConstructorInvocation;
expect(initializer.staticElement, same(unnamedConstructor));
expect(initializer.constructorName, isNull);
List<Expression> arguments = initializer.argumentList.arguments;
_assertArgumentToParameter(
arguments[0], unnamedConstructor.parameters[0]);
_assertArgumentToParameter(
arguments[1], unnamedConstructor.parameters[1]);
}
{
var namedConstructor = cElement.constructors[1];
var constructor = cNode.members[3] as ConstructorDeclaration;
var initializer =
constructor.initializers[0] as RedirectingConstructorInvocation;
expect(initializer.staticElement, same(namedConstructor));
var constructorName = initializer.constructorName!;
expect(constructorName.staticElement, same(namedConstructor));
expect(constructorName.staticType, isNull);
List<Expression> arguments = initializer.argumentList.arguments;
_assertArgumentToParameter(arguments[0], namedConstructor.parameters[0]);
_assertArgumentToParameter(arguments[1], namedConstructor.parameters[1]);
}
}
test_constructor_redirected() async {
addTestFile(r'''
class A implements B {
A(int a);
A.named(double a);
}
class B {
factory B.one(int b) = A;
factory B.two(double b) = A.named;
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
var bNode = result.unit.declarations[1] as ClassDeclaration;
{
ConstructorElement aUnnamed = aElement.constructors[0];
var constructor = bNode.members[0] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
expect(element.redirectedConstructor, same(aUnnamed));
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(aUnnamed));
NamedType namedType = constructorName.type;
expect(namedType.type, interfaceTypeNone(aElement));
var identifier = namedType.name as SimpleIdentifier;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name, isNull);
}
{
ConstructorElement aNamed = aElement.constructors[1];
var constructor = bNode.members[1] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
expect(element.redirectedConstructor, same(aNamed));
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(aNamed));
var namedType = constructorName.type;
expect(namedType.type, interfaceTypeNone(aElement));
var identifier = namedType.name as SimpleIdentifier;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name!.staticElement, aNamed);
expect(constructorName.name!.staticType, isNull);
}
}
test_constructor_redirected_generic() async {
addTestFile(r'''
class A<T> implements B<T> {
A(int a);
A.named(double a);
}
class B<U> {
factory B.one(int b) = A<U>;
factory B.two(double b) = A<U>.named;
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
var bNode = result.unit.declarations[1] as ClassDeclaration;
TypeParameterType uType =
typeParameterTypeNone(bNode.declaredElement!.typeParameters[0]);
InterfaceType auType = aElement.instantiate(
typeArguments: [uType],
nullabilitySuffix: NullabilitySuffix.none,
);
{
ConstructorElement expectedElement = aElement.constructors[0];
var constructor = bNode.members[0] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
var actualMember = element.redirectedConstructor!;
assertMember(actualMember, expectedElement, {'T': 'U'});
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(actualMember));
NamedType namedType = constructorName.type;
expect(namedType.type, auType);
var identifier = namedType.name as SimpleIdentifier;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name, isNull);
}
{
ConstructorElement expectedElement = aElement.constructors[1];
var constructor = bNode.members[1] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
var actualMember = element.redirectedConstructor!;
assertMember(actualMember, expectedElement, {'T': 'U'});
var constructorName = constructor.redirectedConstructor!;
expect(constructorName.staticElement, same(actualMember));
NamedType namedType = constructorName.type;
expect(namedType.type, auType);
var identifier = namedType.name as SimpleIdentifier;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name!.staticElement, same(actualMember));
expect(constructorName.name!.staticType, isNull);
}
}
test_deferredImport_loadLibrary_invocation() async {
newFile('$testPackageLibPath/a.dart', '');
addTestFile(r'''
import 'a.dart' deferred as a;
main() {
a.loadLibrary();
}
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var invocation = findNode.methodInvocation('loadLibrary');
assertType(invocation, 'Future<dynamic>');
assertInvokeType(invocation, 'Future<dynamic> Function()');
var target = invocation.target as SimpleIdentifier;
assertElement(target, import.prefix?.element);
assertType(target, null);
var name = invocation.methodName;
assertElement(name, import.importedLibrary!.loadLibraryFunction);
assertType(name, 'Future<dynamic> Function()');
}
test_deferredImport_loadLibrary_invocation_argument() async {
newFile('$testPackageLibPath/a.dart', '');
addTestFile(r'''
import 'a.dart' deferred as a;
var b = 1;
var c = 2;
main() {
a.loadLibrary(b, c);
}
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var invocation = findNode.methodInvocation('loadLibrary');
assertType(invocation, 'Future<dynamic>');
assertInvokeType(invocation, 'Future<dynamic> Function()');
var target = invocation.target as SimpleIdentifier;
assertElement(target, import.prefix?.element);
assertType(target, null);
var name = invocation.methodName;
assertElement(name, import.importedLibrary!.loadLibraryFunction);
assertType(name, 'Future<dynamic> Function()');
var bRef = invocation.argumentList.arguments[0];
assertElement(bRef, findElement.topGet('b'));
assertType(bRef, 'int');
var cRef = invocation.argumentList.arguments[1];
assertElement(cRef, findElement.topGet('c'));
assertType(cRef, 'int');
}
test_deferredImport_loadLibrary_tearOff() async {
newFile('$testPackageLibPath/a.dart', '');
addTestFile(r'''
import 'a.dart' deferred as a;
main() {
a.loadLibrary;
}
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var prefixed = findNode.prefixed('a.loadLibrary');
assertType(prefixed, 'Future<dynamic> Function()');
var prefix = prefixed.prefix;
assertElement(prefix, import.prefix?.element);
assertType(prefix, null);
var identifier = prefixed.identifier;
assertElement(identifier, import.importedLibrary!.loadLibraryFunction);
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 {}
int myVar;
int get myGetter => 0;
int set mySetter(_) {}
''');
addTestFile(r'''
export 'a.dart' show MyClass, myVar, myGetter, mySetter, Unresolved;
''');
await resolveTestFile();
var export = findElement.export('package:test/a.dart');
var namespace = export.exportedLibrary!.exportNamespace;
{
var ref = findNode.simple('MyClass');
assertElement(ref, namespace.get('MyClass'));
assertType(ref, null);
}
{
var ref = findNode.simple('myVar');
var getter = namespace.get('myVar') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
var getter = namespace.get('myGetter') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
var getter = namespace.get('mySetter=') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('Unresolved');
assertElementNull(ref);
assertType(ref, null);
}
}
test_directive_import_hide() async {
newFile('$testPackageLibPath/a.dart', r'''
class MyClass {}
int myVar;
int get myGetter => 0;
int set mySetter(_) {}
''');
addTestFile(r'''
import 'a.dart' hide MyClass, myVar, myGetter, mySetter, Unresolved;
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var namespace = import.importedLibrary!.exportNamespace;
{
var ref = findNode.simple('MyClass');
assertElement(ref, namespace.get('MyClass'));
assertType(ref, null);
}
{
var ref = findNode.simple('myVar');
var getter = namespace.get('myVar') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
var getter = namespace.get('myGetter') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
var getter = namespace.get('mySetter=') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('Unresolved');
assertElementNull(ref);
assertType(ref, null);
}
}
test_directive_import_show() async {
newFile('$testPackageLibPath/a.dart', r'''
class MyClass {}
int myVar;
int get myGetter => 0;
int set mySetter(_) {}
''');
addTestFile(r'''
import 'a.dart' show MyClass, myVar, myGetter, mySetter, Unresolved;
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
var namespace = import.importedLibrary!.exportNamespace;
{
var ref = findNode.simple('MyClass');
assertElement(ref, namespace.get('MyClass'));
assertType(ref, null);
}
{
var ref = findNode.simple('myVar');
var getter = namespace.get('myVar') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
var getter = namespace.get('myGetter') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
var getter = namespace.get('mySetter=') as PropertyAccessorElement;
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('Unresolved');
assertElementNull(ref);
assertType(ref, null);
}
}
test_enum_toString() async {
addTestFile(r'''
enum MyEnum { A, B, C }
main(MyEnum e) {
e.toString();
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
assertInvokeType(invocation, 'String Function()');
var methodElement = invocation.methodName.staticElement as MethodElement;
expect(methodElement.name, 'toString');
expect(methodElement.enclosingElement, same(objectElement));
}
test_error_unresolvedTypeAnnotation() async {
String content = r'''
main() {
Foo<int> v = null;
}
''';
addTestFile(content);
await resolveTestFile();
var statements = _getMainStatements(result);
var statement = statements[0] as VariableDeclarationStatement;
var namedType = statement.variables.type as NamedType;
expect(namedType.type, isDynamicType);
expect(namedType.typeArguments!.arguments[0].type, typeProvider.intType);
VariableDeclaration vNode = statement.variables.variables[0];
expect(vNode.declaredElement!.type, isDynamicType);
}
test_field_context() async {
addTestFile(r'''
class C<T> {
var f = <T>[];
}
''');
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
var tElement = cNode.declaredElement!.typeParameters[0];
var fDeclaration = cNode.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
var fElement = fNode.declaredElement as FieldElement;
expect(
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 {
A(String p(int a));
}
''');
await resolveTestFile();
var clazz = result.unit.declarations[0] as ClassDeclaration;
var constructor = clazz.members[0] as ConstructorDeclaration;
List<FormalParameter> parameters = constructor.parameters.parameters;
var p = parameters[0] as FunctionTypedFormalParameter;
expect(p.declaredElement, same(constructor.declaredElement!.parameters[0]));
{
var type = (p.declaredElement as ParameterElement).type as FunctionType;
expect(type.returnType, typeProvider.stringType);
expect(type.parameters, hasLength(1));
expect(type.parameters[0].type, typeProvider.intType);
}
_assertNamedTypeSimple(p.returnType!, typeProvider.stringType);
{
var a = p.parameters.parameters[0] as SimpleFormalParameter;
_assertNamedTypeSimple(a.type!, typeProvider.intType);
}
}
test_formalParameter_functionTyped_fieldFormal_typed() async {
// TODO(scheglov) Add "untyped" version with precise type in field.
addTestFile(r'''
class A {
Function f;
A(String this.f(int a));
}
''');
await resolveTestFile();
var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
var fElement = fNode.declaredElement as FieldElement;
var constructor = clazz.members[1] as ConstructorDeclaration;
var pElement = constructor.declaredElement!.parameters[0]
as FieldFormalParameterElement;
expect(pElement.field, same(fElement));
List<FormalParameter> parameters = constructor.parameters.parameters;
var p = parameters[0] as FieldFormalParameter;
expect(p.declaredElement, same(pElement));
_assertNamedTypeSimple(p.type!, typeProvider.stringType);
{
var a = p.parameters!.parameters[0] as SimpleFormalParameter;
_assertNamedTypeSimple(a.type!, typeProvider.intType);
}
}
test_formalParameter_simple_fieldFormal() async {
addTestFile(r'''
class A {
int f;
A(this.f);
}
''');
await resolveTestFile();
var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
var fElement = fNode.declaredElement as FieldElement;
var constructor = clazz.members[1] as ConstructorDeclaration;
List<FormalParameter> parameters = constructor.parameters.parameters;
var parameterElement = constructor.declaredElement!.parameters[0]
as FieldFormalParameterElement;
expect(parameterElement.field, same(fElement));
var parameterNode = parameters[0] as FieldFormalParameter;
expect(parameterNode.type, isNull);
expect(parameterNode.declaredElement, same(parameterElement));
}
test_formalParameter_simple_fieldFormal_typed() async {
addTestFile(r'''
class A {
int f;
A(int this.f);
}
''');
await resolveTestFile();
var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
var fElement = fNode.declaredElement as FieldElement;
var constructor = clazz.members[1] as ConstructorDeclaration;
List<FormalParameter> parameters = constructor.parameters.parameters;
var parameterElement = constructor.declaredElement!.parameters[0]
as FieldFormalParameterElement;
expect(parameterElement.field, same(fElement));
var parameterNode = parameters[0] as FieldFormalParameter;
_assertNamedTypeSimple(parameterNode.type!, typeProvider.intType);
expect(parameterNode.declaredElement, same(parameterElement));
}
test_forwardingStub_class() async {
addTestFile(r'''
class A<T> {
void m(T t) {}
}
class B extends A<int> {}
main(B b) {
b.m(1);
}
''');
await resolveTestFile();
// var aNode = result.unit!.declarations[0] as ClassDeclaration;
// ClassElement eElement = aNode.declaredElement!;
// MethodElement mElement = eElement.getMethod('m');
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
assertInvokeType(invocation, 'void Function(int)');
// TODO(scheglov) Check for MethodElement
// expect(invocation.methodName.staticElement, same(mElement));
}
test_function_call_with_synthetic_arguments() async {
addTestFile('''
void f(x) {}
class C {
m() {
f(,);
}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_functionExpressionInvocation() async {
addTestFile(r'''
typedef Foo<S> = S Function<T>(T x);
void main(f) {
(f as Foo<int>)<String>('hello');
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as FunctionExpressionInvocation;
expect(invocation.staticElement, isNull);
assertInvokeType(invocation, 'int Function(String)');
expect(invocation.staticType, typeProvider.intType);
List<TypeAnnotation> typeArguments = invocation.typeArguments!.arguments;
expect(typeArguments, hasLength(1));
_assertNamedTypeSimple(typeArguments[0], typeProvider.stringType);
}
test_functionExpressionInvocation_namedArgument() async {
addTestFile(r'''
int a;
main(f) {
(f)(p: a);
}
''');
await resolveTestFile();
assertTopGetRef('a);', 'a');
}
test_generic_function_type() async {
addTestFile('''
main() {
void Function<T>(T) f;
}
''');
await resolveTestFile();
var fType = findElement.localVar('f').type as FunctionType;
var fTypeTypeParameter = fType.typeFormals[0];
var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
expect(fTypeParameter.element2, same(fTypeTypeParameter));
var tRef = findNode.typeParameter('T>');
var functionTypeNode = tRef.parent!.parent as GenericFunctionType;
var functionType = functionTypeNode.type as FunctionType;
assertElement(tRef, functionType.typeFormals[0]);
}
test_indexExpression() async {
String content = r'''
main() {
var items = <int>[1, 2, 3];
items[0];
}
''';
addTestFile(content);
await resolveTestFile();
InterfaceType intType = typeProvider.intType;
InterfaceType listIntType = typeProvider.listType(intType);
List<Statement> mainStatements = _getMainStatements(result);
VariableElement itemsElement;
{
var statement = mainStatements[0] as VariableDeclarationStatement;
VariableDeclaration itemsNode = statement.variables.variables[0];
itemsElement = itemsNode.declaredElement!;
expect(itemsElement.type, listIntType);
}
var statement = mainStatements[1] as ExpressionStatement;
var indexExpression = statement.expression as IndexExpression;
expect(indexExpression.staticType, intType);
var actualElement = indexExpression.staticElement as MethodMember;
var expectedElement = listIntType.getMethod('[]') as MethodMember;
expect(actualElement.name, '[]');
expect(actualElement.declaration, same(expectedElement.declaration));
expect(actualElement.returnType, intType);
expect(actualElement.parameters[0].type, intType);
}
test_instanceCreation_factory() async {
String content = r'''
class C {
factory C() => throw 0;
factory C.named() => throw 0;
}
var a = new C();
var b = new C.named();
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
{
var aDeclaration = unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration aNode = aDeclaration.variables.variables[0];
var value = aNode.initializer as InstanceCreationExpression;
expect(value.staticType, interfaceTypeNone(cElement));
var constructorName = value.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
{
var bDeclaration = unit.declarations[2] as TopLevelVariableDeclaration;
VariableDeclaration bNode = bDeclaration.variables.variables[0];
var value = bNode.initializer as InstanceCreationExpression;
expect(value.staticType, interfaceTypeNone(cElement));
var constructorName = value.constructorName;
expect(constructorName.staticElement, namedConstructor);
expect(constructorName.name!.staticType, isNull);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
}
test_instanceCreation_namedArgument() async {
addTestFile(r'''
class X {
X(int a, {bool b, double c});
}
var v = new X(1, b: true, c: 3.0);
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
var xNode = unit.declarations[0] as ClassDeclaration;
ClassElement xElement = xNode.declaredElement!;
ConstructorElement constructorElement = xElement.constructors[0];
var vDeclaration = unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration vNode = vDeclaration.variables.variables[0];
var creation = vNode.initializer as InstanceCreationExpression;
List<Expression> arguments = creation.argumentList.arguments;
expect(creation.staticType, interfaceTypeNone(xElement));
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, constructorElement);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
expect(typeIdentifier.staticElement, xElement);
expect(typeIdentifier.staticType, isNull);
_assertArgumentToParameter(arguments[0], constructorElement.parameters[0]);
_assertArgumentToParameter(arguments[1], constructorElement.parameters[1]);
_assertArgumentToParameter(arguments[2], constructorElement.parameters[2]);
}
test_instanceCreation_noTypeArguments() async {
String content = r'''
class C {
C(int p);
C.named(int p);
}
var a = new C(1);
var b = new C.named(2);
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
{
var aDeclaration = unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration aNode = aDeclaration.variables.variables[0];
var value = aNode.initializer as InstanceCreationExpression;
expect(value.staticType, interfaceTypeNone(cElement));
var constructorName = value.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
Identifier typeIdentifier = namedType.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
Expression argument = value.argumentList.arguments[0];
_assertArgumentToParameter(argument, defaultConstructor.parameters[0]);
}
{
var bDeclaration = unit.declarations[2] as TopLevelVariableDeclaration;
VariableDeclaration bNode = bDeclaration.variables.variables[0];
var value = bNode.initializer as InstanceCreationExpression;
expect(value.staticType, interfaceTypeNone(cElement));
var constructorName = value.constructorName;
expect(constructorName.staticElement, namedConstructor);
expect(constructorName.name!.staticElement, namedConstructor);
expect(constructorName.name!.staticType, isNull);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
Expression argument = value.argumentList.arguments[0];
_assertArgumentToParameter(argument, namedConstructor.parameters[0]);
}
}
test_instanceCreation_prefixed() async {
newFile('$testPackageLibPath/a.dart', r'''
class C<T> {
C(T p);
C.named(T p);
}
''');
addTestFile(r'''
import 'a.dart' as p;
main() {
new p.C(0);
new p.C.named(1.2);
new p.C<bool>.named(false);
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final aImport = unit.declaredElement!.library.libraryImports[0];
LibraryElement aLibrary = aImport.importedLibrary!;
ClassElement cElement = aLibrary.getClass('C')!;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
var statements = _getMainStatements(result);
{
var cTypeInt = cElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeInt);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
defaultConstructor,
substitution: {'T': 'int'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as PrefixedIdentifier;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix?.element));
expect(typePrefix.staticType, isNull);
expect(typeIdentifier.identifier.staticElement, same(cElement));
}
{
var cTypeDouble = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[1] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeDouble);
var constructorName = creation.constructorName;
assertElement(
constructorName.name!.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'dynamic'},
),
);
expect(constructorName.name!.staticType, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'double'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as PrefixedIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix?.element));
expect(typePrefix.staticType, isNull);
expect(typeIdentifier.identifier.staticElement, same(cElement));
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[2] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
assertElement(
constructorName.name!.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'bool'},
),
);
expect(constructorName.name!.staticType, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'bool'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
var typeIdentifier = namedType.name as PrefixedIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix?.element));
expect(typePrefix.staticType, isNull);
expect(typeIdentifier.identifier.staticElement, same(cElement));
}
}
test_instanceCreation_unprefixed() async {
addTestFile(r'''
main() {
new C(0);
new C<bool>(false);
new C.named(1.2);
new C<bool>.named(false);
}
class C<T> {
C(T p);
C.named(T p);
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement cElement = unitElement.getClass('C')!;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
var statements = _getMainStatements(result);
{
var cTypeInt = cElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeInt);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
defaultConstructor,
substitution: {'T': 'int'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[1] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
defaultConstructor,
substitution: {'T': 'bool'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeDouble = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[2] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeDouble);
var constructorName = creation.constructorName;
assertElement(
constructorName.name!.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'dynamic'},
),
);
expect(constructorName.name!.staticType, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'double'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.none,
);
var statement = statements[3] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
assertElement(
constructorName.name!.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'bool'},
),
);
expect(constructorName.name!.staticType, isNull);
assertElement(
constructorName.staticElement,
elementMatcher(
namedConstructor,
substitution: {'T': 'bool'},
),
);
NamedType namedType = constructorName.type;
expect(namedType.typeArguments!.arguments, hasLength(1));
_assertNamedTypeSimple(
namedType.typeArguments!.arguments[0], typeProvider.boolType);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
}
test_instanceCreation_withTypeArguments() async {
addTestFile(r'''
class C<K, V> {
C(K k, V v);
C.named(K k, V v);
}
var a = new C<int, double>(1, 2.3);
var b = new C<num, String>.named(4, 'five');
''');
await resolveTestFile();
var cElement = findElement.class_('C');
var defaultConstructor = cElement.unnamedConstructor!;
var namedConstructor = cElement.getNamedConstructor('named')!;
{
var creation = findNode.instanceCreation('new C<int, double>(1, 2.3);');
assertMember(creation, defaultConstructor, {'K': 'int', 'V': 'double'});
assertType(creation, 'C<int, double>');
var namedType = creation.constructorName.type;
assertNamedType(namedType, cElement, 'C<int, double>');
var typeArguments = namedType.typeArguments!.arguments;
assertNamedType(typeArguments[0] as NamedType, intElement, 'int');
assertNamedType(typeArguments[1] as NamedType, doubleElement, 'double');
expect(creation.constructorName.name, isNull);
Expression argument = creation.argumentList.arguments[0];
_assertArgumentToParameter2(argument, 'int');
}
{
var creation = findNode.instanceCreation('new C<num, String>.named');
assertMember(creation, namedConstructor, {'K': 'num', 'V': 'String'});
assertType(creation, 'C<num, String>');
var namedType = creation.constructorName.type;
assertNamedType(namedType, cElement, 'C<num, String>');
var typeArguments = namedType.typeArguments!.arguments;
assertNamedType(typeArguments[0] as NamedType, numElement, 'num');
assertNamedType(typeArguments[1] as NamedType, stringElement, 'String');
var constructorName = creation.constructorName.name;
assertMember(
constructorName, namedConstructor, {'K': 'num', 'V': 'String'});
assertType(constructorName, null);
var argument = creation.argumentList.arguments[0];
_assertArgumentToParameter2(argument, 'num');
}
}
test_invalid_annotation_on_variable_declaration() async {
addTestFile(r'''
const a = null;
main() {
int x, @a y;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_invalid_annotation_on_variable_declaration_for() async {
addTestFile(r'''
const a = null;
main() {
for (var @a x = 0;;) {}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
test_invalid_catch_parameters_3() async {
addTestFile(r'''
main() {
try { } catch (x, y, z) { }
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertType(
findNode.catchClauseParameter('x,').declaredElement!.type,
'Object',
);
assertType(
findNode.catchClauseParameter('y,').declaredElement!.type,
'StackTrace',
);
}
test_invalid_catch_parameters_empty() async {
addTestFile(r'''
main() {
try { } catch () { }
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
}
test_invalid_catch_parameters_named_stack() async {
addTestFile(r'''
main() {
try { } catch (e, {s}) { }
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertType(
findNode.catchClauseParameter('e,').declaredElement!.type,
'Object',
);
assertType(
findNode.catchClauseParameter('s}').declaredElement!.type,
'StackTrace',
);
}
test_invalid_catch_parameters_optional_stack() async {
addTestFile(r'''
main() {
try { } catch (e, [s]) { }
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertType(
findNode.catchClauseParameter('e,').declaredElement!.type,
'Object',
);
assertType(
findNode.catchClauseParameter('s]').declaredElement!.type,
'StackTrace',
);
}
test_invalid_const_as() async {
addTestFile(r'''
const num a = 1.2;
const int b = a as int;
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a as int');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'num');
assertNamedType(findNode.namedType('int;'), intElement, 'int');
}
test_invalid_const_constructor_initializer_field_multiple() async {
addTestFile(r'''
var a = 0;
class A {
final x = 0;
const A() : x = a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = a');
assertElement(xRef, findElement.field('x'));
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_const_methodInvocation() async {
addTestFile(r'''
const a = 'foo';
const b = 0;
const c = a.codeUnitAt(b);
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var invocation = findNode.methodInvocation('codeUnitAt');
assertType(invocation, 'int');
assertInvokeType(invocation, 'int Function(int)');
assertElement(
invocation.methodName,
elementMatcher(
stringElement.getMethod('codeUnitAt'),
isLegacy: isLegacyLibrary,
),
);
var aRef = invocation.target;
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'String');
var bRef = invocation.argumentList.arguments[0];
assertElement(bRef, findElement.topGet('b'));
assertType(bRef, 'int');
}
test_invalid_const_methodInvocation_static() async {
addTestFile(r'''
const c = A.m();
class A {
static int m() => 0;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var invocation = findNode.methodInvocation('m();');
assertType(invocation, 'int');
assertInvokeType(invocation, 'int Function()');
assertElement(invocation.methodName, findElement.method('m'));
}
test_invalid_const_methodInvocation_topLevelFunction() async {
addTestFile(r'''
const id = identical;
const a = 0;
const b = 0;
const c = id(a, b);
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var invocation = findNode.functionExpressionInvocation('id(');
assertElement(invocation.function, findElement.topGet('id'));
assertInvokeType(invocation, 'bool Function(Object?, Object?)');
assertType(invocation, 'bool');
var aRef = invocation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
var bRef = invocation.argumentList.arguments[1];
assertElement(bRef, findElement.topGet('b'));
assertType(bRef, 'int');
}
test_invalid_const_throw_local() async {
addTestFile(r'''
main() {
const c = throw 42;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var throwExpression = findNode.throw_('throw 42;');
expect(throwExpression.staticType, isNeverType);
assertType(throwExpression.expression, 'int');
}
test_invalid_const_throw_topLevel() async {
addTestFile(r'''
const c = throw 42;
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var throwExpression = findNode.throw_('throw 42;');
expect(throwExpression.staticType, isNeverType);
assertType(throwExpression.expression, 'int');
}
test_invalid_constructor_initializer_field_class() async {
addTestFile(r'''
var a = 0;
class A {
A() : X = a;
}
class X {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('X = ');
assertElementNull(xRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_getter() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
int get x => 0;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElement(xRef, findElement.field('x'));
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_importPrefix() async {
addTestFile(r'''
import 'dart:async' as x;
var a = 0;
class A {
A() : x = a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElementNull(xRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_method() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
void x() {}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElementNull(xRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_setter() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
set x(_) {}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElement(xRef, findElement.field('x'));
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_topLevelFunction() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
}
void x() {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElementNull(xRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_topLevelVar() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
}
int x;
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.simple('x = ');
assertElementNull(xRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_typeParameter() async {
addTestFile(r'''
var a = 0;
class A<T> {
A() : T = a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.simple('T = ');
assertElementNull(tRef);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_initializer_field_unresolved() async {
addTestFile(r'''
var a = 0;
class A {
A() : x = a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_constructor_return_blockBody() async {
addTestFile(r'''
int a = 0;
class C {
C() {
return a;
}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertTopGetRef('a;', 'a');
}
test_invalid_constructor_return_expressionBody() async {
addTestFile(r'''
int a = 0;
class C {
C() => a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertTopGetRef('a;', 'a');
}
test_invalid_deferred_type_localVariable() async {
addTestFile(r'''
import 'dart:async' deferred as a;
main() {
a.Future<int> v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertNamedType(
findNode.namedType('a.Future'),
futureElement,
'Future<int>',
expectedPrefix: findElement.import('dart:async').prefix?.element,
);
assertNamedType(findNode.namedType('int>'), intElement, 'int');
}
test_invalid_fieldInitializer_field() async {
addTestFile(r'''
class C {
final int a = 0;
final int b = a + 1;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a + 1');
assertElement(aRef, findElement.getter('a'));
assertType(aRef, 'int');
}
test_invalid_fieldInitializer_getter() async {
addTestFile(r'''
class C {
int get a => 0;
final int b = a + 1;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a + 1');
assertElement(aRef, findElement.getter('a'));
assertType(aRef, 'int');
}
test_invalid_fieldInitializer_method() async {
addTestFile(r'''
class C {
int a() => 0;
final int b = a + 1;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a + 1');
assertElement(aRef, findElement.method('a'));
assertType(aRef, 'int Function()');
}
test_invalid_fieldInitializer_this() async {
addTestFile(r'''
class C {
final b = this;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var thisRef = findNode.this_('this');
assertType(thisRef, 'C');
}
test_invalid_generator_async_return_blockBody() async {
addTestFile(r'''
int a = 0;
f() async* {
return a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_generator_async_return_expressionBody() async {
addTestFile(r'''
int a = 0;
f() async* => a;
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_generator_sync_return_blockBody() async {
addTestFile(r'''
int a = 0;
f() sync* {
return a;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_generator_sync_return_expressionBody() async {
addTestFile(r'''
int a = 0;
f() sync* => a;
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_getter_parameters() async {
addTestFile(r'''
get m(int a, double b) {
a;
b;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('a;');
assertElement(aRef, findElement.parameter('a'));
assertType(aRef, 'int');
var bRef = findNode.simple('b;');
assertElement(bRef, findElement.parameter('b'));
assertType(bRef, 'double');
}
@failingTest
test_invalid_instanceCreation_abstract() async {
addTestFile(r'''
abstract class C<T> {
C(T a);
C.named(T a);
C.named2();
}
var a = 0;
var b = true;
main() {
new C(a);
new C.named(b);
new C<double>.named2();
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var c = findElement.class_('C');
{
var creation = findNode.instanceCreation('new C(a)');
assertType(creation, 'C<int>');
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
NamedType type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertTypeNull(type.name);
var aRef = creation.argumentList.arguments[0] as SimpleIdentifier;
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
{
var creation = findNode.instanceCreation('new C.named(b)');
assertType(creation, 'C<bool>');
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name!.name, 'named');
NamedType type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertType(type.name, 'C<bool>');
var bRef = creation.argumentList.arguments[0] as SimpleIdentifier;
assertElement(bRef, findElement.topGet('b'));
assertType(bRef, 'bool');
}
{
var creation = findNode.instanceCreation('new C<double>.named2()');
assertType(creation, 'C<double>');
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name!.name, 'named2');
NamedType type = constructorName.type;
assertTypeArguments(type.typeArguments!, [doubleType]);
assertElement(type.name, c);
assertType(type.name, 'C<double>');
}
}
test_invalid_instanceCreation_arguments_named() async {
addTestFile(r'''
class C {
C();
}
var a = 0;
main() {
new C(x: a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('new C(x: a)');
_assertConstructorInvocation(creation, classElement);
var argument = creation.argumentList.arguments[0] as NamedExpression;
assertElementNull(argument.name.label);
var aRef = argument.expression;
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_instanceCreation_arguments_required_01() async {
addTestFile(r'''
class C {
C();
}
var a = 0;
main() {
new C(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('new C(a)');
_assertConstructorInvocation(creation, classElement);
var aRef = creation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_instanceCreation_arguments_required_21() async {
addTestFile(r'''
class C {
C(a, b);
}
var a = 0;
main() {
new C(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('new C(a)');
_assertConstructorInvocation(creation, classElement);
var aRef = creation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_instanceCreation_constOfNotConst_factory() async {
addTestFile(r'''
class C {
factory C(x) => throw 0;
}
var a = 0;
main() {
const C(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('const C(a)');
_assertConstructorInvocation(creation, classElement);
var aRef = creation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_instanceCreation_constOfNotConst_generative() async {
addTestFile(r'''
class C {
C(x);
}
var a = 0;
main() {
const C(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('const C(a)');
_assertConstructorInvocation(creation, classElement);
var aRef = creation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
@failingTest
test_invalid_instanceCreation_prefixAsType() async {
addTestFile(r'''
import 'dart:math' as p;
int a;
main() {
new p(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
final import = findNode.import('dart:math').element2!;
var pRef = findNode.simple('p(a)');
assertElement(pRef, import.prefix);
assertTypeDynamic(pRef);
var aRef = findNode.simple('a);');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_arguments_instance_method() async {
addTestFile(r'''
class C {
void m() {}
}
var a = 0;
main(C c) {
c.m(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var m = findElement.method('m');
var invocation = findNode.methodInvocation('m(a)');
assertElement(invocation.methodName, m);
assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_arguments_named_duplicate2() async {
addTestFile(r'''
void f({p}) {}
int a, b;
main() {
f(p: a, p: b);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var f = findElement.function('f');
var invocation = findNode.methodInvocation('f(p: a');
assertElement(invocation.methodName, f);
assertType(invocation.methodName, 'void Function({dynamic p})');
assertType(invocation, 'void');
var arg0 = invocation.argumentList.arguments[0] as NamedExpression;
assertElement(arg0.name.label, f.parameters[0]);
assertIdentifierTopGetRef(arg0.expression as SimpleIdentifier, 'a');
var arg1 = invocation.argumentList.arguments[1] as NamedExpression;
assertElement(arg1.name.label, f.parameters[0]);
assertIdentifierTopGetRef(arg1.expression as SimpleIdentifier, 'b');
}
test_invalid_invocation_arguments_named_duplicate3() async {
addTestFile(r'''
void f({p}) {}
int a, b, c;
main() {
f(p: a, p: b, p: c);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var f = findElement.function('f');
var invocation = findNode.methodInvocation('f(p: a');
assertElement(invocation.methodName, f);
assertType(invocation.methodName, 'void Function({dynamic p})');
assertType(invocation, 'void');
var arg0 = invocation.argumentList.arguments[0] as NamedExpression;
assertElement(arg0.name.label, f.parameters[0]);
assertIdentifierTopGetRef(arg0.expression as SimpleIdentifier, 'a');
var arg1 = invocation.argumentList.arguments[1] as NamedExpression;
assertElement(arg1.name.label, f.parameters[0]);
assertIdentifierTopGetRef(arg1.expression as SimpleIdentifier, 'b');
var arg2 = invocation.argumentList.arguments[2] as NamedExpression;
assertElement(arg2.name.label, f.parameters[0]);
assertIdentifierTopGetRef(arg2.expression as SimpleIdentifier, 'c');
}
test_invalid_invocation_arguments_requiredAfterNamed() async {
addTestFile(r'''
var a = 0;
var b = 0;
main() {
f(p: a, b);
}
void f({p}) {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertTopGetRef('a, ', 'a');
assertTopGetRef('b);', 'b');
}
test_invalid_invocation_arguments_static_method() async {
addTestFile(r'''
class C {
static void m() {}
}
var a = 0;
main() {
C.m(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var m = findElement.method('m');
var invocation = findNode.methodInvocation('m(a)');
assertElement(invocation.methodName, m);
assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_arguments_static_redirectingConstructor() async {
addTestFile(r'''
class C {
factory C() = C.named;
C.named();
}
int a;
main() {
new C(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var classElement = findElement.class_('C');
var creation = findNode.instanceCreation('new C(a)');
_assertConstructorInvocation(creation, classElement);
var aRef = creation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_arguments_static_topLevelFunction() async {
addTestFile(r'''
void f() {}
var a = 0;
main() {
f(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var f = findElement.function('f');
var invocation = findNode.methodInvocation('f(a)');
assertElement(invocation.methodName, f);
assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_arguments_static_topLevelVariable() async {
addTestFile(r'''
void Function() f;
var a = 0;
main() {
f(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var f = findElement.topGet('f');
var invocation = findNode.functionExpressionInvocation('f(a)');
assertElement(invocation.function, f);
assertInvokeType(invocation, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_invocation_prefixAsMethodName() async {
addTestFile(r'''
import 'dart:math' as p;
int a;
main() {
p(a);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
final import = findNode.import('dart:math').element2!;
var invocation = findNode.methodInvocation('p(a)');
expect(invocation.staticType, isDynamicType);
assertUnresolvedInvokeType(invocation.staticInvokeType!);
var pRef = invocation.methodName;
assertElement(pRef, import.prefix?.element);
assertTypeDynamic(pRef);
var aRef = findNode.simple('a);');
assertElement(aRef, findElement.topGet('a'));
assertType(aRef, 'int');
}
test_invalid_methodInvocation_simpleIdentifier() async {
addTestFile(r'''
int foo = 0;
main() {
foo(1);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var invocation = findNode.functionExpressionInvocation('foo(1)');
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
assertElement(invocation.function, findElement.topGet('foo'));
assertType(invocation.function, 'int');
}
@failingTest
test_invalid_nonTypeAsType_class_constructor() async {
addTestFile(r'''
class A {
A.T();
}
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.class_('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_class_instanceField() async {
addTestFile(r'''
class A {
int T;
}
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.class_('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_class_instanceMethod() async {
addTestFile(r'''
class A {
int T() => 0;
}
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.class_('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_class_staticField() async {
addTestFile(r'''
class A {
static int T;
}
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.class_('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_class_staticMethod() async {
addTestFile(r'''
class A {
static int T() => 0;
}
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.class_('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_topLevelFunction() async {
addTestFile(r'''
int T() => 0;
main() {
T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.simple('T v;');
assertElement(tRef, findElement.topFunction('T'));
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_topLevelFunction_prefixed() async {
newFile('$testPackageLibPath/a.dart', r'''
int T() => 0;
''');
addTestFile(r'''
import 'a.dart' as p;
main() {
p.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
final import = findNode.import('a.dart').element2!;
var tElement = import.importedLibrary!.publicNamespace.get('T');
var prefixedName = findNode.prefixed('p.T');
assertTypeDynamic(prefixedName);
var pRef = prefixedName.prefix;
assertElement(pRef, import.prefix);
expect(pRef.staticType, null);
var tRef = prefixedName.identifier;
assertElement(tRef, tElement);
assertTypeDynamic(tRef);
var namedType = prefixedName.parent as NamedType;
expect(namedType.type, isDynamicType);
}
@failingTest
test_invalid_nonTypeAsType_topLevelVariable() async {
addTestFile(r'''
int T;
main() {
T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.simple('T v;');
assertElement(tRef, findElement.topGet('T'));
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_topLevelVariable_name() async {
addTestFile(r'''
int A;
main() {
A.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var aRef = findNode.simple('A.T v;');
assertElement(aRef, findElement.topGet('A'));
assertTypeDynamic(aRef);
var tRef = findNode.simple('T v;');
assertElement(tRef, null);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_topLevelVariable_prefixed() async {
newFile('$testPackageLibPath/a.dart', r'''
int T;
''');
addTestFile(r'''
import 'a.dart' as p;
main() {
p.T v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
final import = findNode.import('a.dart').element2!;
var tElement = import.importedLibrary!.publicNamespace.get('T');
var prefixedName = findNode.prefixed('p.T');
assertTypeDynamic(prefixedName);
var pRef = prefixedName.prefix;
assertElement(pRef, import.prefix);
expect(pRef.staticType, null);
var tRef = prefixedName.identifier;
assertElement(tRef, tElement);
assertTypeDynamic(tRef);
var namedType = prefixedName.parent as NamedType;
expect(namedType.type, isDynamicType);
}
@failingTest
test_invalid_nonTypeAsType_typeParameter_name() async {
addTestFile(r'''
main<T>() {
T.U v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.simple('T.U v;');
var tElement = findNode.typeParameter('T>()').declaredElement!;
assertElement(tRef, tElement);
assertTypeDynamic(tRef);
}
@failingTest
test_invalid_nonTypeAsType_unresolved_name() async {
addTestFile(r'''
main() {
T.U v;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.simple('T.U v;');
assertElementNull(tRef);
assertTypeDynamic(tRef);
}
test_invalid_rethrow() async {
addTestFile('''
main() {
rethrow;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var rethrowExpression = findNode.rethrow_('rethrow;');
expect(rethrowExpression.staticType, isNeverType);
}
test_invalid_tryCatch_1() async {
addTestFile(r'''
main() {
try {}
catch String catch (e) {}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
}
test_invalid_tryCatch_2() async {
addTestFile(r'''
main() {
try {}
catch catch (e) {}
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
}
test_isExpression() async {
await assertNoErrorsInCode(r'''
void f(var a) {
a is num;
}
''');
var isExpression = findNode.isExpression('a is num');
expect(isExpression.notOperator, isNull);
expect(isExpression.staticType, typeProvider.boolType);
var target = isExpression.expression as SimpleIdentifier;
expect(target.staticElement, findElement.parameter('a'));
expect(target.staticType, dynamicType);
var numName = isExpression.type as NamedType;
expect(numName.name.staticElement, typeProvider.numType.element2);
expect(numName.name.staticType, isNull);
}
test_isExpression_not() async {
await assertNoErrorsInCode(r'''
void f(var a) {
a is! num;
}
''');
var isExpression = findNode.isExpression('a is! num');
expect(isExpression.notOperator, isNotNull);
expect(isExpression.staticType, typeProvider.boolType);
var target = isExpression.expression as SimpleIdentifier;
expect(target.staticElement, findElement.parameter('a'));
expect(target.staticType, dynamicType);
var numName = isExpression.type as NamedType;
expect(numName.name.staticElement, typeProvider.numType.element2);
expect(numName.name.staticType, isNull);
}
test_label_while() async {
addTestFile(r'''
main() {
myLabel:
while (true) {
continue myLabel;
break myLabel;
}
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as LabeledStatement;
Label label = statement.labels.single;
var labelElement = label.label.staticElement as LabelElement;
var whileStatement = statement.statement as WhileStatement;
var whileBlock = whileStatement.body as Block;
var continueStatement = whileBlock.statements[0] as ContinueStatement;
expect(continueStatement.label!.staticElement, same(labelElement));
expect(continueStatement.label!.staticType, isNull);
var breakStatement = whileBlock.statements[1] as BreakStatement;
expect(breakStatement.label!.staticElement, same(labelElement));
expect(breakStatement.label!.staticType, isNull);
}
test_listLiteral_01() async {
addTestFile(r'''
main() {
var v = [];
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var literal = findNode.listLiteral('[];');
expect(literal.typeArguments, isNull);
assertType(literal, 'List<dynamic>');
}
test_listLiteral_02() async {
addTestFile(r'''
main() {
var v = <>[];
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var literal = findNode.listLiteral('[];');
expect(literal.typeArguments, isNotNull);
assertType(literal, 'List<dynamic>');
}
test_listLiteral_2() async {
addTestFile(r'''
main() {
var v = <int, double>[];
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var literal = findNode.listLiteral('<int, double>[]');
assertType(literal, 'List<dynamic>');
var intRef = findNode.simple('int, double');
assertElement(intRef, intElement);
assertTypeNull(intRef);
var doubleRef = findNode.simple('double>[]');
assertElement(doubleRef, doubleElement);
assertTypeNull(doubleRef);
}
test_local_function() async {
addTestFile(r'''
void main() {
double f(int a, String b) {}
var v = f(1, '2');
}
''');
String fTypeString = 'double Function(int, String)';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
InterfaceType doubleType = typeProvider.doubleType;
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
expect(fElement, isNotNull);
assertType(fElement.type, fTypeString);
var fReturnTypeNode = fNode.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(doubleType.element2));
expect(fReturnTypeNode.type, doubleType);
expect(fExpression.declaredElement, same(fElement));
{
List<ParameterElement> elements = fElement.parameters;
expect(elements, hasLength(2));
List<FormalParameter> nodes = fExpression.parameters!.parameters;
expect(nodes, hasLength(2));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, elements[0],
name: 'a',
offset: 29,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
_assertSimpleParameter(nodes[1] as SimpleFormalParameter, elements[1],
name: 'b',
offset: 39,
kind: ParameterKind.REQUIRED,
type: typeProvider.stringType);
}
var vStatement = mainStatements[1] as VariableDeclarationStatement;
VariableDeclaration vDeclaration = vStatement.variables.variables[0];
expect(vDeclaration.declaredElement!.type, doubleType);
var fInvocation = vDeclaration.initializer as MethodInvocation;
expect(fInvocation.methodName.staticElement, same(fElement));
assertType(fInvocation.methodName, fTypeString);
expect(fInvocation.staticType, doubleType);
assertInvokeType(fInvocation, fTypeString);
}
test_local_function_call_with_incomplete_closure_argument() async {
addTestFile('''
void main() {
f(x) => null;
f(=> 42);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
// Note: no further expectations. We don't care how the error is recovered
// from, provided it is recovered from in a way that doesn't crash the
// analyzer/FE integration.
}
@failingTest
test_local_function_generic() async {
addTestFile(r'''
void main() {
T f<T, U>(T a, U b) {
a;
b;
}
var v = f(1, '2');
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
TypeParameterElement tElement = fElement.typeParameters[0];
TypeParameterElement uElement = fElement.typeParameters[1];
{
var fTypeParameters = fExpression.typeParameters!.typeParameters;
expect(fTypeParameters, hasLength(2));
TypeParameter tNode = fTypeParameters[0];
expect(tNode.declaredElement, same(tElement));
TypeParameter uNode = fTypeParameters[1];
expect(uNode.declaredElement, same(uElement));
}
expect(fElement, isNotNull);
assertType(fElement.type, 'T Function<T,U>(T, U)');
var fReturnTypeNode = fNode.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(tElement));
expect(fReturnTypeNode.type, typeParameterTypeStar(tElement));
expect(fExpression.declaredElement, same(fElement));
{
List<ParameterElement> parameters = fElement.parameters;
expect(parameters, hasLength(2));
List<FormalParameter> nodes = fExpression.parameters!.parameters;
expect(nodes, hasLength(2));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, parameters[0],
name: 'a',
offset: 28,
kind: ParameterKind.REQUIRED,
type: typeParameterTypeStar(tElement));
_assertSimpleParameter(nodes[1] as SimpleFormalParameter, parameters[1],
name: 'b',
offset: 33,
kind: ParameterKind.REQUIRED,
type: typeParameterTypeStar(uElement));
var aRef = findNode.simple('a;');
assertElement(aRef, parameters[0]);
assertType(aRef, 'T');
var bRef = findNode.simple('b;');
assertElement(bRef, parameters[1]);
assertType(bRef, 'U');
}
var vStatement = mainStatements[1] as VariableDeclarationStatement;
VariableDeclaration vDeclaration = vStatement.variables.variables[0];
expect(vDeclaration.declaredElement!.type, typeProvider.intType);
var fInvocation = vDeclaration.initializer as MethodInvocation;
expect(fInvocation.methodName.staticElement, same(fElement));
expect(fInvocation.staticType, typeProvider.intType);
assertTypeNull(fInvocation.methodName);
assertInvokeType(fInvocation, 'int Function(int, String)');
}
test_local_function_generic_f_bounded() async {
addTestFile('''
void main() {
void F<T extends U, U, V extends U>(T x, U y, V z) {}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
assertType(
fElement.type, 'void Function<T extends U, U, V extends U>(T, U, V)');
var tElement = fElement.typeParameters[0];
var uElement = fElement.typeParameters[1];
var vElement = fElement.typeParameters[2];
expect((tElement.bound as TypeParameterType).element2, same(uElement));
expect((vElement.bound as TypeParameterType).element2, same(uElement));
}
test_local_function_generic_with_named_parameter() async {
addTestFile('''
void main() {
void F<T>({T x}) {}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
assertType(fElement.type, 'void Function<T>({T x})');
var tElement = fElement.typeParameters[0];
expect(fElement.type.typeFormals[0], same(tElement));
expect((fElement.type.parameters[0].type as TypeParameterType).element2,
same(tElement));
}
test_local_function_generic_with_optional_parameter() async {
addTestFile('''
void main() {
void F<T>([T x]) {}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
assertType(fElement.type, 'void Function<T>([T])');
var tElement = fElement.typeParameters[0];
expect(fElement.type.typeFormals[0], same(tElement));
expect((fElement.type.parameters[0].type as TypeParameterType).element2,
same(tElement));
}
test_local_function_namedParameters() async {
addTestFile(r'''
void main() {
double f(int a, {String b, bool c: false}) {}
f(1, b: '2', c: true);
}
''');
String fTypeString = 'double Function(int, {String b, bool c})';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
InterfaceType doubleType = typeProvider.doubleType;
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
expect(fElement, isNotNull);
assertType(fElement.type, fTypeString);
var fReturnTypeNode = fNode.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(doubleType.element2));
expect(fReturnTypeNode.type, doubleType);
expect(fExpression.declaredElement, same(fElement));
{
List<ParameterElement> elements = fElement.parameters;
expect(elements, hasLength(3));
List<FormalParameter> nodes = fExpression.parameters!.parameters;
expect(nodes, hasLength(3));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, elements[0],
name: 'a',
offset: 29,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
_assertDefaultParameter(nodes[1] as DefaultFormalParameter, elements[1],
name: 'b',
offset: 40,
kind: ParameterKind.NAMED,
type: typeProvider.stringType);
_assertDefaultParameter(nodes[2] as DefaultFormalParameter, elements[2],
name: 'c',
offset: 48,
kind: ParameterKind.NAMED,
type: typeProvider.boolType);
}
{
var statement = mainStatements[1] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(arguments[0], fElement.parameters[0]);
_assertArgumentToParameter(arguments[1], fElement.parameters[1]);
_assertArgumentToParameter(arguments[2], fElement.parameters[2]);
}
}
test_local_function_noReturnType() async {
addTestFile(r'''
void main() {
f() {}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
expect(fNode.returnType, isNull);
expect(fElement, isNotNull);
assertType(fElement.type, 'Null Function()');
expect(fExpression.declaredElement, same(fElement));
}
test_local_function_optionalParameters() async {
addTestFile(r'''
void main() {
double f(int a, [String b, bool c]) {}
var v = f(1, '2', true);
}
''');
String fTypeString = 'double Function(int, [String, bool])';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
InterfaceType doubleType = typeProvider.doubleType;
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
expect(fElement, isNotNull);
assertType(fElement.type, fTypeString);
var fReturnTypeNode = fNode.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(doubleType.element2));
expect(fReturnTypeNode.type, doubleType);
expect(fExpression.declaredElement, same(fElement));
{
List<ParameterElement> elements = fElement.parameters;
expect(elements, hasLength(3));
List<FormalParameter> nodes = fExpression.parameters!.parameters;
expect(nodes, hasLength(3));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, elements[0],
name: 'a',
offset: 29,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
_assertDefaultParameter(nodes[1] as DefaultFormalParameter, elements[1],
name: 'b',
offset: 40,
kind: ParameterKind.POSITIONAL,
type: typeProvider.stringType);
_assertDefaultParameter(nodes[2] as DefaultFormalParameter, elements[2],
name: 'c',
offset: 48,
kind: ParameterKind.POSITIONAL,
type: typeProvider.boolType);
}
{
var statement = mainStatements[1] as VariableDeclarationStatement;
VariableDeclaration declaration = statement.variables.variables[0];
expect(declaration.declaredElement!.type, doubleType);
var invocation = declaration.initializer as MethodInvocation;
expect(invocation.methodName.staticElement, same(fElement));
assertType(invocation.methodName, fTypeString);
expect(invocation.staticType, doubleType);
assertInvokeType(invocation, fTypeString);
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(arguments[0], fElement.parameters[0]);
_assertArgumentToParameter(arguments[1], fElement.parameters[1]);
_assertArgumentToParameter(arguments[2], fElement.parameters[2]);
}
}
test_local_function_with_function_typed_parameter() async {
addTestFile('''
class C {}
class D {}
class E {}
void f() {
void g(C callback<T extends E>(D d)) {}
}
''');
await resolveTestFile();
var callbackElement = findElement.parameter('callback');
assertType(callbackElement.type, 'C Function<T extends E>(D)');
var cReference = findNode.simple('C callback');
var cElement = findElement.class_('C');
assertTypeNull(cReference);
assertElement(cReference, cElement);
var dReference = findNode.simple('D d');
var dElement = findElement.class_('D');
assertTypeNull(dReference);
assertElement(dReference, dElement);
var eReference = findNode.simple('E>');
var eElement = findElement.class_('E');
assertTypeNull(eReference);
assertElement(eReference, eElement);
}
test_local_parameter() async {
await assertNoErrorsInCode(r'''
void main(List<String> p) {
p;
}
''');
var main = result.unit.declarations[0] as FunctionDeclaration;
List<Statement> statements = _getMainStatements(result);
// (int p)
VariableElement pElement = main.declaredElement!.parameters[0];
expect(pElement.type, listNone(typeProvider.stringType));
// p;
{
var statement = statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, pElement);
expect(identifier.staticType, listNone(typeProvider.stringType));
}
}
test_local_parameter_ofLocalFunction() async {
addTestFile(r'''
void main() {
void f(int a) {
a;
void g(double b) {
b;
}
}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
// f(int a) {}
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionExpression fExpression = fNode.functionExpression;
var fElement = fNode.declaredElement as FunctionElement;
ParameterElement aElement = fElement.parameters[0];
_assertSimpleParameter(
fExpression.parameters!.parameters[0] as SimpleFormalParameter,
aElement,
name: 'a',
offset: 27,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
var fBody = fExpression.body as BlockFunctionBody;
List<Statement> fStatements = fBody.block.statements;
// a;
var aStatement = fStatements[0] as ExpressionStatement;
var aNode = aStatement.expression as SimpleIdentifier;
expect(aNode.staticElement, same(aElement));
expect(aNode.staticType, typeProvider.intType);
// g(double b) {}
var gStatement = fStatements[1] as FunctionDeclarationStatement;
FunctionDeclaration gNode = gStatement.functionDeclaration;
FunctionExpression gExpression = gNode.functionExpression;
var gElement = gNode.declaredElement as FunctionElement;
ParameterElement bElement = gElement.parameters[0];
_assertSimpleParameter(
gExpression.parameters!.parameters[0] as SimpleFormalParameter,
bElement,
name: 'b',
offset: 57,
kind: ParameterKind.REQUIRED,
type: typeProvider.doubleType);
var gBody = gExpression.body as BlockFunctionBody;
List<Statement> gStatements = gBody.block.statements;
// b;
var bStatement = gStatements[0] as ExpressionStatement;
var bNode = bStatement.expression as SimpleIdentifier;
expect(bNode.staticElement, same(bElement));
expect(bNode.staticType, typeProvider.doubleType);
}
test_local_type_parameter_reference_as_expression() async {
addTestFile('''
void main() {
void f<T>(T x) {
T;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var bodyStatement = body.block.statements[0] as ExpressionStatement;
var tReference = bodyStatement.expression as SimpleIdentifier;
assertElement(tReference, tElement);
assertType(tReference, 'Type');
}
test_local_type_parameter_reference_function_named_parameter_type() async {
addTestFile('''
void main() {
void f<T>(T x) {
void Function({T t}) g = null;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var gType = gDeclaration.variables.type as GenericFunctionType;
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.namedParameterTypes['t'] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gParameterType =
((gType.parameters.parameters[0] as DefaultFormalParameter).parameter
as SimpleFormalParameter)
.type as NamedType;
var tReference = gParameterType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_function_normal_parameter_type() async {
addTestFile('''
void main() {
void f<T>(T x) {
void Function(T) g = null;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var gType = gDeclaration.variables.type as GenericFunctionType;
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.normalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gParameterType =
(gType.parameters.parameters[0] as SimpleFormalParameter).type
as NamedType;
var tReference = gParameterType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_function_optional_parameter_type() async {
addTestFile('''
void main() {
void f<T>(T x) {
void Function([T]) g = null;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var gType = gDeclaration.variables.type as GenericFunctionType;
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.optionalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gParameterType =
((gType.parameters.parameters[0] as DefaultFormalParameter).parameter
as SimpleFormalParameter)
.type as NamedType;
var tReference = gParameterType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_function_return_type() async {
addTestFile('''
void main() {
void f<T>(T x) {
T Function() g = () => x;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var gType = gDeclaration.variables.type as GenericFunctionType;
var gTypeType = gType.type as FunctionType;
var gTypeReturnType = gTypeType.returnType as TypeParameterType;
expect(gTypeReturnType.element2, same(tElement));
var gReturnType = gType.returnType as NamedType;
var tReference = gReturnType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_interface_type_parameter() async {
addTestFile('''
void main() {
void f<T>(T x) {
List<T> y = [x];
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var yDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var yType = yDeclaration.variables.type as NamedType;
var yTypeType = yType.type as InterfaceType;
var yTypeTypeArgument = yTypeType.typeArguments[0] as TypeParameterType;
expect(yTypeTypeArgument.element2, same(tElement));
var yElementType = yType.typeArguments!.arguments[0] as NamedType;
var tReference = yElementType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_simple() async {
addTestFile('''
void main() {
void f<T>(T x) {
T y = x;
}
f(1);
}
''');
await resolveTestFile();
var mainStatements = _getMainStatements(result);
var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
var fElement = fDeclaration.functionDeclaration.declaredElement!;
var tElement = fElement.typeParameters[0];
var body = fDeclaration.functionDeclaration.functionExpression.body
as BlockFunctionBody;
var yDeclaration = body.block.statements[0] as VariableDeclarationStatement;
var yType = yDeclaration.variables.type as NamedType;
var tReference = yType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_typedef_named_parameter_type() async {
addTestFile('''
typedef void Consumer<U>({U u});
void main() {
void f<T>(T x) {
Consumer<T> g = null;
}
f(1);
}
''');
await resolveTestFile();
var tElement = findNode.typeParameter('T>(T x)').declaredElement!;
var gType = findNode.namedType('Consumer<T>');
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.namedParameterTypes['u'] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gArgumentType = gType.typeArguments!.arguments[0] as NamedType;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_typedef_normal_parameter_type() async {
addTestFile('''
typedef void Consumer<U>(U u);
void main() {
void f<T>(T x) {
Consumer<T> g = null;
}
f(1);
}
''');
await resolveTestFile();
var tElement = findNode.typeParameter('T>(T x)').declaredElement!;
var gType = findNode.namedType('Consumer<T>');
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.normalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gArgumentType = gType.typeArguments!.arguments[0] as NamedType;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_typedef_optional_parameter_type() async {
addTestFile('''
typedef void Consumer<U>([U u]);
void main() {
void f<T>(T x) {
Consumer<T> g = null;
}
f(1);
}
''');
await resolveTestFile();
var tElement = findNode.typeParameter('T>(T x)').declaredElement!;
var gType = findNode.namedType('Consumer<T>');
var gTypeType = gType.type as FunctionType;
var gTypeParameterType =
gTypeType.optionalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element2, same(tElement));
var gArgumentType = gType.typeArguments!.arguments[0] as NamedType;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_type_parameter_reference_typedef_return_type() async {
addTestFile('''
typedef U Producer<U>();
void main() {
void f<T>(T x) {
Producer<T> g = () => x;
}
f(1);
}
''');
await resolveTestFile();
var tElement = findNode.typeParameter('T>(T x)').declaredElement!;
var gType = findNode.namedType('Producer<T>');
var gTypeType = gType.type as FunctionType;
var gTypeReturnType = gTypeType.returnType as TypeParameterType;
expect(gTypeReturnType.element2, same(tElement));
var gArgumentType = gType.typeArguments!.arguments[0] as NamedType;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_local_variable() async {
await assertNoErrorsInCode(r'''
void main() {
var v = 42;
v;
}
''');
InterfaceType intType = typeProvider.intType;
var main = result.unit.declarations[0] as FunctionDeclaration;
expect(main.declaredElement, isNotNull);
var body = main.functionExpression.body as BlockFunctionBody;
NodeList<Statement> statements = body.block.statements;
// var v = 42;
VariableElement vElement;
{
var statement = statements[0] as VariableDeclarationStatement;
VariableDeclaration vNode = statement.variables.variables[0];
expect(vNode.initializer!.staticType, intType);
vElement = vNode.declaredElement!;
expect(vElement, isNotNull);
expect(vElement.type, isNotNull);
expect(vElement.type, intType);
}
// v;
{
var statement = statements[1] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(vElement));
expect(identifier.staticType, intType);
}
}
test_local_variable_forIn_identifier_field() async {
addTestFile(r'''
class C {
num v;
void foo() {
for (v in <int>[]) {
v;
}
}
}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
var cDeclaration = unit.declarations[0] as ClassDeclaration;
var vDeclaration = cDeclaration.members[0] as FieldDeclaration;
VariableDeclaration vNode = vDeclaration.fields.variables[0];
var vElement = vNode.declaredElement as FieldElement;
expect(vElement.type, typeProvider.numType);
var fooDeclaration = cDeclaration.members[1] as MethodDeclaration;
var fooBody = fooDeclaration.body as BlockFunctionBody;
List<Statement> statements = fooBody.block.statements;
var forEachStatement = statements[0] as ForStatement;
var forBlock = forEachStatement.body as Block;
var forEachParts =
forEachStatement.forLoopParts as ForEachPartsWithIdentifier;
SimpleIdentifier vInFor = forEachParts.identifier;
expect(vInFor.staticElement, same(vElement.setter));
expect(vInFor.staticType, typeProvider.numType);
var statement = forBlock.statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(vElement.getter));
expect(identifier.staticType, typeProvider.numType);
}
test_local_variable_forIn_identifier_localVariable() async {
addTestFile(r'''
void main() {
num v;
for (v in <int>[]) {
v;
}
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var vStatement = statements[0] as VariableDeclarationStatement;
VariableDeclaration vNode = vStatement.variables.variables[0];
var vElement = vNode.declaredElement as LocalVariableElement;
expect(vElement.type, typeProvider.numType);
var forEachStatement = statements[1] as ForStatement;
var forBlock = forEachStatement.body as Block;
var forEachParts =
forEachStatement.forLoopParts as ForEachPartsWithIdentifier;
SimpleIdentifier vInFor = forEachParts.identifier;
expect(vInFor.staticElement, vElement);
expect(vInFor.staticType, typeProvider.numType);
var statement = forBlock.statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(vElement));
expect(identifier.staticType, typeProvider.numType);
}
test_local_variable_forIn_identifier_topLevelVariable() async {
addTestFile(r'''
void main() {
for (v in <int>[]) {
v;
}
}
num v;
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
List<Statement> statements = _getMainStatements(result);
var vDeclaration = unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration vNode = vDeclaration.variables.variables[0];
var vElement = vNode.declaredElement as TopLevelVariableElement;
expect(vElement.type, typeProvider.numType);
var forEachStatement = statements[0] as ForStatement;
var forBlock = forEachStatement.body as Block;
var forEachParts =
forEachStatement.forLoopParts as ForEachPartsWithIdentifier;
SimpleIdentifier vInFor = forEachParts.identifier;
expect(vInFor.staticElement, same(vElement.setter));
expect(vInFor.staticType, typeProvider.numType);
var statement = forBlock.statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(vElement.getter));
expect(identifier.staticType, typeProvider.numType);
}
test_local_variable_forIn_loopVariable() async {
addTestFile(r'''
void main() {
for (var v in <int>[]) {
v;
}
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var forEachStatement = statements[0] as ForStatement;
var forBlock = forEachStatement.body as Block;
var forEachParts =
forEachStatement.forLoopParts as ForEachPartsWithDeclaration;
DeclaredIdentifier vNode = forEachParts.loopVariable;
LocalVariableElement vElement = vNode.declaredElement!;
expect(vElement.type, typeProvider.intType);
var statement = forBlock.statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, vElement);
expect(identifier.staticType, typeProvider.intType);
}
test_local_variable_forIn_loopVariable_explicitType() async {
addTestFile(r'''
void main() {
for (num v in <int>[]) {
v;
}
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var forEachStatement = statements[0] as ForStatement;
var forBlock = forEachStatement.body as Block;
var forEachParts =
forEachStatement.forLoopParts as ForEachPartsWithDeclaration;
DeclaredIdentifier vNode = forEachParts.loopVariable;
LocalVariableElement vElement = vNode.declaredElement!;
expect(vElement.type, typeProvider.numType);
var vNamedType = vNode.type as NamedType;
expect(vNamedType.type, typeProvider.numType);
var vTypeIdentifier = vNamedType.name as SimpleIdentifier;
expect(vTypeIdentifier.staticElement, typeProvider.numType.element2);
expect(vTypeIdentifier.staticType, isNull);
var statement = forBlock.statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, vElement);
expect(identifier.staticType, typeProvider.numType);
}
test_local_variable_multiple() async {
addTestFile(r'''
void main() {
var a = 1, b = 2.3;
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var declarationStatement = statements[0] as VariableDeclarationStatement;
VariableDeclaration aNode = declarationStatement.variables.variables[0];
var aElement = aNode.declaredElement as LocalVariableElement;
expect(aElement.type, typeProvider.intType);
VariableDeclaration bNode = declarationStatement.variables.variables[1];
var bElement = bNode.declaredElement as LocalVariableElement;
expect(bElement.type, typeProvider.doubleType);
}
test_local_variable_ofLocalFunction() async {
addTestFile(r'''
void main() {
void f() {
int a;
a;
void g() {
double b;
a;
b;
}
}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
// f() {}
var fStatement = mainStatements[0] as FunctionDeclarationStatement;
FunctionDeclaration fNode = fStatement.functionDeclaration;
var fBody = fNode.functionExpression.body as BlockFunctionBody;
List<Statement> fStatements = fBody.block.statements;
// int a;
var aDeclaration = fStatements[0] as VariableDeclarationStatement;
VariableElement aElement =
aDeclaration.variables.variables[0].declaredElement!;
// a;
{
var aStatement = fStatements[1] as ExpressionStatement;
var aNode = aStatement.expression as SimpleIdentifier;
expect(aNode.staticElement, same(aElement));
expect(aNode.staticType, typeProvider.intType);
}
// g(double b) {}
var gStatement = fStatements[2] as FunctionDeclarationStatement;
FunctionDeclaration gNode = gStatement.functionDeclaration;
var gBody = gNode.functionExpression.body as BlockFunctionBody;
List<Statement> gStatements = gBody.block.statements;
// double b;
var bDeclaration = gStatements[0] as VariableDeclarationStatement;
VariableElement bElement =
bDeclaration.variables.variables[0].declaredElement!;
// a;
{
var aStatement = gStatements[1] as ExpressionStatement;
var aNode = aStatement.expression as SimpleIdentifier;
expect(aNode.staticElement, same(aElement));
expect(aNode.staticType, typeProvider.intType);
}
// b;
{
var bStatement = gStatements[2] as ExpressionStatement;
var bNode = bStatement.expression as SimpleIdentifier;
expect(bNode.staticElement, same(bElement));
expect(bNode.staticType, typeProvider.doubleType);
}
}
test_mapLiteral() async {
addTestFile(r'''
void main() {
<int, double>{};
const <bool, String>{};
}
''');
await resolveTestFile();
var statements = _getMainStatements(result);
{
var statement = statements[0] as ExpressionStatement;
var mapLiteral = statement.expression as SetOrMapLiteral;
expect(mapLiteral.staticType,
typeProvider.mapType(typeProvider.intType, typeProvider.doubleType));
}
{
var statement = statements[1] as ExpressionStatement;
var mapLiteral = statement.expression as SetOrMapLiteral;
expect(mapLiteral.staticType,
typeProvider.mapType(typeProvider.boolType, typeProvider.stringType));
}
}
test_mapLiteral_3() async {
addTestFile(r'''
main() {
var v = <bool, int, double>{};
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var literal = findNode.setOrMapLiteral('<bool, int, double>{}');
assertType(literal, 'Map<dynamic, dynamic>');
var boolRef = findNode.simple('bool, ');
assertElement(boolRef, boolElement);
assertTypeNull(boolRef);
var intRef = findNode.simple('int, ');
assertElement(intRef, intElement);
assertTypeNull(intRef);
var doubleRef = findNode.simple('double>');
assertElement(doubleRef, doubleElement);
assertTypeNull(doubleRef);
}
test_method_namedParameters() async {
addTestFile(r'''
class C {
double f(int a, {String b, bool c: false}) {}
}
void g(C c) {
c.f(1, b: '2', c: true);
}
''');
String fTypeString = 'double Function(int, {String b, bool c})';
await resolveTestFile();
var classDeclaration = result.unit.declarations[0] as ClassDeclaration;
var methodDeclaration = classDeclaration.members[0] as MethodDeclaration;
var methodElement = methodDeclaration.declaredElement as MethodElement;
InterfaceType doubleType = typeProvider.doubleType;
expect(methodElement, isNotNull);
assertType(methodElement.type, fTypeString);
var fReturnTypeNode = methodDeclaration.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(doubleType.element2));
expect(fReturnTypeNode.type, doubleType);
//
// Validate the parameters at the declaration site.
//
List<ParameterElement> elements = methodElement.parameters;
expect(elements, hasLength(3));
List<FormalParameter> nodes = methodDeclaration.parameters!.parameters;
expect(nodes, hasLength(3));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, elements[0],
name: 'a',
offset: 25,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
_assertDefaultParameter(nodes[1] as DefaultFormalParameter, elements[1],
name: 'b',
offset: 36,
kind: ParameterKind.NAMED,
type: typeProvider.stringType);
_assertDefaultParameter(nodes[2] as DefaultFormalParameter, elements[2],
name: 'c',
offset: 44,
kind: ParameterKind.NAMED,
type: typeProvider.boolType);
//
// Validate the arguments at the call site.
//
var functionDeclaration =
result.unit.declarations[1] as FunctionDeclaration;
var body = functionDeclaration.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(arguments[0], methodElement.parameters[0]);
_assertArgumentToParameter(arguments[1], methodElement.parameters[1]);
_assertArgumentToParameter(arguments[2], methodElement.parameters[2]);
}
test_methodInvocation_explicitCall_classTarget() async {
addTestFile(r'''
class C {
double call(int p) => 0.0;
}
main() {
new C().call(0);
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
MethodElement callElement = cElement.methods[0];
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.staticType, typeProvider.doubleType);
assertInvokeType(invocation, 'double Function(int)');
SimpleIdentifier methodName = invocation.methodName;
expect(methodName.staticElement, same(callElement));
assertType(methodName.staticType, 'double Function(int)');
}
test_methodInvocation_explicitCall_functionTarget() async {
addTestFile(r'''
f(double computation(int p)) {
computation.call(1);
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var main = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = main.declaredElement as FunctionElement;
ParameterElement parameter = mainElement.parameters[0];
var mainBody = main.functionExpression.body as BlockFunctionBody;
List<Statement> statements = mainBody.block.statements;
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.staticType, typeProvider.doubleType);
assertInvokeType(invocation, 'double Function(int)');
var target = invocation.target as SimpleIdentifier;
expect(target.staticElement, same(parameter));
assertType(target.staticType, 'double Function(int)');
SimpleIdentifier methodName = invocation.methodName;
expect(methodName.staticElement, isNull);
expect(methodName.staticType, dynamicType);
}
test_methodInvocation_instanceMethod_forwardingStub() async {
addTestFile(r'''
class A {
void foo(int x) {}
}
abstract class I<T> {
void foo(T x);
}
class B extends A implements I<int> {}
main(B b) {
b.foo(1);
}
''');
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
var fooNode = aNode.members[0] as MethodDeclaration;
var fooElement = fooNode.declaredElement as MethodElement;
List<Statement> mainStatements = _getMainStatements(result);
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.methodName.staticElement, same(fooElement));
var invokeTypeStr = 'void Function(int)';
assertType(invocation.staticType, 'void');
assertInvokeType(invocation, invokeTypeStr);
}
@FailingTest(
reason: 'This test started failing, because we probably assign '
'corresponding parameter elements from FunctionType, which became '
'pure in this CL. We should clean this up by using MethodMember '
'parameters instead.')
test_methodInvocation_instanceMethod_genericClass() async {
addTestFile(r'''
main() {
new C<int, double>().m(1);
}
class C<T, U> {
void m(T p) {}
}
''');
await resolveTestFile();
MethodElement mElement = findElement.method('m');
{
var invocation = findNode.methodInvocation('m(1)');
List<Expression> arguments = invocation.argumentList.arguments;
var invokeTypeStr = 'void Function(int)';
assertType(invocation, 'void');
assertInvokeType(invocation, invokeTypeStr);
assertMember(
invocation.methodName, mElement, {'T': 'int', 'U': 'double'});
assertType(invocation.methodName, invokeTypeStr);
_assertArgumentToParameter(arguments[0], mElement.parameters[0]);
}
}
test_methodInvocation_instanceMethod_genericClass_genericMethod() async {
addTestFile(r'''
main() {
new C<int>().m(1, 2.3);
}
class C<T> {
Map<T, U> m<U>(T a, U b) => null;
}
''');
await resolveTestFile();
MethodElement mElement = findElement.method('m');
{
var invocation = findNode.methodInvocation('m(1, 2.3)');
List<Expression> arguments = invocation.argumentList.arguments;
var invokeTypeStr = 'Map<int, double> Function(int, double)';
assertType(invocation, 'Map<int, double>');
assertInvokeType(invocation, invokeTypeStr);
assertMember(invocation.methodName, mElement, {'T': 'int'});
assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
_assertArgumentToParameter2(arguments[0], 'int');
_assertArgumentToParameter2(arguments[1], 'double');
}
}
test_methodInvocation_namedArgument() async {
addTestFile(r'''
void main() {
foo(1, b: true, c: 3.0);
}
void foo(int a, {bool b, double c}) {}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var foo = result.unit.declarations[1] as FunctionDeclaration;
ExecutableElement fooElement = foo.declaredElement!;
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(arguments[0], fooElement.parameters[0]);
_assertArgumentToParameter(arguments[1], fooElement.parameters[1]);
_assertArgumentToParameter(arguments[2], fooElement.parameters[2]);
}
test_methodInvocation_notFunction_field_dynamic() async {
addTestFile(r'''
class C {
dynamic f;
foo() {
f(1);
}
}
''');
await resolveTestFile();
var invocation = findNode.functionExpressionInvocation('f(1)');
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
assertElement(invocation.function, findElement.getter('f'));
List<Expression> arguments = invocation.argumentList.arguments;
expect(arguments[0].staticParameterElement, isNull);
}
test_methodInvocation_notFunction_getter_dynamic() async {
addTestFile(r'''
class C {
get f => null;
foo() {
f(1);
}
}
''');
await resolveTestFile();
var invocation = findNode.functionExpressionInvocation('f(1)');
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
assertElement(invocation.function, findElement.getter('f'));
List<Expression> arguments = invocation.argumentList.arguments;
expect(arguments[0].staticParameterElement, isNull);
}
test_methodInvocation_notFunction_getter_typedef() async {
addTestFile(r'''
typedef String Fun(int a, {int b});
class C {
Fun get f => null;
foo() {
f(1, b: 2);
}
}
''');
await resolveTestFile();
var invocation = findNode.functionExpressionInvocation('f(1');
assertElement(invocation.function, findElement.getter('f'));
assertInvokeType(invocation, 'String Function(int, {int b})');
assertType(invocation, 'String');
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter2(arguments[0], 'int');
_assertArgumentToParameter2(arguments[1], 'int');
}
test_methodInvocation_notFunction_local_dynamic() async {
addTestFile(r'''
main(f) {
f(1);
}
''');
await resolveTestFile();
var invocation = findNode.functionExpressionInvocation('f(1)');
assertElement(invocation.function, findElement.parameter('f'));
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
List<Expression> arguments = invocation.argumentList.arguments;
Expression argument = arguments[0];
expect(argument.staticParameterElement, isNull);
}
test_methodInvocation_notFunction_local_functionTyped() async {
addTestFile(r'''
main(String f(int a)) {
f(1);
}
''');
await resolveTestFile();
var fElement = findElement.parameter('f');
var invocation = findNode.functionExpressionInvocation('f(1)');
assertElement(invocation.function, fElement);
assertInvokeType(invocation, 'String Function(int)');
assertType(invocation, 'String');
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(
arguments[0], (fElement.type as FunctionType).parameters[0]);
}
test_methodInvocation_notFunction_topLevelVariable_dynamic() async {
addTestFile(r'''
dynamic f;
main() {
f(1);
}
''');
await resolveTestFile();
var invocation = findNode.functionExpressionInvocation('f(1)');
assertElement(invocation.function, findElement.topGet('f'));
assertInvokeTypeDynamic(invocation);
assertTypeDynamic(invocation);
List<Expression> arguments = invocation.argumentList.arguments;
Expression argument = arguments[0];
expect(argument.staticParameterElement, isNull);
}
test_methodInvocation_staticMethod() async {
addTestFile(r'''
main() {
C.m(1);
}
class C {
static void m(int p) {}
void foo() {
m(2);
}
}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var cNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var mNode = cNode.members[0] as MethodDeclaration;
var mElement = mNode.declaredElement as MethodElement;
{
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
var target = invocation.target as SimpleIdentifier;
expect(target.staticElement, same(cElement));
assertTypeNull(target);
var invokeTypeStr = 'void Function(int)';
assertType(invocation.staticType, 'void');
assertInvokeType(invocation, invokeTypeStr);
expect(invocation.methodName.staticElement, same(mElement));
assertType(invocation.methodName, invokeTypeStr);
Expression argument = arguments[0];
_assertArgumentToParameter(argument, mElement.parameters[0]);
}
{
var fooNode = cNode.members[1] as MethodDeclaration;
var fooBody = fooNode.body as BlockFunctionBody;
List<Statement> statements = fooBody.block.statements;
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
expect(invocation.target, isNull);
var invokeTypeStr = 'void Function(int)';
assertType(invocation.staticType, 'void');
assertInvokeType(invocation, invokeTypeStr);
expect(invocation.methodName.staticElement, same(mElement));
assertType(invocation.methodName, invokeTypeStr);
Expression argument = arguments[0];
_assertArgumentToParameter(argument, mElement.parameters[0]);
}
}
test_methodInvocation_staticMethod_contextTypeParameter() async {
addTestFile(r'''
class C<T> {
static E foo<E>(C<E> c) => null;
void bar() {
foo(this);
}
}
''');
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
TypeParameterElement tElement = cNode.declaredElement!.typeParameters[0];
var barNode = cNode.members[1] as MethodDeclaration;
var barBody = barNode.body as BlockFunctionBody;
var fooStatement = barBody.block.statements[0] as ExpressionStatement;
var fooInvocation = fooStatement.expression as MethodInvocation;
assertInvokeType(fooInvocation, 'T Function(C<T>)');
assertType(fooInvocation.staticType, 'T');
final type = fooInvocation.typeOrThrow as TypeParameterType;
expect(type.element2, same(tElement));
}
test_methodInvocation_topLevelFunction() async {
addTestFile(r'''
void main() {
f(1, '2');
}
double f(int a, String b) {}
''');
String fTypeString = 'double Function(int, String)';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
InterfaceType doubleType = typeProvider.doubleType;
var fNode = result.unit.declarations[1] as FunctionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
expect(invocation.methodName.staticElement, same(fElement));
assertType(invocation.methodName, fTypeString);
expect(invocation.staticType, doubleType);
assertInvokeType(invocation, fTypeString);
_assertArgumentToParameter(arguments[0], fElement.parameters[0]);
_assertArgumentToParameter(arguments[1], fElement.parameters[1]);
}
@failingTest
test_methodInvocation_topLevelFunction_generic() async {
addTestFile(r'''
void main() {
f<bool, String>(true, 'str');
f(1, 2.3);
}
void f<T, U>(T a, U b) {}
''');
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
var fNode = result.unit.declarations[1] as FunctionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
// f<bool, String>(true, 'str');
{
String fTypeString = 'void Function(bool, String)';
var statement = mainStatements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<TypeAnnotation> typeArguments = invocation.typeArguments!.arguments;
expect(typeArguments, hasLength(2));
{
var typeArgument = typeArguments[0] as NamedType;
InterfaceType boolType = typeProvider.boolType;
expect(typeArgument.type, boolType);
expect(typeArgument.name.staticElement, boolType.element2);
expect(typeArgument.name.staticType, boolType);
}
{
var typeArgument = typeArguments[1] as NamedType;
InterfaceType stringType = typeProvider.stringType;
expect(typeArgument.type, stringType);
expect(typeArgument.name.staticElement, stringType.element2);
expect(typeArgument.name.staticType, stringType);
}
List<Expression> arguments = invocation.argumentList.arguments;
expect(invocation.methodName.staticElement, same(fElement));
expect(invocation.methodName.staticType.toString(), fTypeString);
expect(invocation.staticType, VoidTypeImpl.instance);
assertInvokeType(invocation, fTypeString);
_assertArgumentToParameter(arguments[0], fElement.parameters[0],
memberType: typeProvider.boolType);
_assertArgumentToParameter(arguments[1], fElement.parameters[1],
memberType: typeProvider.stringType);
}
// f(1, 2.3);
{
String fTypeString = 'void Function(int, double)';
var statement = mainStatements[1] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
expect(invocation.methodName.staticElement, same(fElement));
expect(invocation.methodName.staticType.toString(), fTypeString);
expect(invocation.staticType, VoidTypeImpl.instance);
assertInvokeType(invocation, fTypeString);
_assertArgumentToParameter(arguments[0], fElement.parameters[0],
memberType: typeProvider.intType);
_assertArgumentToParameter(arguments[1], fElement.parameters[1],
memberType: typeProvider.doubleType);
}
}
test_optionalConst() async {
addTestFile(r'''
class C {
const C();
const C.named();
}
const a = C(); // ref
const b = C.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var c = findElement.class_('C');
{
var creation = findNode.instanceCreation('C(); // ref');
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
assertNamedType(creation.constructorName.type, c, 'C');
}
{
var creation = findNode.instanceCreation('C.named(); // ref');
var namedConstructor = c.getNamedConstructor('named')!;
assertElement(creation, namedConstructor);
assertType(creation, 'C');
assertNamedType(creation.constructorName.type, c, 'C');
assertElement(creation.constructorName.name, namedConstructor);
}
}
test_optionalConst_prefixed() async {
newFile('$testPackageLibPath/a.dart', r'''
class C {
const C();
const C.named();
}
''');
addTestFile(r'''
import 'a.dart' as p;
const a = p.C(); // ref
const b = p.C.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var import = findElement.import('package:test/a.dart');
var c = import.importedLibrary!.getClass('C')!;
{
var creation = findNode.instanceCreation('C(); // ref');
assertElement(creation, c.unnamedConstructor);
assertType(creation, 'C');
assertNamedType(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix?.element);
}
{
var creation = findNode.instanceCreation('C.named(); // ref');
var namedConstructor = c.getNamedConstructor('named')!;
assertElement(creation, namedConstructor);
assertType(creation, 'C');
assertNamedType(creation.constructorName.type, c, 'C',
expectedPrefix: import.prefix?.element);
assertElement(creation.constructorName.name, namedConstructor);
}
}
test_optionalConst_typeArguments() async {
addTestFile(r'''
class C<T> {
const C();
const C.named();
}
const a = C<int>(); // ref
const b = C<String>.named(); // ref
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var c = findElement.class_('C');
{
var creation = findNode.instanceCreation('C<int>(); // ref');
assertMember(creation, c.unnamedConstructor!, {'T': 'int'});
assertType(creation, 'C<int>');
assertNamedType(creation.constructorName.type, c, 'C<int>');
assertNamedType(findNode.namedType('int>'), intElement, 'int');
}
{
var creation = findNode.instanceCreation('C<String>.named(); // ref');
var namedConstructor = c.getNamedConstructor('named')!;
assertMember(creation, namedConstructor, {'T': 'String'});
assertType(creation, 'C<String>');
assertNamedType(creation.constructorName.type, c, 'C<String>');
assertNamedType(findNode.namedType('String>'), stringElement, 'String');
assertMember(
creation.constructorName.name, namedConstructor, {'T': 'String'});
}
}
test_outline_invalid_mixin_arguments_tooFew() async {
addTestFile(r'''
class A extends Object with Map<int> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var mapRef = findNode.namedType('Map<');
assertNamedType(mapRef, mapElement, 'Map<dynamic, dynamic>');
var intRef = findNode.namedType('int>');
assertNamedType(intRef, intElement, 'int');
}
test_outline_invalid_mixin_arguments_tooMany() async {
addTestFile(r'''
class A extends Object with List<int, double> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var listRef = findNode.namedType('List<');
assertNamedType(listRef, listElement, 'List<dynamic>');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_mixin_typeParameter() async {
addTestFile(r'''
class A<T> extends Object with T<int, double> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.namedType('T<');
assertNamedType(tRef, findElement.typeParameter('T'), 'T');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_supertype_arguments_tooFew() async {
addTestFile(r'''
class A extends Map<int> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var mapRef = findNode.namedType('Map<');
assertNamedType(mapRef, mapElement, 'Map<dynamic, dynamic>');
var intRef = findNode.namedType('int>');
assertNamedType(intRef, intElement, 'int');
}
test_outline_invalid_supertype_arguments_tooMany() async {
addTestFile(r'''
class A extends List<int, double> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var listRef = findNode.namedType('List<');
assertNamedType(listRef, listElement, 'List<dynamic>');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_supertype_hasArguments() async {
addTestFile(r'''
class A extends X<int, double> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.namedType('X<');
assertNamedType(xRef, null, 'dynamic');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_supertype_noArguments() async {
addTestFile(r'''
class A extends X {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var xRef = findNode.namedType('X {}');
assertNamedType(xRef, null, 'dynamic');
}
test_outline_invalid_supertype_typeParameter() async {
addTestFile(r'''
class A<T> extends T<int, double> {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.namedType('T<');
assertNamedType(tRef, findElement.typeParameter('T'), 'T');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_type_arguments_tooFew() async {
addTestFile(r'''
typedef Map<int> F();
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var mapRef = findNode.namedType('Map<');
assertNamedType(mapRef, mapElement, 'Map<dynamic, dynamic>');
var intRef = findNode.namedType('int>');
assertNamedType(intRef, intElement, 'int');
}
test_outline_invalid_type_arguments_tooMany() async {
addTestFile(r'''
typedef List<int, double> F();
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var listRef = findNode.namedType('List<');
assertNamedType(listRef, listElement, 'List<dynamic>');
var intRef = findNode.namedType('int,');
assertNamedType(intRef, intElement, 'int');
var doubleRef = findNode.namedType('double>');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_invalid_type_typeParameter() async {
addTestFile(r'''
typedef T<int> F<T>();
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var tRef = findNode.namedType('T<');
assertNamedType(tRef, findElement.typeParameter('T'), 'T');
var intRef = findNode.namedType('int>');
assertNamedType(intRef, intElement, 'int');
}
test_outline_type_genericFunction() async {
addTestFile(r'''
int Function(double) g() => (double g) => 0;
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var intRef = findNode.namedType('int Function');
assertNamedType(intRef, intElement, 'int');
var functionRef = findNode.genericFunctionType('Function(double)');
assertType(functionRef, 'int Function(double)');
var doubleRef = findNode.namedType('double) g');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_type_topLevelVar_named() async {
addTestFile(r'''
int a = 0;
List<double> b = [];
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var intRef = findNode.namedType('int a');
assertNamedType(intRef, intElement, 'int');
var listRef = findNode.namedType('List<double> b');
assertNamedType(listRef, listElement, 'List<double>');
var doubleRef = findNode.namedType('double> b');
assertNamedType(doubleRef, doubleElement, 'double');
}
test_outline_type_topLevelVar_named_prefixed() async {
addTestFile(r'''
import 'dart:async' as my;
my.Future<int> a;
''');
await resolveTestFile();
final myImport = result.libraryElement.libraryImports[0];
var intRef = findNode.namedType('int> a');
assertNamedType(intRef, intElement, 'int');
var futureRef = findNode.namedType('my.Future<int> a');
assertNamedType(futureRef, futureElement, 'Future<int>',
expectedPrefix: myImport.prefix?.element);
}
test_postfix_increment_of_non_generator() async {
addTestFile('''
void f(int g()) {
g()++;
}
''');
await resolveTestFile();
var gRef = findNode.simple('g()++');
assertType(gRef, 'int Function()');
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) {
++!x;
}
''');
await resolveTestFile();
var xRef = findNode.simple('x;');
assertType(xRef, 'bool');
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() {
var c = new C();
c.f;
}
class C {
int f;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cDeclaration.declaredElement!;
FieldElement fElement = cElement.fields[0];
var cStatement = statements[0] as VariableDeclarationStatement;
VariableElement vElement =
cStatement.variables.variables[0].declaredElement!;
var statement = statements[1] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(vElement));
expect(prefix.staticType, interfaceTypeNone(cElement));
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, same(fElement.getter));
expect(identifier.staticType, typeProvider.intType);
}
test_prefixedIdentifier_className_staticField() async {
String content = r'''
main() {
C.f;
}
class C {
static f = 0;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cDeclaration.declaredElement!;
FieldElement fElement = cElement.fields[0];
var statement = statements[0] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(cElement));
assertTypeNull(prefix);
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, same(fElement.getter));
expect(identifier.staticType, typeProvider.intType);
}
test_prefixedIdentifier_explicitCall() async {
addTestFile(r'''
f(double computation(int p)) {
computation.call;
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var main = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = main.declaredElement as FunctionElement;
ParameterElement parameter = mainElement.parameters[0];
var mainBody = main.functionExpression.body as BlockFunctionBody;
List<Statement> statements = mainBody.block.statements;
var statement = statements[0] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
expect(prefixed.prefix.staticElement, same(parameter));
assertType(prefixed.prefix.staticType, 'double Function(int)');
SimpleIdentifier methodName = prefixed.identifier;
expect(methodName.staticElement, isNull);
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() {
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 access = statement.expression as PropertyAccess;
expect(access.staticType, typeProvider.intType);
var newC = access.target as InstanceCreationExpression;
expect(
newC.constructorName.staticElement,
cClassElement.unnamedConstructor,
);
expect(newC.staticType, interfaceTypeNone(cClassElement));
expect(access.propertyName.staticElement, same(fElement.getter));
expect(access.propertyName.staticType, typeProvider.intType);
}
}
test_propertyAccess_getter() async {
String content = r'''
main() {
new C().f;
}
class C {
int get f => 0;
}
''';
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 access = statement.expression as PropertyAccess;
expect(access.staticType, typeProvider.intType);
var newC = access.target as InstanceCreationExpression;
expect(
newC.constructorName.staticElement,
cClassElement.unnamedConstructor,
);
expect(newC.staticType, interfaceTypeNone(cClassElement));
expect(access.propertyName.staticElement, same(fElement.getter));
expect(access.propertyName.staticType, typeProvider.intType);
}
}
test_reference_to_class_type_parameter() async {
addTestFile('''
class C<T> {
void f() {
T x;
}
}
''');
await resolveTestFile();
var tElement = findElement.class_('C').typeParameters[0];
var tReference = findNode.simple('T x');
assertElement(tReference, tElement);
assertTypeNull(tReference);
}
test_setLiteral() async {
addTestFile(r'''
main() {
var v = <int>{};
print(v);
}
''');
await resolveTestFile();
expect(result.errors, isEmpty);
var literal = findNode.setOrMapLiteral('<int>{}');
assertType(literal, 'Set<int>');
var intRef = findNode.simple('int>{}');
assertElement(intRef, intElement);
assertTypeNull(intRef);
}
test_stringInterpolation() async {
await assertNoErrorsInCode(r'''
void main() {
var v = 42;
'$v$v $v';
' ${v + 1} ';
}
''');
var main = result.unit.declarations[0] as FunctionDeclaration;
expect(main.declaredElement, isNotNull);
var body = main.functionExpression.body as BlockFunctionBody;
NodeList<Statement> statements = body.block.statements;
// var v = 42;
VariableElement vElement;
{
var statement = statements[0] as VariableDeclarationStatement;
vElement = statement.variables.variables[0].declaredElement!;
}
{
var statement = statements[1] as ExpressionStatement;
var interpolation = statement.expression as StringInterpolation;
var element_1 = interpolation.elements[1] as InterpolationExpression;
var expression_1 = element_1.expression as SimpleIdentifier;
expect(expression_1.staticElement, same(vElement));
expect(expression_1.staticType, typeProvider.intType);
var element_3 = interpolation.elements[3] as InterpolationExpression;
var expression_3 = element_3.expression as SimpleIdentifier;
expect(expression_3.staticElement, same(vElement));
expect(expression_3.staticType, typeProvider.intType);
var element_5 = interpolation.elements[5] as InterpolationExpression;
var expression_5 = element_5.expression as SimpleIdentifier;
expect(expression_5.staticElement, same(vElement));
expect(expression_5.staticType, typeProvider.intType);
}
{
var statement = statements[2] as ExpressionStatement;
var interpolation = statement.expression as StringInterpolation;
var element_1 = interpolation.elements[1] as InterpolationExpression;
var expression = element_1.expression as BinaryExpression;
expect(expression.staticType, typeProvider.intType);
var left = expression.leftOperand as SimpleIdentifier;
expect(left.staticElement, same(vElement));
expect(left.staticType, typeProvider.intType);
}
}
test_stringInterpolation_multiLine_emptyBeforeAfter() async {
addTestFile(r"""
void main() {
var v = 42;
'''$v''';
}
""");
await resolveTestFile();
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 {
double f;
C([int a: 1 + 2]) : f = 3.4;
}
''';
addTestFile(content);
await resolveTestFile();
var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var constructorNode = cNode.members[1] as ConstructorDeclaration;
var aNode =
constructorNode.parameters.parameters[0] as DefaultFormalParameter;
_assertDefaultParameter(aNode, cElement.unnamedConstructor!.parameters[0],
name: 'a',
offset: 31,
kind: ParameterKind.POSITIONAL,
type: typeProvider.intType);
var binary = aNode.defaultValue as BinaryExpression;
expect(binary.staticElement, isNotNull);
expect(binary.staticType, typeProvider.intType);
expect(binary.leftOperand.staticType, typeProvider.intType);
expect(binary.rightOperand.staticType, typeProvider.intType);
}
test_top_class_extends() async {
String content = r'''
class A<T> {}
class B extends A<int> {}
''';
addTestFile(content);
await resolveTestFile();
var aRef = findNode.namedType('A<int>');
assertNamedType(aRef, findElement.class_('A'), 'A<int>');
var intRef = findNode.namedType('int>');
assertNamedType(intRef, intElement, 'int');
}
test_top_class_full() async {
String content = r'''
class A<T> {}
class B<T> {}
class C<T> {}
class D extends A<bool> with B<int> implements C<double> {}
''';
addTestFile(content);
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
var bNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement bElement = bNode.declaredElement!;
var cNode = result.unit.declarations[2] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var dNode = result.unit.declarations[3] as ClassDeclaration;
{
var expectedType = aElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType superClass = dNode.extendsClause!.superclass;
expect(superClass.type, expectedType);
var identifier = superClass.name as SimpleIdentifier;
expect(identifier.staticElement, aElement);
expect(identifier.staticType, isNull);
}
{
var expectedType = bElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType mixinType = dNode.withClause!.mixinTypes[0];
expect(mixinType.type, expectedType);
var identifier = mixinType.name as SimpleIdentifier;
expect(identifier.staticElement, bElement);
expect(identifier.staticType, isNull);
}
{
var expectedType = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType implementedType = dNode.implementsClause!.interfaces[0];
expect(implementedType.type, expectedType);
var identifier = implementedType.name as SimpleIdentifier;
expect(identifier.staticElement, cElement);
expect(identifier.staticType, isNull);
}
}
test_top_classTypeAlias() async {
String content = r'''
class A<T> {}
class B<T> {}
class C<T> {}
class D = A<bool> with B<int> implements C<double>;
''';
addTestFile(content);
await resolveTestFile();
var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
var bNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement bElement = bNode.declaredElement!;
var cNode = result.unit.declarations[2] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var dNode = result.unit.declarations[3] as ClassTypeAlias;
{
var expectedType = aElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType superClass = dNode.superclass;
expect(superClass.type, expectedType);
var identifier = superClass.name as SimpleIdentifier;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
}
{
var expectedType = bElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType mixinType = dNode.withClause.mixinTypes[0];
expect(mixinType.type, expectedType);
var identifier = mixinType.name as SimpleIdentifier;
expect(identifier.staticElement, same(bElement));
expect(identifier.staticType, isNull);
}
{
var expectedType = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.none,
);
NamedType interfaceType = dNode.implementsClause!.interfaces[0];
expect(interfaceType.type, expectedType);
var identifier = interfaceType.name as SimpleIdentifier;
expect(identifier.staticElement, same(cElement));
expect(identifier.staticType, isNull);
}
}
test_top_enum() async {
String content = r'''
enum MyEnum {
A, B
}
''';
addTestFile(content);
await resolveTestFile();
var enumNode = result.unit.declarations[0] as EnumDeclaration;
final enumElement = enumNode.declaredElement!;
{
var aElement = enumElement.getField('A');
var aNode = enumNode.constants[0];
expect(aNode.declaredElement, same(aElement));
}
{
var bElement = enumElement.getField('B');
var bNode = enumNode.constants[1];
expect(bNode.declaredElement, same(bElement));
}
}
test_top_executables_class() async {
await assertNoErrorsInCode(r'''
class C {
C(int p);
C.named(int p);
int publicMethod(double p) => 0;
int get publicGetter => 0;
void set publicSetter(double p) {}
}
''');
InterfaceType doubleType = typeProvider.doubleType;
InterfaceType intType = typeProvider.intType;
final doubleElement = doubleType.element2;
final intElement = intType.element2;
var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
// unnamed constructor
{
var node = cNode.members[0] as ConstructorDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'C Function(int)');
expect(node.returnType.staticElement, same(cElement));
expect(node.returnType.staticType, isNull);
expect(node.name, isNull);
}
// named constructor
{
var node = cNode.members[1] as ConstructorDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'C Function(int)');
expect(node.returnType.staticElement, same(cElement));
expect(node.returnType.staticType, isNull);
}
// publicMethod()
{
var node = cNode.members[2] as MethodDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function(double)');
// method return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, intType);
expect(returnTypeName.staticElement, intElement);
expect(returnTypeName.staticType, isNull);
// method parameter
{
var pNode = node.parameters!.parameters[0] as SimpleFormalParameter;
expect(pNode.declaredElement, isNotNull);
expect(pNode.declaredElement!.type, doubleType);
var pType = pNode.type as NamedType;
expect(pType.name.staticElement, doubleElement);
expect(pType.name.staticType, isNull);
}
}
// publicGetter()
{
var node = cNode.members[3] as MethodDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function()');
// getter return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, intType);
expect(returnTypeName.staticElement, intElement);
expect(returnTypeName.staticType, isNull);
}
// publicSetter()
{
var node = cNode.members[4] as MethodDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'void Function(double)');
// setter return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, VoidTypeImpl.instance);
expect(returnTypeName.staticElement, isNull);
expect(returnTypeName.staticType, isNull);
// setter parameter
{
var pNode = node.parameters!.parameters[0] as SimpleFormalParameter;
expect(pNode.declaredElement, isNotNull);
expect(pNode.declaredElement!.type, doubleType);
var pType = pNode.type as NamedType;
expect(pType.name.staticElement, doubleElement);
expect(pType.name.staticType, isNull);
}
}
}
test_top_executables_top() async {
await assertNoErrorsInCode(r'''
int topFunction(double p) => 0;
int get topGetter => 0;
void set topSetter(double p) {}
''');
InterfaceType doubleType = typeProvider.doubleType;
InterfaceType intType = typeProvider.intType;
final doubleElement = doubleType.element2;
final intElement = intType.element2;
// topFunction()
{
var node = result.unit.declarations[0] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function(double)');
// function return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, intType);
expect(returnTypeName.staticElement, intElement);
expect(returnTypeName.staticType, isNull);
// function parameter
{
var pNode = node.functionExpression.parameters!.parameters[0]
as SimpleFormalParameter;
expect(pNode.declaredElement, isNotNull);
expect(pNode.declaredElement!.type, doubleType);
var pType = pNode.type as NamedType;
expect(pType.name.staticElement, doubleElement);
expect(pType.name.staticType, isNull);
}
}
// topGetter()
{
var node = result.unit.declarations[1] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function()');
// getter return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, intType);
expect(returnTypeName.staticElement, intElement);
expect(returnTypeName.staticType, isNull);
}
// topSetter()
{
var node = result.unit.declarations[2] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'void Function(double)');
// setter return type
var returnType = node.returnType as NamedType;
var returnTypeName = returnType.name as SimpleIdentifier;
expect(returnType.type, VoidTypeImpl.instance);
expect(returnTypeName.staticElement, isNull);
expect(returnTypeName.staticType, isNull);
// setter parameter
{
var pNode = node.functionExpression.parameters!.parameters[0]
as SimpleFormalParameter;
expect(pNode.declaredElement, isNotNull);
expect(pNode.declaredElement!.type, doubleType);
var pType = pNode.type as NamedType;
expect(pType.name.staticElement, doubleElement);
expect(pType.name.staticType, isNull);
}
}
}
test_top_field_class() async {
String content = r'''
class C<T> {
var a = 1;
T b;
}
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
TypeParameterElement tElement = cElement.typeParameters[0];
expect(cElement, same(unitElement.classes[0]));
{
FieldElement aElement = cElement.getField('a')!;
var aDeclaration = cNode.members[0] as FieldDeclaration;
VariableDeclaration aNode = aDeclaration.fields.variables[0];
expect(aNode.declaredElement, same(aElement));
expect(aElement.type, typeProvider.intType);
var aValue = aNode.initializer as Expression;
expect(aValue.staticType, typeProvider.intType);
}
{
FieldElement bElement = cElement.getField('b')!;
var bDeclaration = cNode.members[1] as FieldDeclaration;
var namedType = bDeclaration.fields.type as NamedType;
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, same(tElement));
expect(typeIdentifier.staticType, isNull);
VariableDeclaration bNode = bDeclaration.fields.variables[0];
expect(bNode.declaredElement, same(bElement));
expect(bElement.type, typeParameterTypeNone(tElement));
}
}
test_top_field_class_multiple() async {
String content = r'''
class C {
var a = 1, b = 2.3;
}
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var fieldDeclaration = cNode.members[0] as FieldDeclaration;
{
FieldElement aElement = cElement.getField('a')!;
VariableDeclaration aNode = fieldDeclaration.fields.variables[0];
expect(aNode.declaredElement, same(aElement));
expect(aElement.type, typeProvider.intType);
Expression aValue = aNode.initializer!;
expect(aValue.staticType, typeProvider.intType);
}
{
FieldElement bElement = cElement.getField('b')!;
VariableDeclaration bNode = fieldDeclaration.fields.variables[1];
expect(bNode.declaredElement, same(bElement));
expect(bElement.type, typeProvider.doubleType);
Expression aValue = bNode.initializer!;
expect(aValue.staticType, typeProvider.doubleType);
}
}
test_top_field_top() async {
String content = r'''
var a = 1;
double b = 2.3;
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
{
var aDeclaration = unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration aNode = aDeclaration.variables.variables[0];
var aElement = aNode.declaredElement as TopLevelVariableElement;
expect(aElement, same(unitElement.topLevelVariables[0]));
expect(aElement.type, typeProvider.intType);
Expression aValue = aNode.initializer!;
expect(aValue.staticType, typeProvider.intType);
}
{
var bDeclaration = unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration bNode = bDeclaration.variables.variables[0];
var bElement = bNode.declaredElement as TopLevelVariableElement;
expect(bElement, same(unitElement.topLevelVariables[1]));
expect(bElement.type, typeProvider.doubleType);
var namedType = bDeclaration.variables.type as NamedType;
_assertNamedTypeSimple(namedType, typeProvider.doubleType);
Expression aValue = bNode.initializer!;
expect(aValue.staticType, typeProvider.doubleType);
}
}
test_top_field_top_multiple() async {
String content = r'''
var a = 1, b = 2.3;
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var variableDeclaration =
unit.declarations[0] as TopLevelVariableDeclaration;
expect(variableDeclaration.variables.type, isNull);
{
VariableDeclaration aNode = variableDeclaration.variables.variables[0];
var aElement = aNode.declaredElement as TopLevelVariableElement;
expect(aElement, same(unitElement.topLevelVariables[0]));
expect(aElement.type, typeProvider.intType);
Expression aValue = aNode.initializer!;
expect(aValue.staticType, typeProvider.intType);
}
{
VariableDeclaration bNode = variableDeclaration.variables.variables[1];
var bElement = bNode.declaredElement as TopLevelVariableElement;
expect(bElement, same(unitElement.topLevelVariables[1]));
expect(bElement.type, typeProvider.doubleType);
Expression aValue = bNode.initializer!;
expect(aValue.staticType, typeProvider.doubleType);
}
}
test_top_function_namedParameters() async {
addTestFile(r'''
double f(int a, {String b, bool c: 1 == 2}) {}
void main() {
f(1, b: '2', c: true);
}
''');
String fTypeString = 'double Function(int, {String b, bool c})';
await resolveTestFile();
var fDeclaration = result.unit.declarations[0] as FunctionDeclaration;
var fElement = fDeclaration.declaredElement as FunctionElement;
InterfaceType doubleType = typeProvider.doubleType;
expect(fElement, isNotNull);
assertType(fElement.type, fTypeString);
var fReturnTypeNode = fDeclaration.returnType as NamedType;
expect(fReturnTypeNode.name.staticElement, same(doubleType.element2));
expect(fReturnTypeNode.type, doubleType);
//
// Validate the parameters at the declaration site.
//
List<ParameterElement> elements = fElement.parameters;
expect(elements, hasLength(3));
List<FormalParameter> nodes =
fDeclaration.functionExpression.parameters!.parameters;
expect(nodes, hasLength(3));
_assertSimpleParameter(nodes[0] as SimpleFormalParameter, elements[0],
name: 'a',
offset: 13,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
var bNode = nodes[1] as DefaultFormalParameter;
_assertDefaultParameter(bNode, elements[1],
name: 'b',
offset: 24,
kind: ParameterKind.NAMED,
type: typeProvider.stringType);
expect(bNode.defaultValue, isNull);
var cNode = nodes[2] as DefaultFormalParameter;
_assertDefaultParameter(cNode, elements[2],
name: 'c',
offset: 32,
kind: ParameterKind.NAMED,
type: typeProvider.boolType);
{
var defaultValue = cNode.defaultValue as BinaryExpression;
expect(defaultValue.staticElement, isNotNull);
expect(defaultValue.staticType, typeProvider.boolType);
}
//
// Validate the arguments at the call site.
//
var mainDeclaration = result.unit.declarations[1] as FunctionDeclaration;
var body = mainDeclaration.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
List<Expression> arguments = invocation.argumentList.arguments;
_assertArgumentToParameter(arguments[0], fElement.parameters[0]);
_assertArgumentToParameter(arguments[1], fElement.parameters[1]);
_assertArgumentToParameter(arguments[2], fElement.parameters[2]);
}
test_top_functionTypeAlias() async {
String content = r'''
typedef int F<T>(bool a, T b);
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
var alias = unit.declarations[0] as FunctionTypeAlias;
TypeAliasElement aliasElement = alias.declaredElement!;
var function = aliasElement.aliasedElement as GenericFunctionTypeElement;
expect(aliasElement, same(findElement.typeAlias('F')));
expect(function.returnType, typeProvider.intType);
_assertNamedTypeSimple(alias.returnType as NamedType, typeProvider.intType);
_assertSimpleParameter(
alias.parameters.parameters[0] as SimpleFormalParameter,
function.parameters[0],
name: 'a',
offset: 22,
kind: ParameterKind.REQUIRED,
type: typeProvider.boolType);
_assertSimpleParameter(
alias.parameters.parameters[1] as SimpleFormalParameter,
function.parameters[1],
name: 'b',
offset: 27,
kind: ParameterKind.REQUIRED,
type: typeParameterTypeNone(aliasElement.typeParameters[0]));
}
test_top_typeParameter() async {
String content = r'''
class A {}
class C<T extends A, U extends List<A>, V> {}
''';
addTestFile(content);
await resolveTestFile();
CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var aNode = unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
expect(aElement, same(unitElement.classes[0]));
var cNode = unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
expect(cElement, same(unitElement.classes[1]));
{
TypeParameter tNode = cNode.typeParameters!.typeParameters[0];
expect(tNode.declaredElement, same(cElement.typeParameters[0]));
var bound = tNode.bound as NamedType;
expect(bound.type, interfaceTypeNone(aElement));
var boundIdentifier = bound.name as SimpleIdentifier;
expect(boundIdentifier.staticElement, same(aElement));
expect(boundIdentifier.staticType, isNull);
}
{
var listElement = typeProvider.listElement;
var listOfA = listElement.instantiate(
typeArguments: [interfaceTypeNone(aElement)],
nullabilitySuffix: NullabilitySuffix.none,
);
TypeParameter uNode = cNode.typeParameters!.typeParameters[1];
expect(uNode.declaredElement, same(cElement.typeParameters[1]));
var bound = uNode.bound as NamedType;
expect(bound.type, listOfA);
var listIdentifier = bound.name as SimpleIdentifier;
expect(listIdentifier.staticElement, same(listElement));
expect(listIdentifier.staticType, isNull);
var aNamedType = bound.typeArguments!.arguments[0] as NamedType;
expect(aNamedType.type, interfaceTypeNone(aElement));
var aIdentifier = aNamedType.name as SimpleIdentifier;
expect(aIdentifier.staticElement, same(aElement));
expect(aIdentifier.staticType, isNull);
}
{
TypeParameter vNode = cNode.typeParameters!.typeParameters[2];
expect(vNode.declaredElement, same(cElement.typeParameters[2]));
expect(vNode.bound, isNull);
}
}
test_tryCatch() async {
addTestFile(r'''
void main() {
try {} catch (e, st) {
e;
st;
}
try {} on int catch (e, st) {
e;
st;
}
try {} catch (e) {
e;
}
try {} on int catch (e) {
e;
}
try {} on int {}
}
''');
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
// catch (e, st)
{
var statement = statements[0] as TryStatement;
CatchClause catchClause = statement.catchClauses[0];
expect(catchClause.exceptionType, isNull);
var exceptionNode = catchClause.exceptionParameter2!;
var exceptionElement = exceptionNode.declaredElement!;
expect(exceptionElement.type, typeProvider.objectType);
var stackNode = catchClause.stackTraceParameter2!;
var stackElement = stackNode.declaredElement!;
expect(stackElement.type, typeProvider.stackTraceType);
List<Statement> catchStatements = catchClause.body.statements;
var exceptionStatement = catchStatements[0] as ExpressionStatement;
var exceptionIdentifier =
exceptionStatement.expression as SimpleIdentifier;
expect(exceptionIdentifier.staticElement, same(exceptionElement));
expect(exceptionIdentifier.staticType, typeProvider.objectType);
var stackStatement = catchStatements[1] as ExpressionStatement;
var stackIdentifier = stackStatement.expression as SimpleIdentifier;
expect(stackIdentifier.staticElement, same(stackElement));
expect(stackIdentifier.staticType, typeProvider.stackTraceType);
}
// on int catch (e, st)
{
var statement = statements[1] as TryStatement;
CatchClause catchClause = statement.catchClauses[0];
_assertNamedTypeSimple(
catchClause.exceptionType as NamedType, typeProvider.intType);
var exceptionNode = catchClause.exceptionParameter2!;
var exceptionElement = exceptionNode.declaredElement!;
expect(exceptionElement.type, typeProvider.intType);
var stackNode = catchClause.stackTraceParameter2!;
var stackElement = stackNode.declaredElement!;
expect(stackElement.type, typeProvider.stackTraceType);
List<Statement> catchStatements = catchClause.body.statements;
var exceptionStatement = catchStatements[0] as ExpressionStatement;
var exceptionIdentifier =
exceptionStatement.expression as SimpleIdentifier;
expect(exceptionIdentifier.staticElement, same(exceptionElement));
expect(exceptionIdentifier.staticType, typeProvider.intType);
var stackStatement = catchStatements[1] as ExpressionStatement;
var stackIdentifier = stackStatement.expression as SimpleIdentifier;
expect(stackIdentifier.staticElement, same(stackElement));
expect(stackIdentifier.staticType, typeProvider.stackTraceType);
}
// catch (e)
{
var statement = statements[2] as TryStatement;
CatchClause catchClause = statement.catchClauses[0];
expect(catchClause.exceptionType, isNull);
expect(catchClause.stackTraceParameter2, isNull);
var exceptionNode = catchClause.exceptionParameter2!;
var exceptionElement = exceptionNode.declaredElement!;
expect(exceptionElement.type, typeProvider.objectType);
}
// on int catch (e)
{
var statement = statements[3] as TryStatement;
CatchClause catchClause = statement.catchClauses[0];
_assertNamedTypeSimple(catchClause.exceptionType!, typeProvider.intType);
expect(catchClause.stackTraceParameter2, isNull);
var exceptionNode = catchClause.exceptionParameter2!;
var exceptionElement = exceptionNode.declaredElement!;
expect(exceptionElement.type, typeProvider.intType);
}
// on int catch (e)
{
var statement = statements[4] as TryStatement;
CatchClause catchClause = statement.catchClauses[0];
_assertNamedTypeSimple(
catchClause.exceptionType as NamedType, typeProvider.intType);
expect(catchClause.exceptionParameter2, isNull);
expect(catchClause.stackTraceParameter2, isNull);
}
}
test_type_dynamic() async {
addTestFile('''
main() {
dynamic d;
}
''');
await resolveTestFile();
var statements = _getMainStatements(result);
var variableDeclarationStatement =
statements[0] as VariableDeclarationStatement;
var type = variableDeclarationStatement.variables.type as NamedType;
expect(type.type, isDynamicType);
var namedType = type.name;
assertTypeNull(namedType);
}
test_type_functionTypeAlias() async {
addTestFile(r'''
typedef T F<T>(bool a);
class C {
F<int> f;
}
''');
await resolveTestFile();
FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
TypeAliasElement aliasElement = alias.declaredElement!;
FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
var namedType = fDeclaration.fields.type as NamedType;
assertType(namedType, 'int Function(bool)');
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, same(aliasElement));
expect(typeIdentifier.staticType, isNull);
List<TypeAnnotation> typeArguments = namedType.typeArguments!.arguments;
expect(typeArguments, hasLength(1));
_assertNamedTypeSimple(typeArguments[0], typeProvider.intType);
}
test_type_void() async {
addTestFile('''
main() {
void v;
}
''');
await resolveTestFile();
var statements = _getMainStatements(result);
var variableDeclarationStatement =
statements[0] as VariableDeclarationStatement;
var type = variableDeclarationStatement.variables.type as NamedType;
expect(type.type, isVoidType);
var namedType = type.name;
expect(namedType.staticType, isNull);
expect(namedType.staticElement, isNull);
}
test_typeAnnotation_prefixed() async {
newFile('$testPackageLibPath/a.dart', 'class A {}');
newFile('$testPackageLibPath/b.dart', "export 'a.dart';");
newFile('$testPackageLibPath/c.dart', "export 'a.dart';");
addTestFile(r'''
import 'b.dart' as b;
import 'c.dart' as c;
b.A a1;
c.A a2;
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
final bImport = unit.declaredElement!.library.libraryImports[0];
final cImport = unit.declaredElement!.library.libraryImports[1];
LibraryElement bLibrary = bImport.importedLibrary!;
LibraryElement aLibrary = bLibrary.libraryExports[0].exportedLibrary!;
ClassElement aClass = aLibrary.getClass('A')!;
{
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
var namedType = declaration.variables.type as NamedType;
var typeIdentifier = namedType.name as PrefixedIdentifier;
expect(typeIdentifier.staticElement, aClass);
expect(typeIdentifier.prefix.name, 'b');
expect(
typeIdentifier.prefix.staticElement,
same(bImport.prefix?.element),
);
expect(typeIdentifier.identifier.staticElement, aClass);
}
{
var declaration = unit.declarations[1] as TopLevelVariableDeclaration;
var namedType = declaration.variables.type as NamedType;
var typeIdentifier = namedType.name as PrefixedIdentifier;
expect(typeIdentifier.staticElement, aClass);
expect(typeIdentifier.prefix.name, 'c');
expect(
typeIdentifier.prefix.staticElement,
same(cImport.prefix?.element),
);
expect(typeIdentifier.identifier.staticElement, aClass);
}
}
test_typeLiteral() async {
addTestFile(r'''
void main() {
int;
F;
}
typedef void F(int p);
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
var fNode = unit.declarations[1] as FunctionTypeAlias;
TypeAliasElement fElement = fNode.declaredElement!;
var statements = _getMainStatements(result);
{
var statement = statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(typeProvider.intType.element2));
expect(identifier.staticType, typeProvider.typeType);
}
{
var statement = statements[1] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, same(fElement));
expect(identifier.staticType, typeProvider.typeType);
}
}
test_typeParameter() async {
addTestFile(r'''
class C<T> {
get t => T;
}
''');
await resolveTestFile();
var identifier = findNode.simple('T;');
assertElement(identifier, findElement.typeParameter('T'));
assertType(identifier, 'Type');
}
test_unresolved_instanceCreation_name_11() async {
addTestFile(r'''
int arg1, arg2;
main() {
new Foo<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, isDynamicType);
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typeIdentifier = namedType.name as SimpleIdentifier;
expect(typeIdentifier.staticElement, isNull);
expect(typeIdentifier.staticType, isNull);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
@failingTest
test_unresolved_instanceCreation_name_21() async {
addTestFile(r'''
int arg1, arg2;
main() {
new foo.Bar<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, isDynamicType);
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
expect(typePrefixed.staticElement, isNull);
expect(typePrefixed.staticType, isDynamicType);
SimpleIdentifier typePrefix = typePrefixed.prefix;
expect(typePrefix.staticElement, isNull);
expect(typePrefix.staticType, isNull);
SimpleIdentifier typeIdentifier = typePrefixed.identifier;
expect(typeIdentifier.staticElement, isNull);
expect(typeIdentifier.staticType, isDynamicType);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
@failingTest
test_unresolved_instanceCreation_name_22() async {
addTestFile(r'''
import 'dart:math' as foo;
int arg1, arg2;
main() {
new foo.Bar<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var unitElement = result.unit.declaredElement!;
var foo = unitElement.library.libraryImports[0].prefix?.element;
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, isDynamicType);
ConstructorName constructorName = creation.constructorName;
expect(constructorName.name, isNull);
NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
expect(typePrefixed.staticElement, isNull);
expect(typePrefixed.staticType, isDynamicType);
SimpleIdentifier typePrefix = typePrefixed.prefix;
expect(typePrefix.staticElement, same(foo));
expect(typePrefix.staticType, isNull);
SimpleIdentifier typeIdentifier = typePrefixed.identifier;
expect(typeIdentifier.staticElement, isNull);
expect(typeIdentifier.staticType, isDynamicType);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_instanceCreation_name_31() async {
addTestFile(r'''
int arg1, arg2;
main() {
new foo.Bar<int, double>.baz(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, isDynamicType);
ConstructorName constructorName = creation.constructorName;
NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
assertElementNull(typePrefixed);
assertTypeNull(typePrefixed);
SimpleIdentifier typePrefix = typePrefixed.prefix;
assertElementNull(typePrefix);
assertTypeNull(typePrefix);
SimpleIdentifier typeIdentifier = typePrefixed.identifier;
assertElementNull(typeIdentifier);
assertTypeNull(typeIdentifier);
assertElementNull(constructorName.name);
assertTypeNull(constructorName.name!);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_instanceCreation_name_32() async {
addTestFile(r'''
import 'dart:math' as foo;
int arg1, arg2;
main() {
new foo.Bar<int, double>.baz(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var unitElement = result.unit.declaredElement!;
var mathImport = unitElement.library.libraryImports[0];
var foo = mathImport.prefix?.element;
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, isDynamicType);
ConstructorName constructorName = creation.constructorName;
NamedType namedType = constructorName.type;
expect(namedType.type, isDynamicType);
var typePrefixed = namedType.name as PrefixedIdentifier;
assertElementNull(typePrefixed);
assertTypeNull(typePrefixed);
SimpleIdentifier typePrefix = typePrefixed.prefix;
assertElement(typePrefix, foo);
assertTypeNull(typePrefix);
SimpleIdentifier typeIdentifier = typePrefixed.identifier;
assertElementNull(typeIdentifier);
assertTypeNull(typeIdentifier);
assertElementNull(constructorName.name);
assertTypeNull(constructorName.name!);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_instanceCreation_name_33() async {
addTestFile(r'''
import 'dart:math' as foo;
int arg1, arg2;
main() {
new foo.Random<int, double>.baz(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var unitElement = result.unit.declaredElement!;
var mathImport = unitElement.library.libraryImports[0];
var foo = mathImport.prefix?.element;
var randomElement = mathImport.importedLibrary!.getClass('Random')!;
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var creation = statement.expression as InstanceCreationExpression;
expect(creation.staticType, interfaceTypeNone(randomElement));
ConstructorName constructorName = creation.constructorName;
NamedType namedType = constructorName.type;
assertType(namedType, 'Random');
var typePrefixed = namedType.name as PrefixedIdentifier;
assertElement(typePrefixed, randomElement);
assertTypeNull(typePrefixed);
SimpleIdentifier typePrefix = typePrefixed.prefix;
assertElement(typePrefix, foo);
assertTypeNull(typePrefix);
SimpleIdentifier typeIdentifier = typePrefixed.identifier;
assertElement(typeIdentifier, randomElement);
assertTypeNull(typeIdentifier);
assertElementNull(constructorName.name);
assertTypeNull(constructorName.name!);
assertTypeArguments(namedType.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(creation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_methodInvocation_noTarget() async {
addTestFile(r'''
int arg1, arg2;
main() {
bar<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.target, isNull);
expect(invocation.staticType, isDynamicType);
assertUnresolvedInvokeType(invocation.staticInvokeType!);
SimpleIdentifier name = invocation.methodName;
expect(name.staticElement, isNull);
expect(name.staticType, isDynamicType);
assertTypeArguments(invocation.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(invocation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_methodInvocation_target_resolved() async {
addTestFile(r'''
Object foo;
int arg1, arg2;
main() {
foo.bar<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
TopLevelVariableElement foo = _getTopLevelVariable(result, 'foo');
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
expect(invocation.staticType, isDynamicType);
assertUnresolvedInvokeType(invocation.staticInvokeType!);
var target = invocation.target as SimpleIdentifier;
expect(target.staticElement, same(foo.getter));
expect(target.staticType, typeProvider.objectType);
SimpleIdentifier name = invocation.methodName;
expect(name.staticElement, isNull);
assertUnresolvedInvokeType(name.typeOrThrow);
assertTypeArguments(invocation.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(invocation.argumentList,
[checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
}
test_unresolved_methodInvocation_target_unresolved() async {
addTestFile(r'''
int arg1, arg2;
main() {
foo.bar<int, double>(arg1, p2: arg2);
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var invocation = findNode.methodInvocation('foo.bar');
assertTypeDynamic(invocation);
assertUnresolvedInvokeType(invocation.staticInvokeType!);
var target = invocation.target as SimpleIdentifier;
assertElementNull(target);
assertTypeDynamic(target);
SimpleIdentifier name = invocation.methodName;
assertElementNull(name);
assertUnresolvedInvokeType(name.typeOrThrow);
assertTypeArguments(invocation.typeArguments!, [intType, doubleType]);
_assertInvocationArguments(invocation.argumentList,
[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;
main() {
foo.bar;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
TopLevelVariableElement foo = _getTopLevelVariable(result, 'foo');
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
expect(prefixed.staticElement, isNull);
expect(prefixed.staticType, isDynamicType);
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(foo.getter));
expect(prefix.staticType, typeProvider.objectType);
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, isNull);
expect(identifier.staticType, isDynamicType);
}
test_unresolved_prefixedIdentifier_prefix() async {
addTestFile(r'''
main() {
foo.bar;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var prefixed = statement.expression as PrefixedIdentifier;
expect(prefixed.staticElement, isNull);
expect(prefixed.staticType, isDynamicType);
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, isNull);
expect(prefix.staticType, isDynamicType);
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, isNull);
expect(identifier.staticType, isDynamicType);
}
test_unresolved_propertyAccess_1() async {
addTestFile(r'''
main() {
foo.bar.baz;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var propertyAccess = statement.expression as PropertyAccess;
expect(propertyAccess.staticType, isDynamicType);
{
var prefixed = propertyAccess.target as PrefixedIdentifier;
expect(prefixed.staticElement, isNull);
expect(prefixed.staticType, isDynamicType);
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, isNull);
expect(prefix.staticType, isDynamicType);
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, isNull);
expect(identifier.staticType, isDynamicType);
}
SimpleIdentifier property = propertyAccess.propertyName;
expect(property.staticElement, isNull);
expect(property.staticType, isDynamicType);
}
test_unresolved_propertyAccess_2() async {
addTestFile(r'''
Object foo;
main() {
foo.bar.baz;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
TopLevelVariableElement foo = _getTopLevelVariable(result, 'foo');
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var propertyAccess = statement.expression as PropertyAccess;
expect(propertyAccess.staticType, isDynamicType);
{
var prefixed = propertyAccess.target as PrefixedIdentifier;
expect(prefixed.staticElement, isNull);
expect(prefixed.staticType, isDynamicType);
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(foo.getter));
expect(prefix.staticType, typeProvider.objectType);
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, isNull);
expect(identifier.staticType, isDynamicType);
}
SimpleIdentifier property = propertyAccess.propertyName;
expect(property.staticElement, isNull);
expect(property.staticType, isDynamicType);
}
test_unresolved_propertyAccess_3() async {
addTestFile(r'''
Object foo;
main() {
foo.hashCode.baz;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
PropertyAccessorElement objectHashCode =
objectElement.getGetter('hashCode')!;
TopLevelVariableElement foo = _getTopLevelVariable(result, 'foo');
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var propertyAccess = statement.expression as PropertyAccess;
expect(propertyAccess.staticType, isDynamicType);
{
var prefixed = propertyAccess.target as PrefixedIdentifier;
assertPrefixedIdentifier(
prefixed,
element: elementMatcher(
objectHashCode,
isLegacy: isLegacyLibrary,
),
type: 'int',
);
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(foo.getter));
expect(prefix.staticType, typeProvider.objectType);
SimpleIdentifier identifier = prefixed.identifier;
assertSimpleIdentifier(
identifier,
element: elementMatcher(
objectHashCode,
isLegacy: isLegacyLibrary,
),
type: 'int',
);
}
SimpleIdentifier property = propertyAccess.propertyName;
expect(property.staticElement, isNull);
expect(property.staticType, isDynamicType);
}
test_unresolved_redirectingFactory_1() async {
addTestFile(r'''
class A {
factory A() = B;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
}
test_unresolved_redirectingFactory_22() async {
addTestFile(r'''
class A {
factory A() = B.named;
}
class B {}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
var bRef = findNode.simple('B.');
assertElement(bRef, findElement.class_('B'));
assertTypeNull(bRef);
var namedRef = findNode.simple('named;');
assertElementNull(namedRef);
assertTypeNull(namedRef);
}
test_unresolved_simpleIdentifier() async {
addTestFile(r'''
main() {
foo;
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
List<Statement> statements = _getMainStatements(result);
var statement = statements[0] as ExpressionStatement;
var identifier = statement.expression as SimpleIdentifier;
expect(identifier.staticElement, isNull);
expect(identifier.staticType, isDynamicType);
}
/// Assert that the [argument] is associated with the [expected]. If the
/// [argument] is a [NamedExpression], the name must be resolved to the
/// parameter.
void _assertArgumentToParameter(
Expression argument, ParameterElement expected,
{DartType? memberType}) {
ParameterElement actual = argument.staticParameterElement!;
if (memberType != null) {
expect(actual.type, memberType);
}
expect(actual.declaration, same(expected));
if (argument is NamedExpression) {
SimpleIdentifier name = argument.name.label;
expect(name.staticElement, same(actual));
expect(name.staticType, isNull);
}
}
/// Assert that the [argument] has the [expectedType]. If the [argument] is
/// a [NamedExpression], the name must be resolved to the same parameter.
void _assertArgumentToParameter2(Expression argument, String expectedType) {
ParameterElement actual = argument.staticParameterElement!;
assertType(actual.type, expectedType);
if (argument is NamedExpression) {
SimpleIdentifier name = argument.name.label;
expect(name.staticElement, same(actual));
expect(name.staticType, isNull);
}
}
/// Assert that the given [creation] creates instance of the [classElement].
/// Limitations: no import prefix, no type arguments, unnamed constructor.
void _assertConstructorInvocation(
InstanceCreationExpression creation, ClassElement classElement) {
assertType(creation, classElement.name);
var constructorName = creation.constructorName;
var constructorElement = classElement.unnamedConstructor;
expect(constructorName.staticElement, constructorElement);
var namedType = constructorName.type;
expect(namedType.typeArguments, isNull);
var typeIdentifier = namedType.name as SimpleIdentifier;
assertElement(typeIdentifier, classElement);
assertTypeNull(typeIdentifier);
// Only unnamed constructors are supported now.
expect(constructorName.name, isNull);
}
void _assertDefaultParameter(
DefaultFormalParameter node, ParameterElement element,
{String? name, int? offset, ParameterKind? kind, DartType? type}) {
expect(node, isNotNull);
var normalNode = node.parameter as SimpleFormalParameter;
_assertSimpleParameter(normalNode, element,
name: name, offset: offset, kind: kind, type: type);
}
/// Test that [argumentList] has exactly two arguments - required `arg1`, and
/// unresolved named `arg2`, both are the reference to top-level variables.
void _assertInvocationArguments(ArgumentList argumentList,
List<void Function(Expression)> argumentCheckers) {
expect(argumentList.arguments, hasLength(argumentCheckers.length));
for (int i = 0; i < argumentCheckers.length; i++) {
argumentCheckers[i](argumentList.arguments[i]);
}
}
void _assertNamedTypeSimple(TypeAnnotation namedType, InterfaceType type) {
namedType as NamedType;
expect(namedType.type, type);
var identifier = namedType.name as SimpleIdentifier;
expect(identifier.staticElement, same(type.element2));
expect(identifier.staticType, isNull);
}
void _assertParameterElement(ParameterElement element,
{String? name, int? offset, ParameterKind? kind, DartType? type}) {
expect(element, isNotNull);
expect(name, isNotNull);
expect(offset, isNotNull);
expect(kind, isNotNull);
expect(type, isNotNull);
expect(element.name, name);
expect(element.nameOffset, offset);
// ignore: deprecated_member_use_from_same_package
expect(element.parameterKind, kind);
expect(element.type, type);
}
void _assertSimpleParameter(
SimpleFormalParameter node, ParameterElement element,
{String? name, int? offset, ParameterKind? kind, DartType? type}) {
_assertParameterElement(element,
name: name, offset: offset, kind: kind, type: type);
expect(node, isNotNull);
expect(node.declaredElement, same(element));
var namedType = node.type as NamedType?;
if (namedType != null) {
expect(namedType.type, type);
if (type is InterfaceType) {
expect(namedType.name.staticElement, same(type.element2));
} else if (type is TypeParameterType) {
expect(namedType.name.staticElement, same(type.element2));
} else {
throw UnimplementedError();
}
}
}
List<Statement> _getMainStatements(ResolvedUnitResult result) {
for (var declaration in result.unit.declarations) {
if (declaration is FunctionDeclaration &&
declaration.name.lexeme == 'main') {
var body = declaration.functionExpression.body as BlockFunctionBody;
return body.block.statements;
}
}
fail('Not found main() in ${result.unit}');
}
TopLevelVariableElement _getTopLevelVariable(
ResolvedUnitResult result, String name) {
for (var variable in result.unit.declaredElement!.topLevelVariables) {
if (variable.name == name) {
return variable;
}
}
fail('Not found $name');
}
}