blob: 3ba26a14e4b93d65abc92e2d3e7ba2af24afd215 [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/analysis/experiments.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) {
VariableElement element = node.staticElement;
assertType(element.type, expected);
}
void assertDeclaredVariableTypeDynamic(SimpleIdentifier node) {
VariableElement element = node.staticElement;
expect(element.type, isDynamicType);
}
/// Test that [argumentList] has exactly two type items `int` and `double`.
void assertTypeArguments(
TypeArgumentList argumentList, List<DartType> expectedTypes) {
expect(argumentList.arguments, hasLength(expectedTypes.length));
for (int i = 0; i < expectedTypes.length; i++) {
_assertTypeNameSimple(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);
SimpleIdentifier expression = named.expression;
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);
ExpressionStatement statement = statements[0];
AdjacentStrings expression = statement.expression;
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();
TopLevelVariableDeclaration myDeclaration = result.unit.declarations[0];
VariableDeclaration myVariable = myDeclaration.variables.variables[0];
TopLevelVariableElement myElement = myVariable.declaredElement;
void assertMyAnnotation(AnnotatedNode node) {
Annotation annotation = node.metadata[0];
expect(annotation.element, same(myElement.getter));
SimpleIdentifier identifier_1 = annotation.name;
expect(identifier_1.staticElement, same(myElement.getter));
expect(identifier_1.staticType, isNull);
}
{
ClassDeclaration classNode = result.unit.declarations[1];
assertMyAnnotation(classNode);
{
FieldDeclaration node = classNode.members[0];
assertMyAnnotation(node);
}
{
ConstructorDeclaration node = classNode.members[1];
assertMyAnnotation(node);
}
{
MethodDeclaration node = classNode.members[2];
assertMyAnnotation(node);
}
}
{
TopLevelVariableDeclaration node = result.unit.declarations[2];
assertMyAnnotation(node);
}
{
FunctionDeclaration node = result.unit.declarations[3];
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'));
SimpleIdentifier aRef = annotation.name;
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'));
SimpleIdentifier aRef = annotation.name;
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'));
SimpleIdentifier aRef = annotation.name;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_part() async {
newFile('$testPackageLibPath/a.dart', content: 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'));
SimpleIdentifier aRef = annotation.name;
assertElement(aRef, findElement.topGet('a'));
assertTypeNull(aRef);
}
test_annotation_onDirective_partOf() async {
newFile('$testPackageLibPath/a.dart', content: r'''
part 'test.dart';
''');
addTestFile(r'''
@a
part of 'a.dart';
const a = 1;
''');
await resolveTestFile();
var directive = findNode.partOf('a.dart');
expect(directive.metadata, hasLength(1));
Annotation annotation = directive.metadata[0];
expect(annotation.element, findElement.topGet('a'));
SimpleIdentifier aRef = annotation.name;
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);
SimpleIdentifier ref = annotation.name;
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();
ClassDeclaration c = result.unit.declarations[0];
ConstructorDeclaration constructor = c.members[1];
ConstructorElement element = constructor.declaredElement;
FunctionDeclaration main = result.unit.declarations[1];
VariableDeclarationStatement statement =
(main.functionExpression.body as BlockFunctionBody).block.statements[0];
Annotation annotation = statement.variables.metadata[0];
expect(annotation.element, same(element));
SimpleIdentifier identifier_1 = annotation.name;
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();
TopLevelVariableDeclaration myDeclaration = result.unit.declarations[0];
VariableDeclaration myVariable = myDeclaration.variables.variables[0];
TopLevelVariableElement myElement = myVariable.declaredElement;
ClassDeclaration classNode = result.unit.declarations[1];
MethodDeclaration node = classNode.members[0];
VariableDeclarationStatement statement =
(node.body as BlockFunctionBody).block.statements[0];
Annotation annotation = statement.variables.metadata[0];
expect(annotation.element, same(myElement.getter));
SimpleIdentifier identifier_1 = annotation.name;
expect(identifier_1.staticElement, same(myElement.getter));
assertTypeNull(identifier_1);
}
test_annotation_prefixed_classField() async {
newFile('$testPackageLibPath/a.dart', content: r'''
class A {
static const a = 1;
}
''');
addTestFile(r'''
import 'a.dart' as p;
@p.A.a
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement.library.imports[0];
PrefixElement aPrefix = aImport.prefix;
LibraryElement aLibrary = aImport.importedLibrary;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getType('A');
var aGetter = aClass.getField('a').getter;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(aGetter));
PrefixedIdentifier prefixed = annotation.name;
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);
expect(annotation.constructorName.staticType, typeProvider.intType);
expect(annotation.arguments, isNull);
}
test_annotation_prefixed_constructor() async {
newFile('$testPackageLibPath/a.dart', content: 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;
ImportElement aImport = unit.declaredElement.library.imports[0];
PrefixElement aPrefix = aImport.prefix;
LibraryElement aLibrary = aImport.importedLibrary;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getType('A');
ConstructorElement constructor = aClass.unnamedConstructor;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
PrefixedIdentifier prefixed = annotation.name;
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', content: 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;
ImportElement aImport = unit.declaredElement.library.imports[0];
PrefixElement aPrefix = aImport.prefix;
LibraryElement aLibrary = aImport.importedLibrary;
CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
ClassElement aClass = aUnitElement.getType('A');
ConstructorElement constructor = aClass.getNamedConstructor('named');
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
PrefixedIdentifier prefixed = annotation.name;
expect(prefixed.prefix.staticElement, same(aPrefix));
expect(prefixed.prefix.staticType, isNull);
expect(prefixed.identifier.staticElement, same(aClass));
expect(prefixed.prefix.staticType, isNull);
SimpleIdentifier constructorName = annotation.constructorName;
expect(constructorName.staticElement, same(constructor));
assertType(constructorName.staticType, 'A Function(int, {int b})');
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', content: r'''
const topAnnotation = 1;
''');
addTestFile(r'''
import 'a.dart' as p;
@p.topAnnotation
main() {}
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement.library.imports[0];
PrefixElement aPrefix = aImport.prefix;
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));
PrefixedIdentifier prefixed = annotation.name;
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.getType('A');
var aGetter = aClass.getField('a').getter;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(aGetter));
PrefixedIdentifier prefixed = annotation.name;
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.getType('A');
ConstructorElement constructor = aClass.unnamedConstructor;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
SimpleIdentifier name = annotation.name;
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.getType('A');
ConstructorElement constructor = aClass.constructors.single;
Annotation annotation = unit.declarations[0].metadata.single;
expect(annotation.element, same(constructor));
PrefixedIdentifier prefixed = annotation.name;
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];
InstanceCreationExpression constC = atD.arguments.arguments[0];
expect(atD.name.staticElement, elementD);
expect(atD.element, constructorD);
expect(constC.staticType, interfaceTypeStar(elementC));
var constructorName = constC.constructorName;
expect(constructorName.staticElement, constructorC);
expect(constructorName.type.type, interfaceTypeStar(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();
TopLevelVariableDeclaration declaration_1 = result.unit.declarations[0];
VariableDeclaration variable_1 = declaration_1.variables.variables[0];
TopLevelVariableElement element_1 = variable_1.declaredElement;
TopLevelVariableDeclaration declaration_2 = result.unit.declarations[1];
VariableDeclaration variable_2 = declaration_2.variables.variables[0];
TopLevelVariableElement element_2 = variable_2.declaredElement;
FunctionDeclaration main = result.unit.declarations[2];
Annotation annotation_1 = main.metadata[0];
expect(annotation_1.element, same(element_1.getter));
SimpleIdentifier identifier_1 = annotation_1.name;
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));
SimpleIdentifier identifier_2 = annotation_2.name;
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;
}
''');
NodeList<Statement> statements = _getMainStatements(result);
// num v = 42;
VariableElement vElement;
{
VariableDeclarationStatement statement = statements[0];
vElement = statement.variables.variables[0].name.staticElement;
expect(vElement.type, typeProvider.numType);
}
// v as int;
{
ExpressionStatement statement = statements[1];
AsExpression asExpression = statement.expression;
expect(asExpression.staticType, typeProvider.intType);
SimpleIdentifier target = asExpression.expression;
expect(target.staticElement, vElement);
expect(target.staticType, typeProvider.numType);
TypeName intName = asExpression.type;
expect(intName.name.staticElement, typeProvider.intType.element);
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);
VariableDeclarationStatement statement = mainStatements[0];
VariableDeclaration vNode = statement.variables.variables[0];
VariableElement vElement = vNode.declaredElement;
expect(vElement.type, typeProvider.intType);
BinaryExpression value = vNode.initializer;
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 {
var latestLanguageVersionStr = '${ExperimentStatus.currentVersion.major}.'
'${ExperimentStatus.currentVersion.minor}';
writeTestPackageConfig(
PackageConfigFileBuilder(),
languageVersion: latestLanguageVersionStr,
);
writeTestPackageAnalysisOptionsFile(
AnalysisOptionsFileConfig(
experiments: [
EnableString.non_nullable,
EnableString.triple_shift,
],
),
);
await resolveTestCode('''
class A {
A operator >>>(int amount) => this;
}
f(A a) {
a >>> 3;
}
''');
assertBinaryExpression(
findNode.binary('>>> 3'),
element: findElement.method('>>>'),
type: 'A',
);
}
test_binaryExpression_ifNull() async {
String content = r'''
int x = 3;
main() {
1.2 ?? x;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
ExpressionStatement statement = mainStatements[0];
BinaryExpression binary = statement.expression;
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);
{
ExpressionStatement statement = statements[0];
BinaryExpression binaryExpression = statement.expression;
expect(binaryExpression.staticElement, isNull);
expect(binaryExpression.staticType, typeProvider.boolType);
}
{
ExpressionStatement statement = statements[1];
BinaryExpression binaryExpression = statement.expression;
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);
ExpressionStatement statement = statements[0];
BinaryExpression expression = statement.expression;
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);
ExpressionStatement statement = statements[0];
CascadeExpression expression = statement.expression;
expect(expression.target.staticType, isNotNull);
NodeList<Expression> sections = expression.cascadeSections;
MethodInvocation a = sections[0];
expect(a.methodName.staticElement, isNotNull);
expect(a.staticType, isNotNull);
MethodInvocation b = sections[1];
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();
FunctionDeclaration mainDeclaration = result.unit.declarations[0];
FunctionElement mainElement = mainDeclaration.declaredElement;
BlockFunctionBody mainBody = mainDeclaration.functionExpression.body;
List<Statement> mainStatements = mainBody.block.statements;
VariableDeclarationStatement itemsStatement = mainStatements[0];
var itemsElement = itemsStatement.variables.variables[0].declaredElement;
// First closure.
ParameterElement itemElement1;
{
ExpressionStatement forStatement = mainStatements[1];
MethodInvocation forInvocation = forStatement.expression;
SimpleIdentifier forTarget = forInvocation.target;
expect(forTarget.staticElement, itemsElement);
var closureTypeStr = 'Null Function(int)';
FunctionExpression closure = forInvocation.argumentList.arguments[0];
FunctionElementImpl closureElement = closure.declaredElement;
expect(closureElement.enclosingElement, same(mainElement));
ParameterElement itemElement = closureElement.parameters[0];
itemElement1 = itemElement;
expect(closureElement.returnType, typeProvider.nullType);
assertType(closureElement.type, closureTypeStr);
expect(closure.staticType, same(closureElement.type));
List<FormalParameter> closureParameters = closure.parameters.parameters;
expect(closureParameters, hasLength(1));
SimpleFormalParameter itemNode = closureParameters[0];
_assertSimpleParameter(itemNode, itemElement,
name: 'item',
offset: 56,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
BlockFunctionBody closureBody = closure.body;
List<Statement> closureStatements = closureBody.block.statements;
ExpressionStatement itemStatement = closureStatements[0];
SimpleIdentifier itemIdentifier = itemStatement.expression;
expect(itemIdentifier.staticElement, itemElement);
expect(itemIdentifier.staticType, typeProvider.intType);
}
// Second closure, same names, different elements.
{
ExpressionStatement forStatement = mainStatements[2];
MethodInvocation forInvocation = forStatement.expression;
SimpleIdentifier forTarget = forInvocation.target;
expect(forTarget.staticElement, itemsElement);
var closureTypeStr = 'Null Function(int)';
FunctionExpression closure = forInvocation.argumentList.arguments[0];
FunctionElementImpl closureElement = closure.declaredElement;
expect(closureElement.enclosingElement, same(mainElement));
ParameterElement itemElement = closureElement.parameters[0];
expect(itemElement, isNot(same(itemElement1)));
expect(closureElement.returnType, typeProvider.nullType);
assertType(closureElement.type, closureTypeStr);
expect(closure.staticType, same(closureElement.type));
List<FormalParameter> closureParameters = closure.parameters.parameters;
expect(closureParameters, hasLength(1));
SimpleFormalParameter itemNode = closureParameters[0];
_assertSimpleParameter(itemNode, itemElement,
name: 'item',
offset: 97,
kind: ParameterKind.REQUIRED,
type: typeProvider.intType);
BlockFunctionBody closureBody = closure.body;
List<Statement> closureStatements = closureBody.block.statements;
ExpressionStatement itemStatement = closureStatements[0];
SimpleIdentifier itemIdentifier = itemStatement.expression;
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>()');
FunctionElementImpl closureElement = closure.declaredElement;
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;
ClassDeclaration c = unit.declarations[0];
FieldDeclaration declaration = c.members[0];
VariableDeclaration field = declaration.fields.variables[0];
FunctionExpressionInvocation invocation = field.initializer;
FunctionExpression closure = invocation.function.unParenthesized;
FunctionElementImpl closureElement = closure.declaredElement;
expect(closureElement, isNotNull);
}
test_closure_inTopLevelVariable() async {
addTestFile(r'''
var v = (() => 42)();
''');
await resolveTestFile();
CompilationUnit unit = result.unit;
TopLevelVariableDeclaration declaration = unit.declarations[0];
VariableDeclaration variable = declaration.variables.variables[0];
FunctionExpressionInvocation invocation = variable.initializer;
FunctionExpression closure = invocation.function.unParenthesized;
FunctionElementImpl closureElement = closure.declaredElement;
expect(closureElement, isNotNull);
}
test_conditionalExpression() async {
String content = r'''
void main() {
true ? 1 : 2.3;
}
''';
addTestFile(content);
await resolveTestFile();
List<Statement> statements = _getMainStatements(result);
ExpressionStatement statement = statements[0];
ConditionalExpression expression = statement.expression;
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();
ClassDeclaration cNode = result.unit.declarations[0];
ConstructorDeclaration constructorNode = cNode.members[0];
ParameterElement pElement = constructorNode.declaredElement.parameters[0];
BlockFunctionBody constructorBody = constructorNode.body;
ExpressionStatement pStatement = constructorBody.block.statements[0];
SimpleIdentifier pIdentifier = pStatement.expression;
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();
ClassDeclaration cNode = result.unit.declarations[0];
ClassElement cElement = cNode.declaredElement;
FieldElement fElement = cElement.getField('f');
ConstructorDeclaration constructorNode = cNode.members[1];
ParameterElement pParameterElement =
constructorNode.declaredElement.parameters[0];
{
ConstructorFieldInitializer initializer = constructorNode.initializers[0];
expect(initializer.fieldName.staticElement, same(fElement));
SimpleIdentifier expression = initializer.expression;
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();
ClassDeclaration aNode = result.unit.declarations[0];
ClassElement aElement = aNode.declaredElement;
ClassDeclaration bNode = result.unit.declarations[1];
{
ConstructorDeclaration constructor = bNode.members[0];
SuperConstructorInvocation initializer = constructor.initializers[0];
expect(initializer.staticElement, same(aElement.unnamedConstructor));
expect(initializer.constructorName, isNull);
}
{
var namedConstructor = aElement.getNamedConstructor('named');
ConstructorDeclaration constructor = bNode.members[1];
SuperConstructorInvocation initializer = constructor.initializers[0];
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();
ClassDeclaration cNode = result.unit.declarations[0];
ClassElement cElement = cNode.declaredElement;
{
var unnamedConstructor = cElement.constructors[0];
ConstructorDeclaration constructor = cNode.members[2];
RedirectingConstructorInvocation initializer =
constructor.initializers[0];
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];
ConstructorDeclaration constructor = cNode.members[3];
RedirectingConstructorInvocation initializer =
constructor.initializers[0];
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);
ClassDeclaration aNode = result.unit.declarations[0];
ClassElement aElement = aNode.declaredElement;
ClassDeclaration bNode = result.unit.declarations[1];
{
ConstructorElement aUnnamed = aElement.constructors[0];
ConstructorDeclaration constructor = bNode.members[0];
ConstructorElement element = constructor.declaredElement;
expect(element.redirectedConstructor, same(aUnnamed));
var constructorName = constructor.redirectedConstructor;
expect(constructorName.staticElement, same(aUnnamed));
TypeName typeName = constructorName.type;
expect(typeName.type, interfaceTypeStar(aElement));
SimpleIdentifier identifier = typeName.name;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name, isNull);
}
{
ConstructorElement aNamed = aElement.constructors[1];
ConstructorDeclaration constructor = bNode.members[1];
ConstructorElement element = constructor.declaredElement;
expect(element.redirectedConstructor, same(aNamed));
var constructorName = constructor.redirectedConstructor;
expect(constructorName.staticElement, same(aNamed));
TypeName typeName = constructorName.type;
expect(typeName.type, interfaceTypeStar(aElement));
SimpleIdentifier identifier = typeName.name;
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);
ClassDeclaration aNode = result.unit.declarations[0];
ClassElement aElement = aNode.declaredElement;
ClassDeclaration bNode = result.unit.declarations[1];
TypeParameterType uType =
typeParameterTypeStar(bNode.declaredElement.typeParameters[0]);
InterfaceType auType = aElement.instantiate(
typeArguments: [uType],
nullabilitySuffix: NullabilitySuffix.star,
);
{
ConstructorElement expectedElement = aElement.constructors[0];
ConstructorDeclaration constructor = bNode.members[0];
ConstructorElement element = constructor.declaredElement;
ConstructorMember actualMember = element.redirectedConstructor;
assertMember(actualMember, expectedElement, {'T': 'U'});
var constructorName = constructor.redirectedConstructor;
expect(constructorName.staticElement, same(actualMember));
TypeName typeName = constructorName.type;
expect(typeName.type, auType);
SimpleIdentifier identifier = typeName.name;
expect(identifier.staticElement, same(aElement));
expect(identifier.staticType, isNull);
expect(constructorName.name, isNull);
}
{
ConstructorElement expectedElement = aElement.constructors[1];
ConstructorDeclaration constructor = bNode.members[1];
ConstructorElement element = constructor.declaredElement;
ConstructorMember actualMember = element.redirectedConstructor;
assertMember(actualMember, expectedElement, {'T': 'U'});
var constructorName = constructor.redirectedConstructor;
expect(constructorName.staticElement, same(actualMember));
TypeName typeName = constructorName.type;
expect(typeName.type, auType);
SimpleIdentifier identifier = typeName.name;
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()');
SimpleIdentifier target = invocation.target;
assertElement(target, import.prefix);
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()');
SimpleIdentifier target = invocation.target;
assertElement(target, import.prefix);
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);
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', content: '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');
TopLevelVariableElement v = (import.importedLibrary.publicNamespace.get('v')
as PropertyAccessorElement)
.variable;
{
var prefixed = findNode.prefixed('a.v;');
assertElement(prefixed, v.getter);
assertType(prefixed, 'int');
assertElement(prefixed.prefix, import.prefix);
assertType(prefixed.prefix, null);
assertElement(prefixed.identifier, v.getter);
assertType(prefixed.identifier, 'int');
}
{
var prefixed = findNode.prefixed('a.v = 1;');
if (hasAssignmentLeftResolution) {
assertElement(prefixed, v.setter);
assertType(prefixed, 'int');
} else {
assertElementNull(prefixed);
assertTypeNull(prefixed);
}
assertElement(prefixed.prefix, import.prefix);
assertType(prefixed.prefix, null);
if (hasAssignmentLeftResolution) {
assertElement(prefixed.identifier, v.setter);
assertType(prefixed.identifier, 'int');
} else {
assertElementNull(prefixed.identifier);
assertTypeNull(prefixed.identifier);
}
}
}
test_directive_export() async {
newFile('$testPackageLibPath/a.dart', content: 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');
PropertyAccessorElement getter = namespace.get('myVar');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
PropertyAccessorElement getter = namespace.get('myGetter');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
PropertyAccessorElement getter = namespace.get('mySetter=');
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', content: 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');
PropertyAccessorElement getter = namespace.get('myVar');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
PropertyAccessorElement getter = namespace.get('myGetter');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
PropertyAccessorElement getter = namespace.get('mySetter=');
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', content: 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');
PropertyAccessorElement getter = namespace.get('myVar');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('myGetter');
PropertyAccessorElement getter = namespace.get('myGetter');
assertElement(ref, getter.variable);
assertType(ref, null);
}
{
var ref = findNode.simple('mySetter');
PropertyAccessorElement getter = namespace.get('mySetter=');
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();
EnumDeclaration enumNode = result.unit.declarations[0];
ClassElement enumElement = enumNode.declaredElement;
List<Statement> mainStatements = _getMainStatements(result);
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
assertInvokeType(invocation, 'String Function()');
MethodElement methodElement = invocation.methodName.staticElement;
expect(methodElement.name, 'toString');
expect(methodElement.enclosingElement, same(enumElement));
}
test_error_unresolvedTypeAnnotation() async {
String content = r'''
main() {
Foo<int> v = null;
}
''';
addTestFile(content);
await resolveTestFile();
var statements = _getMainStatements(result);
VariableDeclarationStatement statement = statements[0];
TypeName typeName = statement.variables.type;
expect(typeName.type, isDynamicType);
expect(typeName.typeArguments.arguments[0].type, typeProvider.intType);
VariableDeclaration vNode = statement.variables.variables[0];
expect(vNode.name.staticType, isNull);
expect(vNode.declaredElement.type, isDynamicType);
}
test_field_context() async {
addTestFile(r'''
class C<T> {
var f = <T>[];
}
''');
await resolveTestFile();
ClassDeclaration cNode = result.unit.declarations[0];
var tElement = cNode.declaredElement.typeParameters[0];
FieldDeclaration fDeclaration = cNode.members[0];
VariableDeclaration fNode = fDeclaration.fields.variables[0];
FieldElement fElement = fNode.declaredElement;
expect(
fElement.type, typeProvider.listType2(typeParameterTypeStar(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;');
if (hasAssignmentLeftResolution) {
assertMember(fRef, findElement.setter('f'), {'T': 'int'});
assertType(fRef, 'int');
} else {
assertElementNull(fRef);
assertTypeNull(fRef);
}
}
}
test_formalParameter_functionTyped() async {
addTestFile(r'''
class A {
A(String p(int a));
}
''');
await resolveTestFile();
ClassDeclaration clazz = result.unit.declarations[0];
ConstructorDeclaration constructor = clazz.members[0];
List<FormalParameter> parameters = constructor.parameters.parameters;
FunctionTypedFormalParameter p = parameters[0];
expect(p.declaredElement, same(constructor.declaredElement.parameters[0]));
{
FunctionType type = (p.identifier.staticElement as ParameterElement).type;
expect(type.returnType, typeProvider.stringType);
expect(type.parameters, hasLength(1));
expect(type.parameters[0].type, typeProvider.intType);
}
_assertTypeNameSimple(p.returnType, typeProvider.stringType);
{
SimpleFormalParameter a = p.parameters.parameters[0];
_assertTypeNameSimple(a.type, typeProvider.intType);
expect(a.identifier.staticType, isNull);
}
}
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();
ClassDeclaration clazz = result.unit.declarations[0];
FieldDeclaration fDeclaration = clazz.members[0];
VariableDeclaration fNode = fDeclaration.fields.variables[0];
FieldElement fElement = fNode.declaredElement;
ConstructorDeclaration constructor = clazz.members[1];
FieldFormalParameterElement pElement =
constructor.declaredElement.parameters[0];
expect(pElement.field, same(fElement));
List<FormalParameter> parameters = constructor.parameters.parameters;
FieldFormalParameter p = parameters[0];
expect(p.declaredElement, same(pElement));
expect(p.identifier.staticElement, same(pElement));
assertType(p.identifier.staticType, 'String Function(int)');
{
FunctionType type = p.identifier.staticType;
expect(type.returnType, typeProvider.stringType);
expect(type.parameters, hasLength(1));
expect(type.parameters[0].type, typeProvider.intType);
}
_assertTypeNameSimple(p.type, typeProvider.stringType);
{
SimpleFormalParameter a = p.parameters.parameters[0];
_assertTypeNameSimple(a.type, typeProvider.intType);
expect(a.identifier.staticType, isNull);
}
}
test_formalParameter_simple_fieldFormal() async {
addTestFile(r'''
class A {
int f;
A(this.f);
}
''');
await resolveTestFile();
ClassDeclaration clazz = result.unit.declarations[0];
FieldDeclaration fDeclaration = clazz.members[0];
VariableDeclaration fNode = fDeclaration.fields.variables[0];
FieldElement fElement = fNode.declaredElement;
ConstructorDeclaration constructor = clazz.members[1];
List<FormalParameter> parameters = constructor.parameters.parameters;
FieldFormalParameterElement parameterElement =
constructor.declaredElement.parameters[0];
expect(parameterElement.field, same(fElement));
FieldFormalParameter parameterNode = parameters[0];
expect(parameterNode.type, isNull);
expect(parameterNode.declaredElement, same(parameterElement));
expect(parameterNode.identifier.staticElement, same(parameterElement));
expect(parameterNode.identifier.staticType, typeProvider.intType);
}
test_formalParameter_simple_fieldFormal_typed() async {
addTestFile(r'''
class A {
int f;
A(int this.f);
}
''');
await resolveTestFile();
ClassDeclaration clazz = result.unit.declarations[0];
FieldDeclaration fDeclaration = clazz.members[0];
VariableDeclaration fNode = fDeclaration.fields.variables[0];
FieldElement fElement = fNode.declaredElement;
ConstructorDeclaration constructor = clazz.members[1];
List<FormalParameter> parameters = constructor.parameters.parameters;
FieldFormalParameterElement parameterElement =
constructor.declaredElement.parameters[0];
expect(parameterElement.field, same(fElement));
FieldFormalParameter parameterNode = parameters[0];
_assertTypeNameSimple(parameterNode.type, typeProvider.intType);
expect(parameterNode.declaredElement, same(parameterElement));
expect(parameterNode.identifier.staticElement, same(parameterElement));
expect(parameterNode.identifier.staticType, typeProvider.intType);
}
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();
// ClassDeclaration aNode = result.unit.declarations[0];
// ClassElement eElement = aNode.declaredElement;
// MethodElement mElement = eElement.getMethod('m');
List<Statement> mainStatements = _getMainStatements(result);
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
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);
ExpressionStatement statement = statements[0];
FunctionExpressionInvocation invocation = statement.expression;
expect(invocation.staticElement, isNull);
assertInvokeType(invocation, 'int Function(String)');
expect(invocation.staticType, typeProvider.intType);
List<TypeAnnotation> typeArguments = invocation.typeArguments.arguments;
expect(typeArguments, hasLength(1));
_assertTypeNameSimple(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();
assertTypeNull(findNode.simple('f;'));
var fType = findElement.localVar('f').type as FunctionType;
var fTypeTypeParameter = fType.typeFormals[0];
var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
expect(fTypeParameter.element, same(fTypeTypeParameter));
var tRef = findNode.simple('T>');
var functionTypeNode = tRef.parent.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.listType2(intType);
List<Statement> mainStatements = _getMainStatements(result);
VariableElement itemsElement;
{
VariableDeclarationStatement statement = mainStatements[0];
VariableDeclaration itemsNode = statement.variables.variables[0];
itemsElement = itemsNode.declaredElement;
expect(itemsElement.type, listIntType);
}
ExpressionStatement statement = mainStatements[1];
IndexExpression indexExpression = statement.expression;
expect(indexExpression.staticType, intType);
MethodMember actualElement = indexExpression.staticElement;
MethodMember expectedElement = listIntType.getMethod('[]');
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;
ClassDeclaration cNode = unit.declarations[0];
ClassElement cElement = cNode.declaredElement;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
{
TopLevelVariableDeclaration aDeclaration = unit.declarations[1];
VariableDeclaration aNode = aDeclaration.variables.variables[0];
InstanceCreationExpression value = aNode.initializer;
expect(value.staticType, interfaceTypeStar(cElement));
var constructorName = value.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
Identifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
{
TopLevelVariableDeclaration bDeclaration = unit.declarations[2];
VariableDeclaration bNode = bDeclaration.variables.variables[0];
InstanceCreationExpression value = bNode.initializer;
expect(value.staticType, interfaceTypeStar(cElement));
var constructorName = value.constructorName;
expect(constructorName.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
SimpleIdentifier typeIdentifier = typeName.name;
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;
ClassDeclaration xNode = unit.declarations[0];
ClassElement xElement = xNode.declaredElement;
ConstructorElement constructorElement = xElement.constructors[0];
TopLevelVariableDeclaration vDeclaration = unit.declarations[1];
VariableDeclaration vNode = vDeclaration.variables.variables[0];
InstanceCreationExpression creation = vNode.initializer;
List<Expression> arguments = creation.argumentList.arguments;
expect(creation.staticType, interfaceTypeStar(xElement));
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, constructorElement);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
Identifier typeIdentifier = typeName.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;
ClassDeclaration cNode = unit.declarations[0];
ClassElement cElement = cNode.declaredElement;
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
{
TopLevelVariableDeclaration aDeclaration = unit.declarations[1];
VariableDeclaration aNode = aDeclaration.variables.variables[0];
InstanceCreationExpression value = aNode.initializer;
expect(value.staticType, interfaceTypeStar(cElement));
var constructorName = value.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
Identifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
Expression argument = value.argumentList.arguments[0];
_assertArgumentToParameter(argument, defaultConstructor.parameters[0]);
}
{
TopLevelVariableDeclaration bDeclaration = unit.declarations[2];
VariableDeclaration bNode = bDeclaration.variables.variables[0];
InstanceCreationExpression value = bNode.initializer;
expect(value.staticType, interfaceTypeStar(cElement));
var constructorName = value.constructorName;
expect(constructorName.staticElement, namedConstructor);
expect(constructorName.name.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
SimpleIdentifier typeIdentifier = typeName.name;
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', content: 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;
ImportElement aImport = unit.declaredElement.library.imports[0];
LibraryElement aLibrary = aImport.importedLibrary;
ClassElement cElement = aLibrary.getType('C');
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
var statements = _getMainStatements(result);
{
var cTypeInt = cElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeInt);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
PrefixedIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix));
expect(typePrefix.staticType, isNull);
expect(typeIdentifier.identifier.staticElement, same(cElement));
}
{
var cTypeDouble = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[1];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeDouble);
var constructorName = creation.constructorName;
expect(constructorName.name.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
PrefixedIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix));
expect(typePrefix.staticType, isNull);
expect(typeIdentifier.identifier.staticElement, same(cElement));
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[2];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
expect(constructorName.name.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments.arguments, hasLength(1));
_assertTypeNameSimple(
typeName.typeArguments.arguments[0], typeProvider.boolType);
PrefixedIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
SimpleIdentifier typePrefix = typeIdentifier.prefix;
expect(typePrefix.name, 'p');
expect(typePrefix.staticElement, same(aImport.prefix));
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.getType('C');
ConstructorElement defaultConstructor = cElement.constructors[0];
ConstructorElement namedConstructor = cElement.constructors[1];
var statements = _getMainStatements(result);
{
var cTypeInt = cElement.instantiate(
typeArguments: [typeProvider.intType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeInt);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
SimpleIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[1];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
expect(constructorName.name, isNull);
expect(constructorName.staticElement, defaultConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments.arguments, hasLength(1));
_assertTypeNameSimple(
typeName.typeArguments.arguments[0], typeProvider.boolType);
SimpleIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, same(cElement));
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeDouble = cElement.instantiate(
typeArguments: [typeProvider.doubleType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[2];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeDouble);
var constructorName = creation.constructorName;
expect(constructorName.name.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments, isNull);
SimpleIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, cElement);
expect(typeIdentifier.staticType, isNull);
}
{
var cTypeBool = cElement.instantiate(
typeArguments: [typeProvider.boolType],
nullabilitySuffix: NullabilitySuffix.star,
);
ExpressionStatement statement = statements[3];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticType, cTypeBool);
var constructorName = creation.constructorName;
expect(constructorName.name.staticElement, namedConstructor);
expect(constructorName.name.staticType, isNull);
expect(constructorName.staticElement, namedConstructor);
TypeName typeName = constructorName.type;
expect(typeName.typeArguments.arguments, hasLength(1));
_assertTypeNameSimple(
typeName.typeArguments.arguments[0], typeProvider.boolType);
SimpleIdentifier typeIdentifier = typeName.name;
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 typeName = creation.constructorName.type;
assertTypeName(typeName, cElement, 'C<int, double>');
var typeArguments = typeName.typeArguments.arguments;
assertTypeName(typeArguments[0], intElement, 'int');
assertTypeName(typeArguments[1], 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 typeName = creation.constructorName.type;
assertTypeName(typeName, cElement, 'C<num, String>');
var typeArguments = typeName.typeArguments.arguments;
assertTypeName(typeArguments[0], numElement, 'num');
assertTypeName(typeArguments[1], 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);
assertDeclaredVariableTypeDynamic(findNode.simple('x,'));
assertDeclaredVariableType(findNode.simple('y,'), '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);
assertDeclaredVariableTypeDynamic(findNode.simple('e,'));
assertDeclaredVariableType(findNode.simple('s})'), 'StackTrace');
}
test_invalid_catch_parameters_optional_stack() async {
addTestFile(r'''
main() {
try { } catch (e, [s]) { }
}
''');
await resolveTestFile();
expect(result.errors, isNotEmpty);
assertDeclaredVariableTypeDynamic(findNode.simple('e,'));
assertDeclaredVariableType(findNode.simple('s])'), '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');
assertTypeName(findNode.typeName('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: isNullSafetySdkAndLegacyLibrary,
),
);
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);
assertTypeName(
findNode.typeName('a.Future'),
futureElement,
'Future<int>',
expectedPrefix: findElement.import('dart:async').prefix,
);
assertTypeName(findNode.typeName('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);
TypeName type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertTypeNull(type.name);
SimpleIdentifier aRef = creation.argumentList.arguments[0];
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');
TypeName type = constructorName.type;
expect(type.typeArguments, isNull);
assertElement(type.name, c);
assertType(type.name, 'C<bool>');
SimpleIdentifier bRef = creation.argumentList.arguments[0];
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');
TypeName 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);
NamedExpression argument = creation.argumentList.arguments[0];
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);