blob: 53c7e30a31b5a1bc1b2124d22b638d13e23866b6 [file] [log] [blame]
// Copyright (c) 2016, 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 'dart:async';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/element_resolver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/source/source_resource.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/dart/resolution/driver_resolution.dart';
import '../util/element_type_matchers.dart';
import '../utils.dart';
import 'analysis_context_factory.dart';
import 'resolver_test_case.dart';
import 'test_support.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnnotationElementResolverTest);
defineReflectiveTests(ElementResolverTest);
defineReflectiveTests(PreviewDart2Test);
});
}
/// Wrapper around the test package's `fail` function.
///
/// Unlike the test package's `fail` function, this function is not annotated
/// with @alwaysThrows, so we can call it at the top of a test method without
/// causing the rest of the method to be flagged as dead code.
void _fail(String message) {
fail(message);
}
@reflectiveTest
class AnnotationElementResolverTest extends DriverResolutionTest {
test_class_namedConstructor() async {
newFile('/test/lib/a.dart', content: r'''
class A {
const A.named();
}
''');
await _validateAnnotation('', '@A.named()', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
expect(name2, isNotNull);
expect(name2.staticElement, isConstructorElement);
expect(
resolutionMap.staticElementForIdentifier(name2).displayName, 'named');
expect(name3, isNull);
if (annotationElement is ConstructorElement) {
expect(annotationElement, same(name2.staticElement));
expect(annotationElement.enclosingElement, name1.staticElement);
expect(annotationElement.displayName, 'named');
expect(annotationElement.parameters, isEmpty);
} else {
fail('Expected "annotationElement" is ConstructorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_class_prefixed_namedConstructor() async {
newFile('/test/lib/a.dart', content: r'''
class A {
const A.named();
}
''');
await _validateAnnotation('as p', '@p.A.named()', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isPrefixElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
expect(name2, isNotNull);
expect(name2.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
expect(name3, isNotNull);
expect(name3.staticElement, isConstructorElement);
expect(
resolutionMap.staticElementForIdentifier(name3).displayName, 'named');
if (annotationElement is ConstructorElement) {
expect(annotationElement, same(name3.staticElement));
expect(annotationElement.enclosingElement, name2.staticElement);
expect(annotationElement.displayName, 'named');
expect(annotationElement.parameters, isEmpty);
} else {
fail('Expected "annotationElement" is ConstructorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_class_prefixed_staticConstField() async {
newFile('/test/lib/a.dart', content: r'''
class A {
static const V = 0;
}
''');
await _validateAnnotation('as p', '@p.A.V', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isPrefixElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
expect(name2, isNotNull);
expect(name2.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
expect(name3, isNotNull);
expect(name3.staticElement, isPropertyAccessorElement);
expect(resolutionMap.staticElementForIdentifier(name3).displayName, 'V');
if (annotationElement is PropertyAccessorElement) {
expect(annotationElement, same(name3.staticElement));
expect(annotationElement.enclosingElement, name2.staticElement);
expect(annotationElement.displayName, 'V');
} else {
fail('Expected "annotationElement" is PropertyAccessorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_class_prefixed_unnamedConstructor() async {
newFile('/test/lib/a.dart', content: r'''
class A {
const A();
}
''');
await _validateAnnotation('as p', '@p.A', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isPrefixElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
expect(name2, isNotNull);
expect(name2.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
expect(name3, isNull);
if (annotationElement is ConstructorElement) {
expect(annotationElement.enclosingElement, name2.staticElement);
expect(annotationElement.displayName, '');
expect(annotationElement.parameters, isEmpty);
} else {
fail('Expected "annotationElement" is ConstructorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_class_staticConstField() async {
newFile('/test/lib/a.dart', content: r'''
class A {
static const V = 0;
}
''');
await _validateAnnotation('', '@A.V', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
expect(name2, isNotNull);
expect(name2.staticElement, isPropertyAccessorElement);
expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'V');
expect(name3, isNull);
if (annotationElement is PropertyAccessorElement) {
expect(annotationElement, same(name2.staticElement));
expect(annotationElement.enclosingElement, name1.staticElement);
expect(annotationElement.displayName, 'V');
} else {
fail('Expected "annotationElement" is PropertyAccessorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_class_unnamedConstructor() async {
newFile('/test/lib/a.dart', content: r'''
class A {
const A();
}
''');
await _validateAnnotation('', '@A', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isClassElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
expect(name2, isNull);
expect(name3, isNull);
if (annotationElement is ConstructorElement) {
expect(annotationElement.enclosingElement, name1.staticElement);
expect(annotationElement.displayName, '');
expect(annotationElement.parameters, isEmpty);
} else {
fail('Expected "annotationElement" is ConstructorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_topLevelVariable() async {
newFile('/test/lib/a.dart', content: r'''
const V = 0;
''');
await _validateAnnotation('', '@V', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isPropertyAccessorElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'V');
expect(name2, isNull);
expect(name3, isNull);
if (annotationElement is PropertyAccessorElement) {
expect(annotationElement, same(name1.staticElement));
expect(annotationElement.enclosingElement, isCompilationUnitElement);
expect(annotationElement.displayName, 'V');
} else {
fail('Expected "annotationElement" is PropertyAccessorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
test_topLevelVariable_prefixed() async {
newFile('/test/lib/a.dart', content: r'''
const V = 0;
''');
await _validateAnnotation('as p', '@p.V', (SimpleIdentifier name1,
SimpleIdentifier name2,
SimpleIdentifier name3,
Element annotationElement) {
expect(name1, isNotNull);
expect(name1.staticElement, isPrefixElement);
expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
expect(name2, isNotNull);
expect(name2.staticElement, isPropertyAccessorElement);
expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'V');
expect(name3, isNull);
if (annotationElement is PropertyAccessorElement) {
expect(annotationElement, same(name2.staticElement));
expect(annotationElement.enclosingElement, isCompilationUnitElement);
expect(annotationElement.displayName, 'V');
} else {
fail('Expected "annotationElement" is PropertyAccessorElement, '
'but (${annotationElement?.runtimeType}) $annotationElement found.');
}
});
}
Future<void> _validateAnnotation(
String annotationPrefix,
String annotationText,
validator(SimpleIdentifier name1, SimpleIdentifier name2,
SimpleIdentifier name3, Element annotationElement)) async {
addTestFile('''
import 'a.dart' $annotationPrefix;
$annotationText
class C {}
''');
await resolveTestFile();
var clazz = findNode.classDeclaration('C');
Annotation annotation = clazz.metadata.single;
Identifier name = annotation.name;
Element annotationElement = annotation.element;
if (name is SimpleIdentifier) {
validator(name, null, annotation.constructorName, annotationElement);
} else if (name is PrefixedIdentifier) {
validator(name.prefix, name.identifier, annotation.constructorName,
annotationElement);
} else {
fail('Uknown "name": ${name?.runtimeType} $name');
}
}
}
@reflectiveTest
class ElementResolverTest extends EngineTestCase with ResourceProviderMixin {
/**
* The error listener to which errors will be reported.
*/
GatheringErrorListener _listener;
/**
* The type provider used to access the types.
*/
TypeProvider _typeProvider;
/**
* The library containing the code being resolved.
*/
LibraryElementImpl _definingLibrary;
/**
* The resolver visitor that maintains the state for the resolver.
*/
ResolverVisitor _visitor;
/**
* The resolver being used to resolve the test cases.
*/
ElementResolver _resolver;
void fail_visitExportDirective_combinators() {
_fail("Not yet tested");
// Need to set up the exported library so that the identifier can be
// resolved.
ExportDirective directive = AstTestFactory.exportDirective2(null, [
AstTestFactory.hideCombinator2(["A"])
]);
_resolveNode(directive);
_listener.assertNoErrors();
}
void fail_visitFunctionExpressionInvocation() {
_fail("Not yet tested");
_listener.assertNoErrors();
}
void fail_visitImportDirective_combinators_noPrefix() {
_fail("Not yet tested");
// Need to set up the imported library so that the identifier can be
// resolved.
ImportDirective directive = AstTestFactory.importDirective3(null, null, [
AstTestFactory.showCombinator2(["A"])
]);
_resolveNode(directive);
_listener.assertNoErrors();
}
void fail_visitImportDirective_combinators_prefix() {
_fail("Not yet tested");
// Need to set up the imported library so that the identifiers can be
// resolved.
String prefixName = "p";
_definingLibrary.imports = <ImportElement>[
ElementFactory.importFor(null, ElementFactory.prefix(prefixName))
];
ImportDirective directive =
AstTestFactory.importDirective3(null, prefixName, [
AstTestFactory.showCombinator2(["A"]),
AstTestFactory.hideCombinator2(["B"])
]);
_resolveNode(directive);
_listener.assertNoErrors();
}
void fail_visitRedirectingConstructorInvocation() {
_fail("Not yet tested");
_listener.assertNoErrors();
}
@override
void setUp() {
super.setUp();
_listener = new GatheringErrorListener();
_createResolver();
}
test_lookUpMethodInInterfaces() async {
InterfaceType intType = _typeProvider.intType;
//
// abstract class A { int operator[](int index); }
//
ClassElementImpl classA = ElementFactory.classElement2("A");
MethodElement operator =
ElementFactory.methodElement("[]", intType, [intType]);
classA.methods = <MethodElement>[operator];
//
// class B implements A {}
//
ClassElementImpl classB = ElementFactory.classElement2("B");
classB.interfaces = <InterfaceType>[classA.type];
//
// class C extends Object with B {}
//
ClassElementImpl classC = ElementFactory.classElement2("C");
classC.mixins = <InterfaceType>[classB.type];
//
// class D extends C {}
//
ClassElementImpl classD = ElementFactory.classElement("D", classC.type);
//
// D a;
// a[i];
//
SimpleIdentifier array = AstTestFactory.identifier3("a");
array.staticType = classD.type;
IndexExpression expression =
AstTestFactory.indexExpression(array, AstTestFactory.identifier3("i"));
expect(_resolveIndexExpression(expression), same(operator));
_listener.assertNoErrors();
}
test_visitAssignmentExpression_compound() async {
InterfaceType intType = _typeProvider.intType;
SimpleIdentifier leftHandSide = AstTestFactory.identifier3("a");
leftHandSide.staticType = intType;
AssignmentExpression assignment = AstTestFactory.assignmentExpression(
leftHandSide, TokenType.PLUS_EQ, AstTestFactory.integer(1));
_resolveNode(assignment);
expect(
assignment.staticElement, same(getMethod(_typeProvider.numType, "+")));
_listener.assertNoErrors();
}
test_visitAssignmentExpression_simple() async {
AssignmentExpression expression = AstTestFactory.assignmentExpression(
AstTestFactory.identifier3("x"),
TokenType.EQ,
AstTestFactory.integer(0));
_resolveNode(expression);
expect(expression.staticElement, isNull);
_listener.assertNoErrors();
}
test_visitBinaryExpression_bangEq() async {
// String i;
// var j;
// i == j
InterfaceType stringType = _typeProvider.stringType;
SimpleIdentifier left = AstTestFactory.identifier3("i");
left.staticType = stringType;
BinaryExpression expression = AstTestFactory.binaryExpression(
left, TokenType.BANG_EQ, AstTestFactory.identifier3("j"));
_resolveNode(expression);
var stringElement = stringType.element;
expect(expression.staticElement, isNotNull);
expect(
expression.staticElement,
stringElement.lookUpMethod(
TokenType.EQ_EQ.lexeme, stringElement.library));
_listener.assertNoErrors();
}
test_visitBinaryExpression_eq() async {
// String i;
// var j;
// i == j
InterfaceType stringType = _typeProvider.stringType;
SimpleIdentifier left = AstTestFactory.identifier3("i");
left.staticType = stringType;
BinaryExpression expression = AstTestFactory.binaryExpression(
left, TokenType.EQ_EQ, AstTestFactory.identifier3("j"));
_resolveNode(expression);
var stringElement = stringType.element;
expect(
expression.staticElement,
stringElement.lookUpMethod(
TokenType.EQ_EQ.lexeme, stringElement.library));
_listener.assertNoErrors();
}
test_visitBinaryExpression_plus() async {
// num i;
// var j;
// i + j
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier left = AstTestFactory.identifier3("i");
left.staticType = numType;
BinaryExpression expression = AstTestFactory.binaryExpression(
left, TokenType.PLUS, AstTestFactory.identifier3("j"));
_resolveNode(expression);
expect(expression.staticElement, getMethod(numType, "+"));
_listener.assertNoErrors();
}
test_visitBreakStatement_withLabel() async {
// loop: while (true) {
// break loop;
// }
String label = "loop";
LabelElementImpl labelElement = new LabelElementImpl.forNode(
AstTestFactory.identifier3(label), false, false);
BreakStatement breakStatement = AstTestFactory.breakStatement2(label);
Expression condition = AstTestFactory.booleanLiteral(true);
WhileStatement whileStatement =
AstTestFactory.whileStatement(condition, breakStatement);
expect(_resolveBreak(breakStatement, labelElement, whileStatement),
same(labelElement));
expect(breakStatement.target, same(whileStatement));
_listener.assertNoErrors();
}
test_visitBreakStatement_withoutLabel() async {
BreakStatement statement = AstTestFactory.breakStatement();
_resolveStatement(statement, null, null);
_listener.assertNoErrors();
}
test_visitCommentReference_prefixedIdentifier_class_getter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set accessors
String propName = "p";
PropertyAccessorElement getter =
ElementFactory.getterElement(propName, false, _typeProvider.intType);
PropertyAccessorElement setter =
ElementFactory.setterElement(propName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter, setter];
// set name scope
_visitor.nameScope = new EnclosedScope(null)
..defineNameWithoutChecking('A', classA);
// prepare "A.p"
PrefixedIdentifier prefixed = AstTestFactory.identifier5('A', 'p');
CommentReference commentReference =
astFactory.commentReference(null, prefixed);
// resolve
_resolveNode(commentReference);
expect(prefixed.prefix.staticElement, classA);
expect(prefixed.identifier.staticElement, getter);
_listener.assertNoErrors();
}
test_visitCommentReference_prefixedIdentifier_class_method() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set method
MethodElement method =
ElementFactory.methodElement("m", _typeProvider.intType);
classA.methods = <MethodElement>[method];
// set name scope
_visitor.nameScope = new EnclosedScope(null)
..defineNameWithoutChecking('A', classA);
// prepare "A.m"
PrefixedIdentifier prefixed = AstTestFactory.identifier5('A', 'm');
CommentReference commentReference =
astFactory.commentReference(null, prefixed);
// resolve
_resolveNode(commentReference);
expect(prefixed.prefix.staticElement, classA);
expect(prefixed.identifier.staticElement, method);
_listener.assertNoErrors();
}
test_visitCommentReference_prefixedIdentifier_class_operator() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set method
MethodElement method =
ElementFactory.methodElement("==", _typeProvider.boolType);
classA.methods = <MethodElement>[method];
// set name scope
_visitor.nameScope = new EnclosedScope(null)
..defineNameWithoutChecking('A', classA);
// prepare "A.=="
PrefixedIdentifier prefixed = AstTestFactory.identifier5('A', '==');
CommentReference commentReference =
astFactory.commentReference(null, prefixed);
// resolve
_resolveNode(commentReference);
expect(prefixed.prefix.staticElement, classA);
expect(prefixed.identifier.staticElement, method);
_listener.assertNoErrors();
}
test_visitConstructorName_named() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String constructorName = "a";
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
AstTestFactory.typeName(classA), constructorName);
_resolveNode(name);
expect(name.staticElement, same(constructor));
_listener.assertNoErrors();
}
test_visitConstructorName_unnamed() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String constructorName = null;
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
AstTestFactory.typeName(classA), constructorName);
_resolveNode(name);
expect(name.staticElement, same(constructor));
_listener.assertNoErrors();
}
test_visitContinueStatement_withLabel() async {
// loop: while (true) {
// continue loop;
// }
String label = "loop";
LabelElementImpl labelElement = new LabelElementImpl.forNode(
AstTestFactory.identifier3(label), false, false);
ContinueStatement continueStatement =
AstTestFactory.continueStatement(label);
Expression condition = AstTestFactory.booleanLiteral(true);
WhileStatement whileStatement =
AstTestFactory.whileStatement(condition, continueStatement);
expect(_resolveContinue(continueStatement, labelElement, whileStatement),
same(labelElement));
expect(continueStatement.target, same(whileStatement));
_listener.assertNoErrors();
}
test_visitContinueStatement_withoutLabel() async {
ContinueStatement statement = AstTestFactory.continueStatement();
_resolveStatement(statement, null, null);
_listener.assertNoErrors();
}
test_visitEnumDeclaration() async {
CompilationUnitElementImpl compilationUnitElement =
ElementFactory.compilationUnit('foo.dart');
EnumElementImpl enumElement =
ElementFactory.enumElement(_typeProvider, ('E'));
compilationUnitElement.enums = <ClassElement>[enumElement];
EnumDeclaration enumNode = AstTestFactory.enumDeclaration2('E', []);
Annotation annotationNode =
AstTestFactory.annotation(AstTestFactory.identifier3('a'));
annotationNode.element = ElementFactory.classElement2('A');
annotationNode.elementAnnotation =
new ElementAnnotationImpl(compilationUnitElement);
enumNode.metadata.add(annotationNode);
enumNode.name.staticElement = enumElement;
List<ElementAnnotation> metadata = <ElementAnnotation>[
annotationNode.elementAnnotation
];
_resolveNode(enumNode);
expect(metadata[0].element, annotationNode.element);
}
test_visitExportDirective_noCombinators() async {
ExportDirective directive = AstTestFactory.exportDirective2(null);
directive.element = ElementFactory.exportFor(
ElementFactory.library(_definingLibrary.context, "lib"));
_resolveNode(directive);
_listener.assertNoErrors();
}
test_visitFieldFormalParameter() async {
String fieldName = "f";
InterfaceType intType = _typeProvider.intType;
FieldElementImpl fieldElement =
ElementFactory.fieldElement(fieldName, false, false, false, intType);
ClassElementImpl classA = ElementFactory.classElement2("A");
classA.fields = <FieldElement>[fieldElement];
FieldFormalParameter parameter =
AstTestFactory.fieldFormalParameter2(fieldName);
FieldFormalParameterElementImpl parameterElement =
ElementFactory.fieldFormalParameter(parameter.identifier);
parameterElement.field = fieldElement;
parameterElement.type = intType;
parameter.identifier.staticElement = parameterElement;
_resolveInClass(parameter, classA);
expect(resolutionMap.elementDeclaredByFormalParameter(parameter).type,
same(intType));
}
test_visitImportDirective_noCombinators_noPrefix() async {
ImportDirective directive = AstTestFactory.importDirective3(null, null);
directive.element = ElementFactory.importFor(
ElementFactory.library(_definingLibrary.context, "lib"), null);
_resolveNode(directive);
_listener.assertNoErrors();
}
test_visitImportDirective_noCombinators_prefix() async {
String prefixName = "p";
ImportElement importElement = ElementFactory.importFor(
ElementFactory.library(_definingLibrary.context, "lib"),
ElementFactory.prefix(prefixName));
_definingLibrary.imports = <ImportElement>[importElement];
ImportDirective directive =
AstTestFactory.importDirective3(null, prefixName);
directive.element = importElement;
_resolveNode(directive);
_listener.assertNoErrors();
}
test_visitImportDirective_withCombinators() async {
ShowCombinator combinator = AstTestFactory.showCombinator2(["A", "B", "C"]);
ImportDirective directive =
AstTestFactory.importDirective3(null, null, [combinator]);
LibraryElementImpl library =
ElementFactory.library(_definingLibrary.context, "lib");
TopLevelVariableElementImpl varA =
ElementFactory.topLevelVariableElement2("A");
TopLevelVariableElementImpl varB =
ElementFactory.topLevelVariableElement2("B");
TopLevelVariableElementImpl varC =
ElementFactory.topLevelVariableElement2("C");
CompilationUnitElementImpl unit =
library.definingCompilationUnit as CompilationUnitElementImpl;
unit.accessors = <PropertyAccessorElement>[
varA.getter,
varA.setter,
varB.getter,
varC.setter
];
unit.topLevelVariables = <TopLevelVariableElement>[varA, varB, varC];
directive.element = ElementFactory.importFor(library, null);
_resolveNode(directive);
expect(combinator.shownNames[0].staticElement, same(varA));
expect(combinator.shownNames[1].staticElement, same(varB));
expect(combinator.shownNames[2].staticElement, same(varC));
_listener.assertNoErrors();
}
test_visitIndexExpression_get() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
InterfaceType intType = _typeProvider.intType;
MethodElement getter =
ElementFactory.methodElement("[]", intType, [intType]);
classA.methods = <MethodElement>[getter];
SimpleIdentifier array = AstTestFactory.identifier3("a");
array.staticType = classA.type;
IndexExpression expression =
AstTestFactory.indexExpression(array, AstTestFactory.identifier3("i"));
expect(_resolveIndexExpression(expression), same(getter));
_listener.assertNoErrors();
}
test_visitIndexExpression_set() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
InterfaceType intType = _typeProvider.intType;
MethodElement setter =
ElementFactory.methodElement("[]=", intType, [intType]);
classA.methods = <MethodElement>[setter];
SimpleIdentifier array = AstTestFactory.identifier3("a");
array.staticType = classA.type;
IndexExpression expression =
AstTestFactory.indexExpression(array, AstTestFactory.identifier3("i"));
AstTestFactory.assignmentExpression(
expression, TokenType.EQ, AstTestFactory.integer(0));
expect(_resolveIndexExpression(expression), same(setter));
_listener.assertNoErrors();
}
test_visitInstanceCreationExpression_named() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String constructorName = "a";
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
AstTestFactory.typeName(classA), constructorName);
name.staticElement = constructor;
InstanceCreationExpression creation =
AstTestFactory.instanceCreationExpression(Keyword.NEW, name);
_resolveNode(creation);
expect(creation.staticElement, same(constructor));
_listener.assertNoErrors();
}
test_visitInstanceCreationExpression_unnamed() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String constructorName = null;
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
AstTestFactory.typeName(classA), constructorName);
name.staticElement = constructor;
InstanceCreationExpression creation =
AstTestFactory.instanceCreationExpression(Keyword.NEW, name);
_resolveNode(creation);
expect(creation.staticElement, same(constructor));
_listener.assertNoErrors();
}
test_visitInstanceCreationExpression_unnamed_namedParameter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String constructorName = null;
ConstructorElementImpl constructor =
ElementFactory.constructorElement2(classA, constructorName);
String parameterName = "a";
ParameterElement parameter = ElementFactory.namedParameter(parameterName);
constructor.parameters = <ParameterElement>[parameter];
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
AstTestFactory.typeName(classA), constructorName);
name.staticElement = constructor;
InstanceCreationExpression creation =
AstTestFactory.instanceCreationExpression(Keyword.NEW, name, [
AstTestFactory.namedExpression2(parameterName, AstTestFactory.integer(0))
]);
_resolveNode(creation);
expect(creation.staticElement, same(constructor));
expect(
(creation.argumentList.arguments[0] as NamedExpression)
.name
.label
.staticElement,
same(parameter));
_listener.assertNoErrors();
}
test_visitMethodInvocation() async {
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier left = AstTestFactory.identifier3("i");
left.staticType = numType;
String methodName = "abs";
MethodInvocation invocation =
AstTestFactory.methodInvocation(left, methodName);
_resolveNode(invocation);
expect(invocation.methodName.staticElement,
same(getMethod(numType, methodName)));
_listener.assertNoErrors();
}
test_visitPostfixExpression() async {
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier operand = AstTestFactory.identifier3("i");
operand.staticType = numType;
PostfixExpression expression =
AstTestFactory.postfixExpression(operand, TokenType.PLUS_PLUS);
_resolveNode(expression);
expect(expression.staticElement, getMethod(numType, "+"));
_listener.assertNoErrors();
}
@failingTest
test_visitPostfixExpression_bang() async {
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier operand = AstTestFactory.identifier3("i");
operand.staticType = numType;
PostfixExpression expression =
AstTestFactory.postfixExpression(operand, TokenType.BANG);
// TODO(danrubel): fails with Unsupported operation
_resolveNode(expression);
_listener.assertErrorsWithCodes([StaticTypeWarningCode.UNDEFINED_OPERATOR]);
}
@failingTest
test_visitPostfixExpression_bang_NNBD() async {
// TODO(danrubel): enable NNBD
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier operand = AstTestFactory.identifier3("i");
operand.staticType = numType;
PostfixExpression expression =
AstTestFactory.postfixExpression(operand, TokenType.BANG);
_resolveNode(expression);
// TODO(danrubel): fails with Unsupported operation
expect(expression.staticElement, getMethod(numType, "!"));
_listener.assertNoErrors();
}
test_visitPrefixedIdentifier_dynamic() async {
DartType dynamicType = _typeProvider.dynamicType;
SimpleIdentifier target = AstTestFactory.identifier3("a");
VariableElementImpl variable = ElementFactory.localVariableElement(target);
variable.type = dynamicType;
target.staticElement = variable;
target.staticType = dynamicType;
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3("b"));
_resolveNode(identifier);
expect(identifier.staticElement, isNull);
expect(identifier.identifier.staticElement, isNull);
_listener.assertNoErrors();
}
test_visitPrefixedIdentifier_nonDynamic() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SimpleIdentifier target = AstTestFactory.identifier3("a");
VariableElementImpl variable = ElementFactory.localVariableElement(target);
variable.type = classA.type;
target.staticElement = variable;
target.staticType = classA.type;
PrefixedIdentifier identifier = AstTestFactory.identifier(
target, AstTestFactory.identifier3(getterName));
_resolveNode(identifier);
expect(identifier.staticElement, same(getter));
expect(identifier.identifier.staticElement, same(getter));
_listener.assertNoErrors();
}
test_visitPrefixedIdentifier_staticClassMember_getter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set accessors
String propName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(propName, false, _typeProvider.intType);
PropertyAccessorElement setter =
ElementFactory.setterElement(propName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter, setter];
// prepare "A.m"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
target.staticType = classA.type;
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
// resolve
_resolveNode(identifier);
expect(identifier.staticElement, same(getter));
expect(identifier.identifier.staticElement, same(getter));
_listener.assertNoErrors();
}
test_visitPrefixedIdentifier_staticClassMember_method() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set methods
String propName = "m";
MethodElement method =
ElementFactory.methodElement("m", _typeProvider.intType);
classA.methods = <MethodElement>[method];
// prepare "A.m"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
target.staticType = classA.type;
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
AstTestFactory.assignmentExpression(
identifier, TokenType.EQ, AstTestFactory.nullLiteral());
// resolve
_resolveNode(identifier);
expect(identifier.staticElement, same(method));
expect(identifier.identifier.staticElement, same(method));
_listener.assertNoErrors();
}
test_visitPrefixedIdentifier_staticClassMember_setter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
// set accessors
String propName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(propName, false, _typeProvider.intType);
PropertyAccessorElement setter =
ElementFactory.setterElement(propName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter, setter];
// prepare "A.b = null"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
target.staticType = classA.type;
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
AstTestFactory.assignmentExpression(
identifier, TokenType.EQ, AstTestFactory.nullLiteral());
// resolve
_resolveNode(identifier);
expect(identifier.staticElement, same(setter));
expect(identifier.identifier.staticElement, same(setter));
_listener.assertNoErrors();
}
test_visitPrefixExpression() async {
InterfaceType numType = _typeProvider.numType;
SimpleIdentifier operand = AstTestFactory.identifier3("i");
operand.staticType = numType;
PrefixExpression expression =
AstTestFactory.prefixExpression(TokenType.PLUS_PLUS, operand);
_resolveNode(expression);
expect(expression.staticElement, getMethod(numType, "+"));
_listener.assertNoErrors();
}
test_visitPropertyAccess_getter_identifier() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SimpleIdentifier target = AstTestFactory.identifier3("a");
target.staticType = classA.type;
PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
_resolveNode(access);
expect(access.propertyName.staticElement, same(getter));
_listener.assertNoErrors();
}
test_visitPropertyAccess_getter_super() async {
//
// class A {
// int get b;
// }
// class B {
// ... super.m ...
// }
//
ClassElementImpl classA = ElementFactory.classElement2("A");
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SuperExpression target = AstTestFactory.superExpression();
target.staticType = ElementFactory.classElement("B", classA.type).type;
PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3("m"),
AstTestFactory.formalParameterList(),
AstTestFactory.expressionFunctionBody(access));
_resolveNode(access);
expect(access.propertyName.staticElement, same(getter));
_listener.assertNoErrors();
}
test_visitPropertyAccess_setter_this() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
String setterName = "b";
PropertyAccessorElement setter =
ElementFactory.setterElement(setterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[setter];
ThisExpression target = AstTestFactory.thisExpression();
target.staticType = classA.type;
PropertyAccess access = AstTestFactory.propertyAccess2(target, setterName);
AstTestFactory.assignmentExpression(
access, TokenType.EQ, AstTestFactory.integer(0));
_resolveNode(access);
expect(access.propertyName.staticElement, same(setter));
_listener.assertNoErrors();
}
test_visitSimpleIdentifier_classScope() async {
InterfaceType doubleType = _typeProvider.doubleType;
String fieldName = "NAN";
SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
_resolveInClass(node, doubleType.element);
expect(node.staticElement, getGetter(doubleType, fieldName));
_listener.assertNoErrors();
}
test_visitSimpleIdentifier_dynamic() async {
SimpleIdentifier node = AstTestFactory.identifier3("dynamic");
_resolveIdentifier(node);
expect(node.staticElement, same(_typeProvider.dynamicType.element));
expect(node.staticType, same(_typeProvider.typeType));
_listener.assertNoErrors();
}
test_visitSimpleIdentifier_lexicalScope() async {
SimpleIdentifier node = AstTestFactory.identifier3("i");
VariableElementImpl element = ElementFactory.localVariableElement(node);
expect(_resolveIdentifier(node, [element]), same(element));
_listener.assertNoErrors();
}
test_visitSimpleIdentifier_lexicalScope_field_setter() async {
InterfaceType intType = _typeProvider.intType;
ClassElementImpl classA = ElementFactory.classElement2("A");
String fieldName = "a";
FieldElement field =
ElementFactory.fieldElement(fieldName, false, false, false, intType);
classA.fields = <FieldElement>[field];
classA.accessors = <PropertyAccessorElement>[field.getter, field.setter];
SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
AstTestFactory.assignmentExpression(
node, TokenType.EQ, AstTestFactory.integer(0));
_resolveInClass(node, classA);
PropertyAccessorElement element = node.staticElement;
expect(element.isSetter, isTrue);
_listener.assertNoErrors();
}
test_visitSuperConstructorInvocation() async {
ClassElementImpl superclass = ElementFactory.classElement2("A");
ConstructorElementImpl superConstructor =
ElementFactory.constructorElement2(superclass, null);
superclass.constructors = <ConstructorElement>[superConstructor];
ClassElementImpl subclass =
ElementFactory.classElement("B", superclass.type);
ConstructorElementImpl subConstructor =
ElementFactory.constructorElement2(subclass, null);
subclass.constructors = <ConstructorElement>[subConstructor];
SuperConstructorInvocation invocation =
AstTestFactory.superConstructorInvocation();
AstTestFactory.classDeclaration(null, 'C', null, null, null, null, [
AstTestFactory.constructorDeclaration(null, 'C', null, [invocation])
]);
_resolveInClass(invocation, subclass);
expect(invocation.staticElement, superConstructor);
_listener.assertNoErrors();
}
test_visitSuperConstructorInvocation_namedParameter() async {
ClassElementImpl superclass = ElementFactory.classElement2("A");
ConstructorElementImpl superConstructor =
ElementFactory.constructorElement2(superclass, null);
String parameterName = "p";
ParameterElement parameter = ElementFactory.namedParameter(parameterName);
superConstructor.parameters = <ParameterElement>[parameter];
superclass.constructors = <ConstructorElement>[superConstructor];
ClassElementImpl subclass =
ElementFactory.classElement("B", superclass.type);
ConstructorElementImpl subConstructor =
ElementFactory.constructorElement2(subclass, null);
subclass.constructors = <ConstructorElement>[subConstructor];
SuperConstructorInvocation invocation =
AstTestFactory.superConstructorInvocation([
AstTestFactory.namedExpression2(parameterName, AstTestFactory.integer(0))
]);
AstTestFactory.classDeclaration(null, 'C', null, null, null, null, [
AstTestFactory.constructorDeclaration(null, 'C', null, [invocation])
]);
_resolveInClass(invocation, subclass);
expect(invocation.staticElement, superConstructor);
expect(
(invocation.argumentList.arguments[0] as NamedExpression)
.name
.label
.staticElement,
same(parameter));
_listener.assertNoErrors();
}
/**
* Create and return the resolver used by the tests.
*/
void _createResolver() {
InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(
resourceProvider: resourceProvider);
_typeProvider = context.typeProvider;
var inheritance = new InheritanceManager2(context.typeSystem);
Source source = new FileSource(getFile("/test.dart"));
CompilationUnitElementImpl unit = new CompilationUnitElementImpl();
unit.librarySource = unit.source = source;
_definingLibrary = ElementFactory.library(context, "test");
_definingLibrary.definingCompilationUnit = unit;
_visitor = new ResolverVisitor(
inheritance, _definingLibrary, source, _typeProvider, _listener,
featureSet: FeatureSet.forTesting(),
nameScope: new LibraryScope(_definingLibrary));
_resolver = _visitor.elementResolver;
}
/**
* Return the element associated with the label of [statement] after the
* resolver has resolved it. [labelElement] is the label element to be
* defined in the statement's label scope, and [labelTarget] is the statement
* the label resolves to.
*/
Element _resolveBreak(BreakStatement statement, LabelElementImpl labelElement,
Statement labelTarget) {
_resolveStatement(statement, labelElement, labelTarget);
return statement.label.staticElement;
}
/**
* Return the element associated with the label [statement] after the
* resolver has resolved it. [labelElement] is the label element to be
* defined in the statement's label scope, and [labelTarget] is the AST node
* the label resolves to.
*
* @param statement the statement to be resolved
* @param labelElement the label element to be defined in the statement's label scope
* @return the element to which the statement's label was resolved
*/
Element _resolveContinue(ContinueStatement statement,
LabelElementImpl labelElement, AstNode labelTarget) {
_resolveStatement(statement, labelElement, labelTarget);
return statement.label.staticElement;
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) {
_resolveNode(node, definedElements);
return node.staticElement;
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param enclosingClass the element representing the class enclosing the identifier
* @return the element to which the expression was resolved
*/
void _resolveInClass(AstNode node, ClassElement enclosingClass) {
Scope outerScope = _visitor.nameScope;
try {
_visitor.enclosingClass = enclosingClass;
EnclosedScope innerScope = new ClassScope(
new TypeParameterScope(outerScope, enclosingClass), enclosingClass);
_visitor.nameScope = innerScope;
node.accept(_resolver);
} finally {
_visitor.enclosingClass = null;
_visitor.nameScope = outerScope;
}
}
/**
* Return the element associated with the given expression after the resolver has resolved the
* expression.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
Element _resolveIndexExpression(IndexExpression node,
[List<Element> definedElements]) {
_resolveNode(node, definedElements);
return node.staticElement;
}
/**
* Return the element associated with the given identifier after the resolver has resolved the
* identifier.
*
* @param node the expression to be resolved
* @param definedElements the elements that are to be defined in the scope in which the element is
* being resolved
* @return the element to which the expression was resolved
*/
void _resolveNode(AstNode node, [List<Element> definedElements]) {
Scope outerScope = _visitor.nameScope;
try {
EnclosedScope innerScope = new EnclosedScope(outerScope);
if (definedElements != null) {
for (Element element in definedElements) {
innerScope.define(element);
}
}
_visitor.nameScope = innerScope;
node.accept(_resolver);
} finally {
_visitor.nameScope = outerScope;
}
}
/**
* Return the element associated with the label of the given statement after the resolver has
* resolved the statement.
*
* @param statement the statement to be resolved
* @param labelElement the label element to be defined in the statement's label scope
* @return the element to which the statement's label was resolved
*/
void _resolveStatement(
Statement statement, LabelElementImpl labelElement, AstNode labelTarget) {
LabelScope outerScope = _visitor.labelScope;
try {
LabelScope innerScope;
if (labelElement == null) {
innerScope = outerScope;
} else {
innerScope = new LabelScope(
outerScope, labelElement.name, labelTarget, labelElement);
}
_visitor.labelScope = innerScope;
statement.accept(_resolver);
} finally {
_visitor.labelScope = outerScope;
}
}
}
@reflectiveTest
class PreviewDart2Test extends ResolverTestCase {
@override
void setUp() {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
resetWith(options: options);
}
/**
* Tests and verifies that even with a explicit 'new' keyword, the
* construction of the InstanceCreationExpression node with types and elements
* is all correct.
*/
test_visitMethodInvocations_explicit() async {
String code = '''
class A {
A() {}
}
main() {
new A();
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
expect(creation.staticElement, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, isConstructorElement);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
}
/**
* Test that the call to a constructor with an implicit unnamed constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* C()
*/
test_visitMethodInvocations_implicit() async {
String code = '''
class A {
A(a, {b}) {}
}
main() {
A(0, b: 1);
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
List<Expression> arguments = creation.argumentList.arguments;
Expression argumentA = arguments[0];
expect(argumentA.staticParameterElement, constructor.parameters[0]);
NamedExpression argumentB = arguments[1];
expect(argumentB.name.label.staticElement, constructor.parameters[1]);
}
/**
* Test that the call to a constructor with an implicit unnamed constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* C(), where class C has no constructors
*/
test_visitMethodInvocations_implicit_implicit() async {
String code = '''
class A {}
main() {
A();
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
expect(creation.argumentList.arguments, isEmpty);
}
/**
* Test that the call to a constructor with an implicit named constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* C.n()
*/
test_visitMethodInvocations_implicit_named() async {
String code = '''
class A {
A.named() {}
}
main() {
A.named();
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name.staticElement, constructor);
}
/**
* Test that the call to a constructor with a prefixed implicit constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* p.C()
*/
test_visitMethodInvocations_implicit_prefixed() async {
addNamedSource("/fileOne.dart", r'''
class A {
A() {}
}
''');
String code = '''
import 'fileOne.dart' as one;
main() {
one.A();
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
}
/**
* Test that the call to a constructor with a prefixed implicit named constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* p.C.n()
*/
test_visitMethodInvocations_implicit_prefixed_named() async {
addNamedSource("/fileOne.dart", r'''
class A {
A.named(a, {b}) {}
}
''');
String code = '''
import 'fileOne.dart' as one;
main() {
one.A.named(0, b: 1);
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name.staticElement, constructor);
List<Expression> arguments = creation.argumentList.arguments;
Expression argumentA = arguments[0];
expect(argumentA.staticParameterElement, constructor.parameters[0]);
NamedExpression argumentB = arguments[1];
expect(argumentB.name.label.staticElement, constructor.parameters[1]);
}
/**
* Test that the call to a constructor with a prefixed implicit constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* p.C<>()
*/
test_visitMethodInvocations_implicit_prefixed_typeArgs() async {
addNamedSource("/fileOne.dart", r'''
class A<T> {
final T x;
A(this.x) {}
}
''');
String code = '''
import 'fileOne.dart' as one;
main() {
one.A<int>(42);
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
}
/**
* Test that the call to a constructor with an implicit unnamed constructor is
* re-written as an InstanceCreationExpression AST node from a
* MethodInvocation.
*
* C<>()
*/
test_visitMethodInvocations_implicit_typeArgs() async {
String code = '''
class A<T> {
final T x;
A(this.x) {}
}
main() {
A<int>(42);
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
ConstructorElement constructor = creation.staticElement;
expect(constructor, isConstructorElement);
expect(creation.staticType, isNotNull);
expect(creation.constructorName.staticElement, constructor);
expect(creation.constructorName.type.type, isNotNull);
expect(creation.constructorName.type.name.staticElement, isClassElement);
expect(creation.constructorName.name, isNull);
}
test_visitMethodInvocations_importPrefix_function() async {
String code = '''
import 'dart:math' as ma;
main() {
ma.max(1, 2); // marker
}
''';
CompilationUnit unit = await resolveSource(code);
var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
ExpressionStatement statement = statements[0];
MethodInvocation invocation = statement.expression;
SimpleIdentifier prefix = invocation.target;
expect(prefix.staticElement, isPrefixElement);
expect(invocation.methodName.name, 'max');
}
/**
* Test that the call to a static method will not be re-written as a
* InstanceCreationExpression AST node.
*/
test_visitMethodInvocations_not_implicit_constructor() async {
String code = '''
class A {
static staticMethod() {}
}
main() {
A.staticMethod(); // marker
}
''';
CompilationUnit unit = await resolveSource(code);
AstNode node = findMarkedIdentifier(code, unit, "(); // marker");
assert(node.parent is MethodInvocation);
}
}