blob: da4866a66dfd279611f614cb3ba3c8159760a71e [file] [log] [blame]
// Copyright (c) 2014, 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/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.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/generated/testing/element_search.dart';
import 'package:analyzer/src/generated/testing/node_search.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/parser_test.dart';
import '../../generated/test_support.dart';
import '../../util/element_type_matchers.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ApiElementBuilderTest);
defineReflectiveTests(ElementBuilderTest);
defineReflectiveTests(LocalElementBuilderTest);
});
}
@reflectiveTest
class ApiElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin {
@override
AstVisitor createElementBuilder(ElementHolder holder) {
return new ApiElementBuilder(holder, compilationUnitElement);
}
void test_api_class_field() {
List<FieldElement> fields = buildElementsForText(r'''
class C {
var a = 42;
var b = () {
int v = 0;
localFunction() {}
};
}
''').types[0].fields;
expect(fields, hasLength(2));
{
FieldElement a = fields[0];
expect(a.displayName, 'a');
expect(a.initializer, isNull);
}
{
FieldElement b = fields[1];
expect(b.displayName, 'b');
expect(b.initializer, isNull);
}
}
void test_api_class_method_blockBody() {
MethodElement method = buildElementsForText(r'''
class C {
void m(int a, {int b: 42}) {
int v = 0;
localFunction() {}
}
}
''').types[0].methods[0];
{
expect(method.parameters, hasLength(2));
expect(method.parameters[0].displayName, 'a');
expect(method.parameters[0].initializer, isNull);
expect(method.parameters[1].displayName, 'b');
expect(method.parameters[1].initializer, isNull);
}
expect(
findDeclaredIdentifiersByName(compilationUnit, 'v')
.single
.staticElement,
isNull);
expect(
findDeclaredIdentifiersByName(compilationUnit, 'localFunction')
.single
.staticElement,
isNull);
}
void test_api_topLevelFunction_blockBody() {
FunctionElement topLevelFunction = buildElementsForText(r'''
void topLevelFunction() {
int v = 0;
localFunction() {}
}
''').functions[0];
expect(topLevelFunction, isNotNull);
expect(topLevelFunction.name, 'topLevelFunction');
expect(
findDeclaredIdentifiersByName(compilationUnit, 'v')
.single
.staticElement,
isNull);
expect(
findDeclaredIdentifiersByName(compilationUnit, 'localFunction')
.single
.staticElement,
isNull);
}
void test_api_topLevelFunction_expressionBody() {
FunctionElement topLevelFunction = buildElementsForText(r'''
topLevelFunction() => () {
int localVar = 0;
};
''').functions[0];
expect(topLevelFunction, isNotNull);
expect(topLevelFunction.name, 'topLevelFunction');
expect(
findDeclaredIdentifiersByName(compilationUnit, 'localVar')
.single
.staticElement,
isNull);
}
void test_api_topLevelFunction_parameters() {
FunctionElement function = buildElementsForText(r'''
void topLevelFunction(int a, int b(double b2), {c: () {int c2; c3() {} }}) {
}
''').functions[0];
List<ParameterElement> parameters = function.parameters;
expect(parameters, hasLength(3));
{
ParameterElement a = parameters[0];
expect(a.displayName, 'a');
expect(a.initializer, isNull);
}
{
ParameterElement b = parameters[1];
expect(b.displayName, 'b');
expect(b.initializer, isNull);
var bTypeElement = b.type.element as GenericFunctionTypeElementImpl;
expect(bTypeElement.parameters, hasLength(1));
expect(bTypeElement.parameters[0].displayName, 'b2');
}
{
var c = parameters[2] as DefaultParameterElementImpl;
expect(c.displayName, 'c');
expect(c.initializer, isNull);
}
}
void test_api_topLevelVariable() {
List<TopLevelVariableElement> variables = buildElementsForText(r'''
var A = 42;
var B = () {
int v = 0;
localFunction(int _) {}
};
''').topLevelVariables;
expect(variables, hasLength(2));
{
TopLevelVariableElement a = variables[0];
expect(a.displayName, 'A');
expect(a.initializer, isNull);
}
{
TopLevelVariableElement b = variables[1];
expect(b.displayName, 'B');
expect(b.initializer, isNull);
}
}
@override
void _assertHasVariableInitializer(VariableElement element) {
expect(element.initializer, isNull);
}
}
@reflectiveTest
class ElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin {
/**
* Parse the given [code], pass it through [ElementBuilder], and return the
* resulting [ElementHolder].
*/
ElementHolder buildElementsForText(String code) {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = new ElementBuilder(holder, compilationUnitElement);
_visitAstOfCode(code, builder);
return holder;
}
AstVisitor createElementBuilder(ElementHolder holder) {
return new ElementBuilder(holder, compilationUnitElement);
}
void fail_visitMethodDeclaration_setter_duplicate() {
// https://github.com/dart-lang/sdk/issues/25601
String code = r'''
class C {
set zzz(x) {}
set zzz(y) {}
}
''';
ClassElement classElement = buildElementsForText(code).types[0];
for (PropertyAccessorElement accessor in classElement.accessors) {
expect(accessor.variable.setter, same(accessor));
}
}
@override
void setUp() {
super.setUp();
compilationUnitElement = new CompilationUnitElementImpl();
}
void test_metadata_localVariableDeclaration() {
var code = 'f() { @a int x, y; }';
buildElementsForText(code);
var x = findLocalVariable(code, 'x, ');
var y = findLocalVariable(code, 'x, ');
checkMetadata(x);
checkMetadata(y);
expect(x.metadata, same(y.metadata));
}
void test_metadata_visitDeclaredIdentifier() {
var code = 'f() { for (@a var x in y) {} }';
buildElementsForText(code);
var x = findLocalVariable(code, 'x in');
checkMetadata(x);
}
void test_visitCatchClause() {
var code = 'f() { try {} catch (e, s) {} }';
buildElementsForText(code);
var e = findLocalVariable(code, 'e, ');
var s = findLocalVariable(code, 's) {}');
expect(e, isNotNull);
expect(e.name, 'e');
expect(e.hasImplicitType, isTrue);
expect(e.isSynthetic, isFalse);
expect(e.isConst, isFalse);
expect(e.isFinal, isFalse);
expect(e.initializer, isNull);
_assertVisibleRange(e, 13, 28);
expect(s, isNotNull);
expect(s.name, 's');
expect(s.isSynthetic, isFalse);
expect(s.isConst, isFalse);
expect(s.isFinal, isFalse);
expect(s.initializer, isNull);
_assertVisibleRange(s, 13, 28);
}
void test_visitCatchClause_withType() {
var code = 'f() { try {} on E catch (e) {} }';
buildElementsForText(code);
var e = findLocalVariable(code, 'e) {}');
expect(e, isNotNull);
expect(e.name, 'e');
expect(e.hasImplicitType, isFalse);
}
void test_visitCompilationUnit_codeRange() {
TopLevelVariableDeclaration topLevelVariableDeclaration =
AstTestFactory.topLevelVariableDeclaration(
null,
AstTestFactory.typeName4('int'),
[AstTestFactory.variableDeclaration('V')]);
CompilationUnit unit = astFactory.compilationUnit(
topLevelVariableDeclaration.beginToken,
null,
[],
[topLevelVariableDeclaration],
topLevelVariableDeclaration.endToken);
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
unit.beginToken.offset = 10;
unit.endToken.offset = 40;
unit.accept(builder);
assertHasCodeRange(compilationUnitElement, 0, 41);
}
void test_visitDeclaredIdentifier_noType() {
var code = 'f() { for (var i in []) {} }';
buildElementsForText(code);
var variable = findLocalVariable(code, 'i in');
assertHasCodeRange(variable, 11, 5);
expect(variable, isNotNull);
expect(variable.hasImplicitType, isTrue);
expect(variable.isConst, isFalse);
expect(variable.hasDeprecated, isFalse);
expect(variable.isFinal, isFalse);
expect(variable.hasAlwaysThrows, isFalse);
expect(variable.isPrivate, isFalse);
expect(variable.isPublic, isTrue);
expect(variable.isSynthetic, isFalse);
expect(variable.name, 'i');
}
void test_visitDeclaredIdentifier_type() {
var code = 'f() { for (int i in []) {} }';
buildElementsForText(code);
var variable = findLocalVariable(code, 'i in');
assertHasCodeRange(variable, 11, 5);
expect(variable.hasImplicitType, isFalse);
expect(variable.isConst, isFalse);
expect(variable.hasDeprecated, isFalse);
expect(variable.isFinal, isFalse);
expect(variable.hasOverride, isFalse);
expect(variable.isPrivate, isFalse);
expect(variable.isPublic, isTrue);
expect(variable.isSynthetic, isFalse);
expect(variable.name, 'i');
}
void test_visitDefaultFormalParameter_noType() {
// p = 0
String parameterName = 'p';
DefaultFormalParameter formalParameter =
AstTestFactory.positionalFormalParameter(
AstTestFactory.simpleFormalParameter3(parameterName),
AstTestFactory.integer(0));
formalParameter.beginToken.offset = 50;
formalParameter.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(formalParameter);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
assertHasCodeRange(parameter, 50, 31);
expect(parameter.hasImplicitType, isTrue);
expect(parameter.initializer, isNotNull);
expect(parameter.initializer.type, isNotNull);
expect(parameter.initializer.hasImplicitReturnType, isTrue);
expect(parameter.isConst, isFalse);
expect(parameter.hasDeprecated, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isInitializingFormal, isFalse);
expect(parameter.hasOverride, isFalse);
expect(parameter.isPrivate, isFalse);
expect(parameter.isPublic, isTrue);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
}
void test_visitDefaultFormalParameter_type() {
// E p = 0
String parameterName = 'p';
DefaultFormalParameter formalParameter =
AstTestFactory.namedFormalParameter(
AstTestFactory.simpleFormalParameter4(
AstTestFactory.typeName4('E'), parameterName),
AstTestFactory.integer(0));
ElementHolder holder = buildElementsForAst(formalParameter);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter.hasImplicitType, isFalse);
expect(parameter.initializer, isNotNull);
expect(parameter.initializer.type, isNotNull);
expect(parameter.initializer.hasImplicitReturnType, isTrue);
expect(parameter.isConst, isFalse);
expect(parameter.hasDeprecated, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isInitializingFormal, isFalse);
expect(parameter.hasOverride, isFalse);
expect(parameter.isPrivate, isFalse);
expect(parameter.isPublic, isTrue);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
}
void test_visitFunctionExpression() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
FunctionExpression expression = AstTestFactory.functionExpression2(
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
expression.accept(builder);
List<FunctionElement> functions = holder.functions;
expect(functions, hasLength(1));
FunctionElement function = functions[0];
expect(function, isNotNull);
expect(expression.declaredElement, same(function));
expect(function.hasImplicitReturnType, isTrue);
expect(function.isSynthetic, isFalse);
expect(function.typeParameters, hasLength(0));
}
void test_visitFunctionExpression_inBlockBody() {
buildElementsForText('f() { return () => 42; }');
FunctionDeclaration f = compilationUnit.declarations[0];
BlockFunctionBody fBody = f.functionExpression.body;
ReturnStatement returnStatement = fBody.block.statements[0];
FunctionExpression closure = returnStatement.expression;
FunctionElement function = closure.declaredElement;
expect(function, isNotNull);
expect(function.hasImplicitReturnType, isTrue);
expect(function.isSynthetic, isFalse);
expect(function.typeParameters, hasLength(0));
}
void test_visitFunctionExpression_inExpressionBody() {
buildElementsForText('f() => () => 42;');
FunctionDeclaration f = compilationUnit.declarations[0];
ExpressionFunctionBody fBody = f.functionExpression.body;
FunctionExpression closure = fBody.expression;
FunctionElement function = closure.declaredElement;
expect(function, isNotNull);
expect(function.hasImplicitReturnType, isTrue);
expect(function.isSynthetic, isFalse);
expect(function.typeParameters, hasLength(0));
}
void test_visitFunctionTypeAlias() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String aliasName = "F";
String parameterName = "E";
FunctionTypeAlias aliasNode = AstTestFactory.typeAlias(null, aliasName,
AstTestFactory.typeParameterList([parameterName]), null);
aliasNode.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
aliasNode.endToken.offset = 80;
aliasNode.accept(builder);
List<FunctionTypeAliasElement> aliases = holder.typeAliases;
expect(aliases, hasLength(1));
FunctionTypeAliasElement alias = aliases[0];
expect(alias, isNotNull);
assertHasCodeRange(alias, 50, 31);
expect(alias.documentationComment, '/// aaa');
expect(alias.name, aliasName);
expect(alias.parameters, hasLength(0));
List<TypeParameterElement> typeParameters = alias.typeParameters;
expect(typeParameters, hasLength(1));
TypeParameterElement typeParameter = typeParameters[0];
expect(typeParameter, isNotNull);
expect(typeParameter.name, parameterName);
}
void test_visitFunctionTypedFormalParameter() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
FunctionTypedFormalParameter formalParameter =
AstTestFactory.functionTypedFormalParameter(null, parameterName);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.name, parameterName);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitFunctionTypedFormalParameter_covariant() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
FunctionTypedFormalParameterImpl formalParameter =
AstTestFactory.functionTypedFormalParameter(null, parameterName);
formalParameter.covariantKeyword =
TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElementImpl parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.name, parameterName);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isExplicitlyCovariant, isTrue);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitFunctionTypedFormalParameter_withTypeParameters() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
FunctionTypedFormalParameter formalParameter =
AstTestFactory.functionTypedFormalParameter(null, parameterName);
formalParameter.typeParameters = AstTestFactory.typeParameterList(['F']);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
var typeElement = parameter.type.element as GenericFunctionTypeElementImpl;
expect(parameter, isNotNull);
expect(parameter.name, parameterName);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isRequiredPositional, isTrue);
expect(typeElement.typeParameters, hasLength(1));
_assertVisibleRange(parameter, 100, 110);
}
void test_visitLabeledStatement() {
String code = 'f() { l: print(42); }';
buildElementsForText(code);
LabelElement label = findLabel(code, 'l:');
expect(label, isNotNull);
expect(label.name, 'l');
expect(label.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_withMembers() {
var code = 'class C { m(p) { var v; try { l: return; } catch (e) {} } }';
MethodElement method = buildElementsForText(code).types[0].methods[0];
String methodName = "m";
String parameterName = "p";
String labelName = "l";
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isFalse);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
List<VariableElement> parameters = method.parameters;
expect(parameters, hasLength(1));
VariableElement parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.name, parameterName);
var v = findLocalVariable(code, 'v;');
expect(v.name, 'v');
var e = findLocalVariable(code, 'e) {}');
expect(e.name, 'e');
LabelElement label = findLabel(code, 'l:');
expect(label, isNotNull);
expect(label.name, labelName);
}
void test_visitNamedFormalParameter() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
DefaultFormalParameter formalParameter =
AstTestFactory.namedFormalParameter(
AstTestFactory.simpleFormalParameter3(parameterName),
AstTestFactory.identifier3("42"));
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.beginToken.offset = 50;
formalParameter.endToken.offset = 80;
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter, isNotNull);
assertHasCodeRange(parameter, 50, 32);
expect(parameter.name, parameterName);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isNamed, isTrue);
_assertVisibleRange(parameter, 100, 110);
expect(parameter.defaultValueCode, "42");
FunctionElement initializer = parameter.initializer;
expect(initializer, isNotNull);
expect(initializer.isSynthetic, isTrue);
expect(initializer.hasImplicitReturnType, isTrue);
}
void test_visitNamedFormalParameter_covariant() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
DefaultFormalParameter formalParameter =
AstTestFactory.namedFormalParameter(
AstTestFactory.simpleFormalParameter3(parameterName),
AstTestFactory.identifier3("42"));
(formalParameter.parameter as NormalFormalParameterImpl).covariantKeyword =
TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.beginToken.offset = 50;
formalParameter.endToken.offset = 80;
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElementImpl parameter = parameters[0];
expect(parameter, isNotNull);
assertHasCodeRange(parameter, 50, 32);
expect(parameter.name, parameterName);
expect(parameter.isConst, isFalse);
expect(parameter.isExplicitlyCovariant, isTrue);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isNamed, isTrue);
_assertVisibleRange(parameter, 100, 110);
expect(parameter.defaultValueCode, "42");
FunctionElement initializer = parameter.initializer;
expect(initializer, isNotNull);
expect(initializer.isSynthetic, isTrue);
expect(initializer.hasImplicitReturnType, isTrue);
}
void test_visitSimpleFormalParameter_noType() {
// p
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
SimpleFormalParameter formalParameter =
AstTestFactory.simpleFormalParameter3(parameterName);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.hasImplicitType, isTrue);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitSimpleFormalParameter_noType_covariant() {
// p
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
SimpleFormalParameterImpl formalParameter =
AstTestFactory.simpleFormalParameter3(parameterName);
formalParameter.covariantKeyword =
TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElementImpl parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.hasImplicitType, isTrue);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isExplicitlyCovariant, isTrue);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitSimpleFormalParameter_type() {
// T p
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
SimpleFormalParameter formalParameter =
AstTestFactory.simpleFormalParameter4(
AstTestFactory.typeName4('T'), parameterName);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.hasImplicitType, isFalse);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitSimpleFormalParameter_type_covariant() {
// T p
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String parameterName = "p";
SimpleFormalParameterImpl formalParameter =
AstTestFactory.simpleFormalParameter4(
AstTestFactory.typeName4('T'), parameterName);
formalParameter.covariantKeyword =
TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
_useParameterInMethod(formalParameter, 100, 110);
formalParameter.accept(builder);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElementImpl parameter = parameters[0];
expect(parameter, isNotNull);
expect(parameter.hasImplicitType, isFalse);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isExplicitlyCovariant, isTrue);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.name, parameterName);
expect(parameter.isRequiredPositional, isTrue);
_assertVisibleRange(parameter, 100, 110);
}
void test_visitVariableDeclaration_field_covariant() {
// covariant int f;
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String fieldName = "f";
VariableDeclarationImpl variableDeclaration =
AstTestFactory.variableDeclaration2(fieldName, null);
FieldDeclarationImpl fieldDeclaration = AstTestFactory.fieldDeclaration(
false,
null,
AstTestFactory.typeName4('int'),
<VariableDeclaration>[variableDeclaration]);
fieldDeclaration.covariantKeyword =
TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
variableDeclaration.accept(builder);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElementImpl field = fields[0];
expect(field, isNotNull);
PropertyAccessorElementImpl setter = field.setter;
expect(setter, isNotNull);
expect(setter.parameters[0].isCovariant, isTrue);
}
void test_visitVariableDeclaration_inConstructor() {
var code = 'class C { C() { var v = 1; } }';
buildElementsForText(code);
var v = findLocalVariable(code, 'v =');
assertHasCodeRange(v, 16, 9);
expect(v.hasImplicitType, isTrue);
expect(v.name, 'v');
_assertVisibleRange(v, 14, 28);
}
void test_visitVariableDeclaration_inForEachStatement() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
//
// m() { for (var v in []) }
//
String variableName = "v";
DeclaredIdentifier variableIdentifier =
AstTestFactory.declaredIdentifier3('v');
Statement statement = AstTestFactory.forStatement(
AstTestFactory.forEachPartsWithDeclaration(
variableIdentifier, AstTestFactory.listLiteral()),
AstTestFactory.block());
_setNodeSourceRange(statement, 100, 110);
MethodDeclaration method = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3("m"),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2([statement]));
_setBlockBodySourceRange(method.body, 200, 220);
method.accept(builder);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
LocalVariableElement variableElement = variableIdentifier.declaredElement;
expect(variableElement.name, variableName);
_assertVisibleRange(variableElement, 100, 110);
}
void test_visitVariableDeclaration_inForStatement() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
//
// m() { for (T v;;) }
//
String variableName = "v";
VariableDeclaration variableIdentifier =
AstTestFactory.variableDeclaration('v');
ForStatement statement = AstTestFactory.forStatement(
AstTestFactory.forPartsWithDeclarations(
AstTestFactory.variableDeclarationList(
null, AstTestFactory.typeName4('T'), [variableIdentifier]),
null,
null),
AstTestFactory.block());
_setNodeSourceRange(statement, 100, 110);
MethodDeclaration method = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3("m"),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2([statement]));
_setBlockBodySourceRange(method.body, 200, 220);
method.accept(builder);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
LocalVariableElement variableElement = variableIdentifier.declaredElement;
expect(variableElement.name, variableName);
_assertVisibleRange(variableElement, 100, 110);
}
void test_visitVariableDeclaration_inMethod() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
//
// m() {T v;}
//
String variableName = "v";
VariableDeclaration variable =
AstTestFactory.variableDeclaration2(variableName, null);
Statement statement = AstTestFactory.variableDeclarationStatement(
null, AstTestFactory.typeName4('T'), [variable]);
MethodDeclaration method = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3("m"),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2([statement]));
_setBlockBodySourceRange(method.body, 100, 110);
method.accept(builder);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
LocalVariableElement variableElement = variable.declaredElement;
expect(variableElement.hasImplicitType, isFalse);
expect(variableElement.name, variableName);
_assertVisibleRange(variableElement, 100, 110);
}
void test_visitVariableDeclaration_localNestedInFunction() {
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
//
// var f = () {var v;};
//
String variableName = "v";
VariableDeclaration variable =
AstTestFactory.variableDeclaration2(variableName, null);
Statement statement =
AstTestFactory.variableDeclarationStatement2(null, [variable]);
FunctionExpression initializer = AstTestFactory.functionExpression2(
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2([statement]));
String fieldName = "f";
VariableDeclaration field =
AstTestFactory.variableDeclaration2(fieldName, initializer);
FieldDeclaration fieldDeclaration =
AstTestFactory.fieldDeclaration2(false, null, [field]);
fieldDeclaration.accept(builder);
List<FieldElement> variables = holder.fields;
expect(variables, hasLength(1));
FieldElement fieldElement = variables[0];
expect(fieldElement, isNotNull);
FunctionElement initializerElement = fieldElement.initializer;
expect(initializerElement, isNotNull);
expect(initializerElement.hasImplicitReturnType, isTrue);
expect(initializer.declaredElement, isFunctionElement);
LocalVariableElement variableElement = variable.declaredElement;
expect(variableElement.hasImplicitType, isTrue);
expect(variableElement.isConst, isFalse);
expect(variableElement.isFinal, isFalse);
expect(variableElement.isSynthetic, isFalse);
expect(variableElement.name, variableName);
}
void test_visitVariableDeclaration_noInitializer() {
// var v;
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String variableName = "v";
VariableDeclaration variableDeclaration =
AstTestFactory.variableDeclaration2(variableName, null);
AstTestFactory.variableDeclarationList2(null, [variableDeclaration]);
variableDeclaration.accept(builder);
List<TopLevelVariableElement> variables = holder.topLevelVariables;
expect(variables, hasLength(1));
TopLevelVariableElement variable = variables[0];
expect(variable, isNotNull);
expect(variable.hasImplicitType, isTrue);
expect(variable.initializer, isNull);
expect(variable.name, variableName);
expect(variable.isConst, isFalse);
expect(variable.isFinal, isFalse);
expect(variable.isSynthetic, isFalse);
expect(variable.getter, isNotNull);
expect(variable.setter, isNotNull);
}
void test_visitVariableDeclaration_top() {
// final a, b;
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
VariableDeclaration variableDeclaration1 =
AstTestFactory.variableDeclaration('a');
VariableDeclaration variableDeclaration2 =
AstTestFactory.variableDeclaration('b');
TopLevelVariableDeclaration topLevelVariableDeclaration =
AstTestFactory.topLevelVariableDeclaration(
Keyword.FINAL, null, [variableDeclaration1, variableDeclaration2]);
topLevelVariableDeclaration.documentationComment =
AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
topLevelVariableDeclaration.accept(builder);
List<TopLevelVariableElement> variables = holder.topLevelVariables;
expect(variables, hasLength(2));
TopLevelVariableElement variable1 = variables[0];
expect(variable1, isNotNull);
expect(variable1.documentationComment, '/// aaa');
TopLevelVariableElement variable2 = variables[1];
expect(variable2, isNotNull);
expect(variable2.documentationComment, '/// aaa');
}
void test_visitVariableDeclaration_top_const_hasInitializer() {
// const v = 42;
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String variableName = "v";
VariableDeclaration variableDeclaration =
AstTestFactory.variableDeclaration2(
variableName, AstTestFactory.integer(42));
AstTestFactory.variableDeclarationList2(
Keyword.CONST, [variableDeclaration]);
variableDeclaration.accept(builder);
List<TopLevelVariableElement> variables = holder.topLevelVariables;
expect(variables, hasLength(1));
TopLevelVariableElement variable = variables[0];
expect(variable, new TypeMatcher<ConstTopLevelVariableElementImpl>());
expect(variable.initializer, isNotNull);
expect(variable.initializer.type, isNotNull);
expect(variable.initializer.hasImplicitReturnType, isTrue);
expect(variable.name, variableName);
expect(variable.hasImplicitType, isTrue);
expect(variable.isConst, isTrue);
expect(variable.isFinal, isFalse);
expect(variable.isSynthetic, isFalse);
expect(variable.getter, isNotNull);
expect(variable.setter, isNull);
}
void test_visitVariableDeclaration_top_final() {
// final v;
ElementHolder holder = new ElementHolder();
ElementBuilder builder = _makeBuilder(holder);
String variableName = "v";
VariableDeclaration variableDeclaration =
AstTestFactory.variableDeclaration2(variableName, null);
AstTestFactory.variableDeclarationList2(
Keyword.FINAL, [variableDeclaration]);
variableDeclaration.accept(builder);
List<TopLevelVariableElement> variables = holder.topLevelVariables;
expect(variables, hasLength(1));
TopLevelVariableElement variable = variables[0];
expect(variable, isNotNull);
expect(variable.hasImplicitType, isTrue);
expect(variable.initializer, isNull);
expect(variable.name, variableName);
expect(variable.isConst, isFalse);
expect(variable.isFinal, isTrue);
expect(variable.isSynthetic, isFalse);
expect(variable.getter, isNotNull);
expect(variable.setter, isNull);
}
ElementBuilder _makeBuilder(ElementHolder holder) =>
new ElementBuilder(holder, compilationUnitElement);
void _setBlockBodySourceRange(BlockFunctionBody body, int offset, int end) {
_setNodeSourceRange(body.block, offset, end);
}
void _setNodeSourceRange(AstNode node, int offset, int end) {
node.beginToken.offset = offset;
Token endToken = node.endToken;
endToken.offset = end - endToken.length;
}
void _useParameterInMethod(
FormalParameter formalParameter, int blockOffset, int blockEnd) {
Block block = AstTestFactory.block();
block.leftBracket.offset = blockOffset;
block.rightBracket.offset = blockEnd - 1;
BlockFunctionBody body = AstTestFactory.blockFunctionBody(block);
AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3("main"),
AstTestFactory.formalParameterList([formalParameter]),
body);
}
}
@reflectiveTest
class LocalElementBuilderTest extends _BaseTest {
@override
AstVisitor createElementBuilder(ElementHolder holder) {
return new LocalElementBuilder(holder, compilationUnitElement);
}
void test_buildLocalElements() {
var code = r'''
main() {
int v1;
f1() {
int v2;
f2() {
int v3;
}
}
}
''';
_compilationUnit = parseCompilationUnit(code);
var mainAst = _compilationUnit.declarations.single as FunctionDeclaration;
// Build API elements.
FunctionElementImpl main;
{
ElementHolder holder = new ElementHolder();
_compilationUnit
.accept(new ApiElementBuilder(holder, compilationUnitElement));
main = holder.functions.single as FunctionElementImpl;
}
// Build local elements in body.
ElementHolder holder = new ElementHolder();
FunctionBody mainBody = mainAst.functionExpression.body;
mainBody.accept(new LocalElementBuilder(holder, compilationUnitElement));
main.encloseElements(holder.functions);
main.encloseElements(holder.localVariables);
var f1 = findLocalFunction(code, 'f1() {');
var f2 = findLocalFunction(code, 'f2() {');
var v1 = findLocalVariable(code, 'v1;');
var v2 = findLocalVariable(code, 'v2;');
var v3 = findLocalVariable(code, 'v3;');
expect(v1.enclosingElement, main);
{
expect(f1.name, 'f1');
expect(v2.enclosingElement, f1);
{
expect(f2.name, 'f2');
expect(v3.enclosingElement, f2);
}
}
}
void test_buildParameterInitializer() {
CompilationUnit unit = parseCompilationUnit('f({p: 42}) {}');
var function = unit.declarations.single as FunctionDeclaration;
var parameter = function.functionExpression.parameters.parameters.single
as DefaultFormalParameter;
// Build API elements.
{
ElementHolder holder = new ElementHolder();
unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
}
// Validate the parameter element.
var parameterElement = parameter.declaredElement as ParameterElementImpl;
expect(parameterElement, isNotNull);
expect(parameterElement.initializer, isNull);
// Build the initializer element.
new LocalElementBuilder(new ElementHolder(), compilationUnitElement)
.buildParameterInitializer(parameterElement, parameter.defaultValue);
expect(parameterElement.initializer, isNotNull);
}
void test_buildVariableInitializer() {
CompilationUnit unit = parseCompilationUnit('var V = 42;');
TopLevelVariableDeclaration topLevelDecl =
unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration variable = topLevelDecl.variables.variables.single;
// Build the variable element.
{
ElementHolder holder = new ElementHolder();
unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
}
// Validate the variable element.
var variableElement = variable.declaredElement as VariableElementImpl;
expect(variableElement, isNotNull);
expect(variableElement.initializer, isNull);
// Build the initializer element.
new LocalElementBuilder(new ElementHolder(), compilationUnitElement)
.buildVariableInitializer(variableElement, variable.initializer);
expect(variableElement.initializer, isNotNull);
}
void test_genericFunction_isExpression() {
buildElementsForText('main(p) { p is Function(int a, String); }');
var main = compilationUnit.declarations[0] as FunctionDeclaration;
var body = main.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var expression = statement.expression as IsExpression;
var typeNode = expression.type as GenericFunctionType;
var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
expect(typeElement.parameters, hasLength(2));
expect(typeElement.parameters[0].name, 'a');
expect(typeElement.parameters[1].name, '');
}
void test_visitDefaultFormalParameter_local() {
CompilationUnit unit = parseCompilationUnit('''
main() {
f({bool b: false}) {}
}
''');
var mainAst = unit.declarations.single as FunctionDeclaration;
// Build API elements.
FunctionElementImpl main;
{
ElementHolder holder = new ElementHolder();
unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
main = holder.functions.single as FunctionElementImpl;
}
// Build local elements in body.
ElementHolder holder = new ElementHolder();
FunctionBody mainBody = mainAst.functionExpression.body;
mainBody.accept(new LocalElementBuilder(holder, compilationUnitElement));
List<FunctionElement> functions = holder.functions;
main.encloseElements(functions);
FunctionElement f = findElementsByName(unit, 'f').single;
expect(f.parameters, hasLength(1));
expect(f.parameters[0].initializer, isNotNull);
}
void test_visitFieldFormalParameter() {
CompilationUnit unit = parseCompilationUnit(r'''
main() {
f(a, this.b) {}
}
''', codes: [ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
var main = unit.declarations[0] as FunctionDeclaration;
var mainBody = main.functionExpression.body as BlockFunctionBody;
var mainBlock = mainBody.block;
var statement = mainBlock.statements[0] as FunctionDeclarationStatement;
FunctionDeclaration f = statement.functionDeclaration;
// Build API elements.
{
ElementHolder holder = new ElementHolder();
unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
}
// Build local elements.
ElementHolder holder = new ElementHolder();
var builder = new LocalElementBuilder(holder, compilationUnitElement);
f.accept(builder);
List<FormalParameter> parameters =
f.functionExpression.parameters.parameters;
ParameterElement a = parameters[0].declaredElement;
expect(a, isNotNull);
expect(a.name, 'a');
ParameterElement b = parameters[1].declaredElement;
expect(b, isNotNull);
expect(b.name, 'b');
}
void test_visitVariableDeclaration_local() {
var code = 'class C { m() { T v = null; } }';
buildElementsForText(code);
LocalVariableElement element = findIdentifier(code, 'v =').staticElement;
expect(element.hasImplicitType, isFalse);
expect(element.name, 'v');
expect(element.initializer, isNotNull);
_assertVisibleRange(element, 14, 29);
}
}
/**
* Mixin with test methods for testing element building in [ApiElementBuilder].
* It is used to test the [ApiElementBuilder] itself, and its usage by
* [ElementBuilder].
*/
mixin _ApiElementBuilderTestMixin {
CompilationUnit get compilationUnit;
void set isMixinSupportEnabled(bool value);
void assertHasCodeRange(Element element, int offset, int length);
/**
* Build elements using [ApiElementBuilder].
*/
ElementHolder buildElementsForAst(AstNode node);
/**
* Parse the given [code], and build elements using [ApiElementBuilder].
*/
ElementHolder buildElementsForText(String code);
/**
* Verify that the given [metadata] has exactly one annotation, and that its
* [ElementAnnotationImpl] is unresolved.
*/
void checkAnnotation(NodeList<Annotation> metadata);
/**
* Verify that the given [element] has exactly one annotation, and that its
* [ElementAnnotationImpl] is unresolved.
*/
void checkMetadata(Element element);
void test_genericFunction_asTopLevelVariableType() {
buildElementsForText('int Function(int a, String) v;');
var v = compilationUnit.declarations[0] as TopLevelVariableDeclaration;
var typeNode = v.variables.type as GenericFunctionType;
var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
expect(typeElement.parameters, hasLength(2));
expect(typeElement.parameters[0].name, 'a');
expect(typeElement.parameters[1].name, '');
}
void test_metadata_fieldDeclaration() {
List<FieldElement> fields =
buildElementsForText('class C { @a int x, y; }').types[0].fields;
checkMetadata(fields[0]);
checkMetadata(fields[1]);
expect(fields[0].metadata, same(fields[1].metadata));
}
void test_metadata_topLevelVariableDeclaration() {
List<TopLevelVariableElement> topLevelVariables =
buildElementsForText('@a int x, y;').topLevelVariables;
checkMetadata(topLevelVariables[0]);
checkMetadata(topLevelVariables[1]);
expect(topLevelVariables[0].metadata, same(topLevelVariables[1].metadata));
}
void test_metadata_visitClassDeclaration() {
ClassElement classElement = buildElementsForText('@a class C {}').types[0];
checkMetadata(classElement);
}
void test_metadata_visitClassTypeAlias() {
ClassElement classElement =
buildElementsForText('@a class C = D with E;').types[0];
checkMetadata(classElement);
}
void test_metadata_visitConstructorDeclaration() {
ConstructorElement constructorElement =
buildElementsForText('class C { @a C(); }').types[0].constructors[0];
checkMetadata(constructorElement);
}
void test_metadata_visitDefaultFormalParameter_fieldFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('class C { var x; C([@a this.x = null]); }')
.types[0]
.constructors[0]
.parameters[0];
checkMetadata(parameterElement);
}
void
test_metadata_visitDefaultFormalParameter_functionTypedFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('f([@a g() = null]) {}')
.functions[0]
.parameters[0];
checkMetadata(parameterElement);
}
void test_metadata_visitDefaultFormalParameter_simpleFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('f([@a gx = null]) {}').functions[0].parameters[0];
checkMetadata(parameterElement);
}
void test_metadata_visitEnumConstant() {
ElementHolder enumElement = buildElementsForText('enum E { @a v }');
FieldElement v = enumElement.enums[0].fields[0];
expect(v.name, 'v');
checkMetadata(v);
}
void test_metadata_visitEnumDeclaration() {
ClassElement classElement =
buildElementsForText('@a enum E { v }').enums[0];
checkMetadata(classElement);
}
void test_metadata_visitExportDirective() {
buildElementsForText('@a export "foo.dart";');
expect(compilationUnit.directives[0], new TypeMatcher<ExportDirective>());
ExportDirective exportDirective = compilationUnit.directives[0];
checkAnnotation(exportDirective.metadata);
}
void test_metadata_visitFieldFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('class C { var x; C(@a this.x); }')
.types[0]
.constructors[0]
.parameters[0];
checkMetadata(parameterElement);
}
void test_metadata_visitFunctionDeclaration_function() {
FunctionElement functionElement =
buildElementsForText('@a f() {}').functions[0];
checkMetadata(functionElement);
}
void test_metadata_visitFunctionDeclaration_getter() {
PropertyAccessorElement propertyAccessorElement =
buildElementsForText('@a get f => null;').accessors[0];
checkMetadata(propertyAccessorElement);
}
void test_metadata_visitFunctionDeclaration_setter() {
PropertyAccessorElement propertyAccessorElement =
buildElementsForText('@a set f(value) {}').accessors[0];
checkMetadata(propertyAccessorElement);
}
void test_metadata_visitFunctionTypeAlias() {
FunctionTypeAliasElement functionTypeAliasElement =
buildElementsForText('@a typedef F();').typeAliases[0];
checkMetadata(functionTypeAliasElement);
}
void test_metadata_visitFunctionTypedFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('f(@a g()) {}').functions[0].parameters[0];
checkMetadata(parameterElement);
}
void test_metadata_visitImportDirective() {
buildElementsForText('@a import "foo.dart";');
expect(compilationUnit.directives[0], new TypeMatcher<ImportDirective>());
ImportDirective importDirective = compilationUnit.directives[0];
checkAnnotation(importDirective.metadata);
}
void test_metadata_visitLibraryDirective() {
buildElementsForText('@a library L;');
expect(compilationUnit.directives[0], new TypeMatcher<LibraryDirective>());
LibraryDirective libraryDirective = compilationUnit.directives[0];
checkAnnotation(libraryDirective.metadata);
}
void test_metadata_visitMethodDeclaration_getter() {
PropertyAccessorElement propertyAccessorElement =
buildElementsForText('class C { @a get m => null; }')
.types[0]
.accessors[0];
checkMetadata(propertyAccessorElement);
}
void test_metadata_visitMethodDeclaration_method() {
MethodElement methodElement =
buildElementsForText('class C { @a m() {} }').types[0].methods[0];
checkMetadata(methodElement);
}
void test_metadata_visitMethodDeclaration_setter() {
PropertyAccessorElement propertyAccessorElement =
buildElementsForText('class C { @a set f(value) {} }')
.types[0]
.accessors[0];
checkMetadata(propertyAccessorElement);
}
void test_metadata_visitPartDirective() {
buildElementsForText('@a part "foo.dart";');
expect(compilationUnit.directives[0], new TypeMatcher<PartDirective>());
PartDirective partDirective = compilationUnit.directives[0];
checkAnnotation(partDirective.metadata);
}
void test_metadata_visitPartOfDirective() {
// We don't build ElementAnnotation objects for `part of` directives, since
// analyzer ignores them in favor of annotations on the library directive.
buildElementsForText('@a part of L;');
expect(compilationUnit.directives[0], new TypeMatcher<PartOfDirective>());
PartOfDirective partOfDirective = compilationUnit.directives[0];
expect(partOfDirective.metadata, hasLength(1));
expect(partOfDirective.metadata[0].elementAnnotation, isNull);
}
void test_metadata_visitSimpleFormalParameter() {
ParameterElement parameterElement =
buildElementsForText('f(@a x) {}').functions[0].parameters[0];
checkMetadata(parameterElement);
}
void test_metadata_visitTypeParameter() {
TypeParameterElement typeParameterElement =
buildElementsForText('class C<@a T> {}').types[0].typeParameters[0];
checkMetadata(typeParameterElement);
}
void test_visitClassDeclaration_abstract() {
List<ClassElement> types =
buildElementsForText('abstract class C {}').types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type, isNotNull);
expect(type.name, 'C');
List<TypeParameterElement> typeParameters = type.typeParameters;
expect(typeParameters, hasLength(0));
expect(type.isAbstract, isTrue);
expect(type.isMixinApplication, isFalse);
expect(type.isSynthetic, isFalse);
}
void test_visitClassDeclaration_invalidFunctionInAnnotation_class() {
// https://github.com/dart-lang/sdk/issues/25696
String code = r'''
class A {
const A({f});
}
@A(f: () {})
class C {}
''';
buildElementsForText(code);
}
void test_visitClassDeclaration_invalidFunctionInAnnotation_method() {
String code = r'''
class A {
const A({f});
}
class C {
@A(f: () {})
void m() {}
}
''';
ElementHolder holder = buildElementsForText(code);
ClassElement elementC = holder.types[1];
expect(elementC, isNotNull);
MethodElement methodM = elementC.methods[0];
expect(methodM, isNotNull);
}
void test_visitClassDeclaration_minimal() {
String className = "C";
ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
null, className, null, null, null, null);
classDeclaration.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
classDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(classDeclaration);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type, isNotNull);
expect(type.name, className);
List<TypeParameterElement> typeParameters = type.typeParameters;
expect(typeParameters, hasLength(0));
expect(type.isAbstract, isFalse);
expect(type.isMixinApplication, isFalse);
expect(type.isSynthetic, isFalse);
expect(type.documentationComment, '/// aaa');
assertHasCodeRange(type, 50, 31);
}
void test_visitClassDeclaration_parameterized() {
String className = "C";
String firstVariableName = "E";
String secondVariableName = "F";
ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
null,
className,
AstTestFactory.typeParameterList(
[firstVariableName, secondVariableName]),
null,
null,
null);
ElementHolder holder = buildElementsForAst(classDeclaration);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type, isNotNull);
expect(type.name, className);
List<TypeParameterElement> typeParameters = type.typeParameters;
expect(typeParameters, hasLength(2));
expect(typeParameters[0].name, firstVariableName);
expect(typeParameters[1].name, secondVariableName);
expect(type.isAbstract, isFalse);
expect(type.isMixinApplication, isFalse);
expect(type.isSynthetic, isFalse);
}
void test_visitClassDeclaration_withMembers() {
String className = "C";
String typeParameterName = "E";
String fieldName = "f";
String methodName = "m";
ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
null,
className,
AstTestFactory.typeParameterList([typeParameterName]),
null,
null,
null, [
AstTestFactory.fieldDeclaration2(
false, null, [AstTestFactory.variableDeclaration(fieldName)]),
AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2())
]);
ElementHolder holder = buildElementsForAst(classDeclaration);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type, isNotNull);
expect(type.name, className);
expect(type.isAbstract, isFalse);
expect(type.isMixinApplication, isFalse);
expect(type.isSynthetic, isFalse);
List<TypeParameterElement> typeParameters = type.typeParameters;
expect(typeParameters, hasLength(1));
TypeParameterElement typeParameter = typeParameters[0];
expect(typeParameter, isNotNull);
expect(typeParameter.name, typeParameterName);
List<FieldElement> fields = type.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, fieldName);
List<MethodElement> methods = type.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.name, methodName);
}
void test_visitClassTypeAlias() {
// class B {}
// class M {}
// class C = B with M
ClassElementImpl classB = ElementFactory.classElement2('B', []);
ConstructorElementImpl constructorB =
ElementFactory.constructorElement2(classB, '', []);
constructorB.setModifier(Modifier.SYNTHETIC, true);
classB.constructors = [constructorB];
ClassElement classM = ElementFactory.classElement2('M', []);
WithClause withClause =
AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
ClassTypeAlias alias = AstTestFactory.classTypeAlias(
'C', null, null, AstTestFactory.typeName(classB, []), withClause, null);
ElementHolder holder = buildElementsForAst(alias);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(alias.declaredElement, same(type));
expect(type.name, equals('C'));
expect(type.isAbstract, isFalse);
expect(type.isMixinApplication, isTrue);
expect(type.isSynthetic, isFalse);
expect(type.typeParameters, isEmpty);
expect(type.fields, isEmpty);
expect(type.methods, isEmpty);
}
void test_visitClassTypeAlias_abstract() {
// class B {}
// class M {}
// abstract class C = B with M
ClassElementImpl classB = ElementFactory.classElement2('B', []);
ConstructorElementImpl constructorB =
ElementFactory.constructorElement2(classB, '', []);
constructorB.setModifier(Modifier.SYNTHETIC, true);
classB.constructors = [constructorB];
ClassElement classM = ElementFactory.classElement2('M', []);
WithClause withClause =
AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
ClassTypeAlias alias = AstTestFactory.classTypeAlias(
'C',
null,
Keyword.ABSTRACT,
AstTestFactory.typeName(classB, []),
withClause,
null);
ElementHolder holder = buildElementsForAst(alias);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type.isAbstract, isTrue);
expect(type.isMixinApplication, isTrue);
}
void test_visitClassTypeAlias_typeParams() {
// class B {}
// class M {}
// class C<T> = B with M
ClassElementImpl classB = ElementFactory.classElement2('B', []);
ConstructorElementImpl constructorB =
ElementFactory.constructorElement2(classB, '', []);
constructorB.setModifier(Modifier.SYNTHETIC, true);
classB.constructors = [constructorB];
ClassElementImpl classM = ElementFactory.classElement2('M', []);
WithClause withClause =
AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
ClassTypeAlias alias = AstTestFactory.classTypeAlias(
'C',
AstTestFactory.typeParameterList(['T']),
null,
AstTestFactory.typeName(classB, []),
withClause,
null);
ElementHolder holder = buildElementsForAst(alias);
List<ClassElement> types = holder.types;
expect(types, hasLength(1));
ClassElement type = types[0];
expect(type.typeParameters, hasLength(1));
expect(type.typeParameters[0].name, equals('T'));
}
void test_visitConstructorDeclaration_external() {
String className = "A";
ConstructorDeclaration constructorDeclaration =
AstTestFactory.constructorDeclaration2(
null,
null,
AstTestFactory.identifier3(className),
null,
AstTestFactory.formalParameterList(),
null,
AstTestFactory.blockFunctionBody2());
constructorDeclaration.externalKeyword =
TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
ElementHolder holder = buildElementsForAst(constructorDeclaration);
List<ConstructorElement> constructors = holder.constructors;
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
expect(constructor.isExternal, isTrue);
expect(constructor.isFactory, isFalse);
expect(constructor.name, "");
expect(constructor.parameters, hasLength(0));
}
void test_visitConstructorDeclaration_factory() {
String className = "A";
ConstructorDeclaration constructorDeclaration =
AstTestFactory.constructorDeclaration2(
null,
Keyword.FACTORY,
AstTestFactory.identifier3(className),
null,
AstTestFactory.formalParameterList(),
null,
AstTestFactory.blockFunctionBody2());
ElementHolder holder = buildElementsForAst(constructorDeclaration);
List<ConstructorElement> constructors = holder.constructors;
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
expect(constructor.isExternal, isFalse);
expect(constructor.isFactory, isTrue);
expect(constructor.name, "");
expect(constructor.parameters, hasLength(0));
}
void test_visitConstructorDeclaration_minimal() {
String className = "A";
ConstructorDeclaration constructorDeclaration =
AstTestFactory.constructorDeclaration2(
null,
null,
AstTestFactory.identifier3(className),
null,
AstTestFactory.formalParameterList(),
null,
AstTestFactory.blockFunctionBody2());
constructorDeclaration.documentationComment =
AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
constructorDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(constructorDeclaration);
List<ConstructorElement> constructors = holder.constructors;
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
assertHasCodeRange(constructor, 50, 31);
expect(constructor.documentationComment, '/// aaa');
expect(constructor.isExternal, isFalse);
expect(constructor.isFactory, isFalse);
expect(constructor.name, "");
expect(constructor.parameters, hasLength(0));
}
void test_visitConstructorDeclaration_named() {
String className = "A";
String constructorName = "c";
ConstructorDeclaration constructorDeclaration =
AstTestFactory.constructorDeclaration2(
null,
null,
AstTestFactory.identifier3(className),
constructorName,
AstTestFactory.formalParameterList(),
null,
AstTestFactory.blockFunctionBody2());
ElementHolder holder = buildElementsForAst(constructorDeclaration);
List<ConstructorElement> constructors = holder.constructors;
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
expect(constructor.isExternal, isFalse);
expect(constructor.isFactory, isFalse);
expect(constructor.name, constructorName);
expect(constructor.parameters, hasLength(0));
expect(constructorDeclaration.name.staticElement, same(constructor));
expect(constructorDeclaration.declaredElement, same(constructor));
}
void test_visitConstructorDeclaration_unnamed() {
String className = "A";
ConstructorDeclaration constructorDeclaration =
AstTestFactory.constructorDeclaration2(
null,
null,
AstTestFactory.identifier3(className),
null,
AstTestFactory.formalParameterList(),
null,
AstTestFactory.blockFunctionBody2());
ElementHolder holder = buildElementsForAst(constructorDeclaration);
List<ConstructorElement> constructors = holder.constructors;
expect(constructors, hasLength(1));
ConstructorElement constructor = constructors[0];
expect(constructor, isNotNull);
expect(constructor.isExternal, isFalse);
expect(constructor.isFactory, isFalse);
expect(constructor.name, "");
expect(constructor.parameters, hasLength(0));
expect(constructorDeclaration.declaredElement, same(constructor));
}
void test_visitEnumDeclaration() {
String enumName = "E";
EnumDeclaration enumDeclaration =
AstTestFactory.enumDeclaration2(enumName, ["ONE"]);
enumDeclaration.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
enumDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(enumDeclaration);
List<ClassElement> enums = holder.enums;
expect(enums, hasLength(1));
ClassElement enumElement = enums[0];
expect(enumElement, isNotNull);
assertHasCodeRange(enumElement, 50, 31);
expect(enumElement.documentationComment, '/// aaa');
expect(enumElement.name, enumName);
}
void test_visitFieldDeclaration() {
var holder = buildElementsForText(r'''
class C {
/// aaa
int x = 1, y;
}
''');
ClassElement c = holder.types.single;
List<FieldElement> fields = c.fields;
expect(fields, hasLength(2));
FieldElement x = fields[0];
expect(x, isNotNull);
assertHasCodeRange(x, 12, 19);
expect(x.documentationComment, '/// aaa');
expect(x.name, 'x');
_assertHasVariableInitializer(x);
expect(x.isConst, isFalse);
expect(x.isFinal, isFalse);
expect(x.isSynthetic, isFalse);
FieldElement y = fields[1];
expect(y, isNotNull);
assertHasCodeRange(y, 33, 1);
expect(y.documentationComment, '/// aaa');
expect(y.name, 'y');
expect(y.initializer, isNull);
expect(y.isConst, isFalse);
expect(y.isFinal, isFalse);
expect(y.isSynthetic, isFalse);
}
void test_visitFieldFormalParameter() {
String parameterName = "p";
FieldFormalParameter formalParameter =
AstTestFactory.fieldFormalParameter(null, null, parameterName);
formalParameter.beginToken.offset = 50;
formalParameter.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(formalParameter);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
expect(parameter, isNotNull);
assertHasCodeRange(parameter, 50, 31);
expect(parameter.name, parameterName);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isRequiredPositional, isTrue);
expect(parameter.parameters, hasLength(0));
}
void test_visitFieldFormalParameter_functionTyped() {
String parameterName = "p";
FieldFormalParameter formalParameter = AstTestFactory.fieldFormalParameter(
null,
null,
parameterName,
AstTestFactory.formalParameterList(
[AstTestFactory.simpleFormalParameter3("a")]));
ElementHolder holder = buildElementsForAst(formalParameter);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(1));
ParameterElement parameter = parameters[0];
var typeElement = parameter.type.element as GenericFunctionTypeElementImpl;
expect(parameter, isNotNull);
expect(parameter.name, parameterName);
expect(parameter.initializer, isNull);
expect(parameter.isConst, isFalse);
expect(parameter.isFinal, isFalse);
expect(parameter.isSynthetic, isFalse);
expect(parameter.isRequiredPositional, isTrue);
expect(typeElement.parameters, hasLength(1));
}
void test_visitFormalParameterList() {
String firstParameterName = "a";
String secondParameterName = "b";
FormalParameterList parameterList = AstTestFactory.formalParameterList([
AstTestFactory.simpleFormalParameter3(firstParameterName),
AstTestFactory.simpleFormalParameter3(secondParameterName)
]);
ElementHolder holder = buildElementsForAst(parameterList);
List<ParameterElement> parameters = holder.parameters;
expect(parameters, hasLength(2));
expect(parameters[0].name, firstParameterName);
expect(parameters[1].name, secondParameterName);
}
void test_visitFunctionDeclaration_external() {
// external f();
String functionName = "f";
FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
null,
null,
functionName,
AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody()));
declaration.externalKeyword =
TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
ElementHolder holder = buildElementsForAst(declaration);
List<FunctionElement> functions = holder.functions;
expect(functions, hasLength(1));
FunctionElement function = functions[0];
expect(function, isNotNull);
expect(function.name, functionName);
expect(declaration.declaredElement, same(function));
expect(declaration.functionExpression.declaredElement, same(function));
expect(function.hasImplicitReturnType, isTrue);
expect(function.isExternal, isTrue);
expect(function.isSynthetic, isFalse);
expect(function.typeParameters, hasLength(0));
}
void test_visitFunctionDeclaration_getter() {
// get f() {}
String functionName = "f";
FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
null,
Keyword.GET,
functionName,
AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2()));
declaration.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
declaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(declaration);
List<PropertyAccessorElement> accessors = holder.accessors;
expect(accessors, hasLength(1));
PropertyAccessorElement accessor = accessors[0];
expect(accessor, isNotNull);
assertHasCodeRange(accessor, 50, 31);
expect(accessor.documentationComment, '/// aaa');
expect(accessor.name, functionName);
expect(declaration.declaredElement, same(accessor));
expect(declaration.functionExpression.declaredElement, same(accessor));
expect(accessor.hasImplicitReturnType, isTrue);
expect(accessor.isGetter, isTrue);
expect(accessor.isExternal, isFalse);
expect(accessor.isSetter, isFalse);
expect(accessor.isSynthetic, isFalse);
expect(accessor.typeParameters, hasLength(0));
TopLevelVariableElement variable = accessor.variable;
expect(variable.isSynthetic, isTrue);
}
void test_visitFunctionDeclaration_plain() {
// T f() {}
String functionName = "f";
FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
AstTestFactory.typeName4('T'),
null,
functionName,
AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2()));
declaration.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
declaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(declaration);
List<FunctionElement> functions = holder.functions;
expect(functions, hasLength(1));
FunctionElement function = functions[0];
expect(function, isNotNull);
assertHasCodeRange(function, 50, 31);
expect(function.documentationComment, '/// aaa');
expect(function.hasImplicitReturnType, isFalse);
expect(function.name, functionName);
expect(declaration.declaredElement, same(function));
expect(declaration.functionExpression.declaredElement, same(function));
expect(function.isExternal, isFalse);
expect(function.isSynthetic, isFalse);
expect(function.typeParameters, hasLength(0));
}
void test_visitFunctionDeclaration_setter() {
// set f() {}
String functionName = "f";
FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
null,
Keyword.SET,
functionName,
AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2()));
declaration.documentationComment = AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
declaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(declaration);
List<PropertyAccessorElement> accessors = holder.accessors;
expect(accessors, hasLength(1));
PropertyAccessorElement accessor = accessors[0];
expect(accessor, isNotNull);
assertHasCodeRange(accessor, 50, 31);
expect(accessor.documentationComment, '/// aaa');
expect(accessor.hasImplicitReturnType, isTrue);
expect(accessor.name, "$functionName=");
expect(declaration.declaredElement, same(accessor));
expect(declaration.functionExpression.declaredElement, same(accessor));
expect(accessor.isGetter, isFalse);
expect(accessor.isExternal, isFalse);
expect(accessor.isSetter, isTrue);
expect(accessor.isSynthetic, isFalse);
expect(accessor.typeParameters, hasLength(0));
TopLevelVariableElement variable = accessor.variable;
expect(variable.isSynthetic, isTrue);
}
void test_visitFunctionDeclaration_typeParameters() {
// f<E>() {}
String functionName = 'f';
String typeParameterName = 'E';
FunctionExpression expression = AstTestFactory.functionExpression3(
AstTestFactory.typeParameterList([typeParameterName]),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
null, null, functionName, expression);
ElementHolder holder = buildElementsForAst(declaration);
List<FunctionElement> functions = holder.functions;
expect(functions, hasLength(1));
FunctionElement function = functions[0];
expect(function, isNotNull);
expect(function.hasImplicitReturnType, isTrue);
expect(function.name, functionName);
expect(function.isExternal, isFalse);
expect(function.isSynthetic, isFalse);
expect(declaration.declaredElement, same(function));
expect(expression.declaredElement, same(function));
List<TypeParameterElement> typeParameters = function.typeParameters;
expect(typeParameters, hasLength(1));
TypeParameterElement typeParameter = typeParameters[0];
expect(typeParameter, isNotNull);
expect(typeParameter.name, typeParameterName);
}
void test_visitMethodDeclaration_abstract() {
// m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody());
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.parameters, hasLength(0));
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isTrue);
expect(method.isExternal, isFalse);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_duplicateField_synthetic() {
buildElementsForText(r'''
class A {
int f;
int get f => 42;
}
''');
ClassDeclaration classNode = compilationUnit.declarations.single;
// ClassElement
ClassElement classElement = classNode.declaredElement;
expect(classElement.fields, hasLength(2));
expect(classElement.accessors, hasLength(3));
FieldElement notSyntheticFieldElement = classElement.fields
.singleWhere((f) => f.displayName == 'f' && !f.isSynthetic);
FieldElement syntheticFieldElement = classElement.fields
.singleWhere((f) => f.displayName == 'f' && f.isSynthetic);
PropertyAccessorElement syntheticGetterElement = classElement.accessors
.singleWhere(
(a) => a.displayName == 'f' && a.isGetter && a.isSynthetic);
PropertyAccessorElement syntheticSetterElement = classElement.accessors
.singleWhere(
(a) => a.displayName == 'f' && a.isSetter && a.isSynthetic);
PropertyAccessorElement notSyntheticGetterElement = classElement.accessors
.singleWhere(
(a) => a.displayName == 'f' && a.isGetter && !a.isSynthetic);
expect(notSyntheticFieldElement.getter, same(syntheticGetterElement));
expect(notSyntheticFieldElement.setter, same(syntheticSetterElement));
expect(syntheticFieldElement.getter, same(notSyntheticGetterElement));
expect(syntheticFieldElement.setter, isNull);
// class members nodes and their elements
FieldDeclaration fieldDeclNode = classNode.members[0];
VariableDeclaration fieldNode = fieldDeclNode.fields.variables.single;
MethodDeclaration getterNode = classNode.members[1];
expect(fieldNode.declaredElement, notSyntheticFieldElement);
expect(getterNode.declaredElement, notSyntheticGetterElement);
}
void test_visitMethodDeclaration_external() {
// external m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody());
methodDeclaration.externalKeyword =
TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.parameters, hasLength(0));
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isTrue);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_getter() {
// get m() {}
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
Keyword.GET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
methodDeclaration.documentationComment =
AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
methodDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.setter, isNull);
PropertyAccessorElement getter = field.getter;
expect(getter, isNotNull);
assertHasCodeRange(getter, 50, 31);
expect(getter.documentationComment, '/// aaa');
expect(getter.hasImplicitReturnType, isTrue);
expect(getter.isAbstract, isFalse);
expect(getter.isExternal, isFalse);
expect(getter.isGetter, isTrue);
expect(getter.isSynthetic, isFalse);
expect(getter.name, methodName);
expect(getter.variable, field);
expect(getter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_getter_abstract() {
// get m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
Keyword.GET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody());
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.setter, isNull);
PropertyAccessorElement getter = field.getter;
expect(getter, isNotNull);
expect(getter.hasImplicitReturnType, isTrue);
expect(getter.isAbstract, isTrue);
expect(getter.isExternal, isFalse);
expect(getter.isGetter, isTrue);
expect(getter.isSynthetic, isFalse);
expect(getter.name, methodName);
expect(getter.variable, field);
expect(getter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_getter_external() {
// external get m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration(
null,
null,
Keyword.GET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList());
methodDeclaration.externalKeyword =
TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.setter, isNull);
PropertyAccessorElement getter = field.getter;
expect(getter, isNotNull);
expect(getter.hasImplicitReturnType, isTrue);
expect(getter.isAbstract, isFalse);
expect(getter.isExternal, isTrue);
expect(getter.isGetter, isTrue);
expect(getter.isSynthetic, isFalse);
expect(getter.name, methodName);
expect(getter.variable, field);
expect(getter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_minimal() {
// T m() {}
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
AstTestFactory.typeName4('T'),
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
methodDeclaration.documentationComment =
AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
methodDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
assertHasCodeRange(method, 50, 31);
expect(method.documentationComment, '/// aaa');
expect(method.hasImplicitReturnType, isFalse);
expect(method.name, methodName);
expect(method.parameters, hasLength(0));
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isFalse);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_operator() {
// operator +(addend) {}
String methodName = "+";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
null,
Keyword.OPERATOR,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(
[AstTestFactory.simpleFormalParameter3("addend")]),
AstTestFactory.blockFunctionBody2());
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.parameters, hasLength(1));
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isFalse);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_setter() {
// set m() {}
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
Keyword.SET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
methodDeclaration.documentationComment =
AstTestFactory.documentationComment(
[TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
methodDeclaration.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.getter, isNull);
PropertyAccessorElement setter = field.setter;
expect(setter, isNotNull);
assertHasCodeRange(setter, 50, 31);
expect(setter.documentationComment, '/// aaa');
expect(setter.hasImplicitReturnType, isTrue);
expect(setter.isAbstract, isFalse);
expect(setter.isExternal, isFalse);
expect(setter.isSetter, isTrue);
expect(setter.isSynthetic, isFalse);
expect(setter.name, "$methodName=");
expect(setter.displayName, methodName);
expect(setter.variable, field);
expect(setter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_setter_abstract() {
// set m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
Keyword.SET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody());
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.getter, isNull);
PropertyAccessorElement setter = field.setter;
expect(setter, isNotNull);
expect(setter.hasImplicitReturnType, isTrue);
expect(setter.isAbstract, isTrue);
expect(setter.isExternal, isFalse);
expect(setter.isSetter, isTrue);
expect(setter.isSynthetic, isFalse);
expect(setter.name, "$methodName=");
expect(setter.displayName, methodName);
expect(setter.variable, field);
expect(setter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_setter_external() {
// external m();
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration(
null,
null,
Keyword.SET,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList());
methodDeclaration.externalKeyword =
TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<FieldElement> fields = holder.fields;
expect(fields, hasLength(1));
FieldElement field = fields[0];
expect(field, isNotNull);
expect(field.name, methodName);
expect(field.isSynthetic, isTrue);
expect(field.getter, isNull);
PropertyAccessorElement setter = field.setter;
expect(setter, isNotNull);
expect(setter.hasImplicitReturnType, isTrue);
expect(setter.isAbstract, isFalse);
expect(setter.isExternal, isTrue);
expect(setter.isSetter, isTrue);
expect(setter.isSynthetic, isFalse);
expect(setter.name, "$methodName=");
expect(setter.displayName, methodName);
expect(setter.variable, field);
expect(setter.parameters, hasLength(0));
}
void test_visitMethodDeclaration_static() {
// static m() {}
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
Keyword.STATIC,
null,
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.parameters, hasLength(0));
expect(method.typeParameters, hasLength(0));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isFalse);
expect(method.isStatic, isTrue);
expect(method.isSynthetic, isFalse);
}
void test_visitMethodDeclaration_typeParameters() {
// m<E>() {}
String methodName = "m";
MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
null,
null,
null,
null,
AstTestFactory.identifier3(methodName),
AstTestFactory.formalParameterList(),
AstTestFactory.blockFunctionBody2());
methodDeclaration.typeParameters = AstTestFactory.typeParameterList(['E']);
ElementHolder holder = buildElementsForAst(methodDeclaration);
List<MethodElement> methods = holder.methods;
expect(methods, hasLength(1));
MethodElement method = methods[0];
expect(method, isNotNull);
expect(method.hasImplicitReturnType, isTrue);
expect(method.name, methodName);
expect(method.parameters, hasLength(0));
expect(method.typeParameters, hasLength(1));
expect(method.isAbstract, isFalse);
expect(method.isExternal, isFalse);
expect(method.isStatic, isFalse);
expect(method.isSynthetic, isFalse);
}
void test_visitMixinDeclaration() {
isMixinSupportEnabled = true;
var holder = buildElementsForText(r'''
/// doc
mixin M<T, U> on A, B implements C {
double f;
int get g => 0;
set s(int v) {}
int m(int v) => 0;
}
''');
var mixins = holder.mixins;
expect(mixins, hasLength(1));
var type = mixins[0];
expect(type.name, 'M');
expect(type.isMixin, isTrue);
expect(type.documentationComment, '/// doc');
assertHasCodeRange(type, 0, 115);
List<TypeParameterElement> typeParameters = type.typeParameters;
expect(typeParameters, hasLength(2));
expect(typeParameters[0].name, 'T');
expect(typeParameters[1].name, 'U');
var fields = type.fields;
expect(fields, hasLength(3));
expect(fields[0].name, 'f');
expect(fields[1].name, 'g');
expect(fields[2].name, 's');
var accessors = type.accessors;
expect(accessors, hasLength(4));
expect(accessors[0].name, 'f');
expect(accessors[1].name, 'f=');
expect(accessors[2].name, 'g');
expect(accessors[3].name, 's=');
var methods = type.methods;
expect(methods, hasLength(1));
expect(methods[0].name, 'm');
}
void test_visitTypeAlias_minimal() {
String aliasName = "F";
TypeAlias typeAlias = AstTestFactory.typeAlias(null, aliasName, null, null);
ElementHolder holder = buildElementsForAst(typeAlias);
List<FunctionTypeAliasElement> aliases = holder.typeAliases;
expect(aliases, hasLength(1));
FunctionTypeAliasElement alias = aliases[0];
expect(alias, isNotNull);
expect(alias.name, aliasName);
expect(alias.type, isNotNull);
expect(alias.isSynthetic, isFalse);
}
void test_visitTypeAlias_withFormalParameters() {
String aliasName = "F";
String firstParameterName = "x";
String secondParameterName = "y";
TypeAlias typeAlias = AstTestFactory.typeAlias(
null,
aliasName,
AstTestFactory.typeParameterList(),
AstTestFactory.formalParameterList([
AstTestFactory.simpleFormalParameter3(firstParameterName),
AstTestFactory.simpleFormalParameter3(secondParameterName)
]));
typeAlias.beginToken.offset = 50;
typeAlias.endToken.offset = 80;
ElementHolder holder = buildElementsForAst(typeAlias);
List<FunctionTypeAliasElement> aliases = holder.typeAliases;
expect(aliases, hasLength(1));
GenericTypeAliasElementImpl alias = aliases[0];
expect(alias, isNotNull);
assertHasCodeRange(alias, 50, 31);
expect(alias.name, aliasName);
expect(alias.type, isNotNull);
expect(alias.isSynthetic, isFalse);
List<VariableElement> parameters = alias.parameters;
expect(parameters, hasLength(2));
expect(parameters[0].name, firstParameterName);
expect(parameters[1].name, secondParameterName);
List<TypeParameterElement> typeParameters = alias.typeParameters;
expect(typeParameters, isNotNull);
expect(typeParameters, hasLength(0));
}
void test_visitTypeAlias_withTypeParameters() {
String aliasName = "F";
String firstTypeParameterName = "A";
String secondTypeParameterName = "B";
TypeAlias typeAlias = AstTestFactory.typeAlias(
null,
aliasName,
AstTestFactory.typeParameterList(
[firstTypeParameterName, secondTypeParameterName]),
AstTestFactory.formalParameterList());
ElementHolder holder = buildElementsForAst(typeAlias);
List<FunctionTypeAliasElement> aliases = holder.typeAliases;
expect(aliases, hasLength(1));
GenericTypeAliasElementImpl alias = aliases[0];
expect(alias, isNotNull);
expect(alias.name, aliasName);
expect(alias.type, isNotNull);
expect(alias.isSynthetic, isFalse);
List<VariableElement> parameters = alias.parameters;
expect(parameters, isNotNull);
expect(parameters, hasLength(0));
List<TypeParameterElement> typeParameters = alias.typeParameters;
expect(typeParameters, hasLength(2));
expect(typeParameters[0].name, firstTypeParameterName);
expect(typeParameters[1].name, secondTypeParameterName);
}
void test_visitTypeParameter() {
String parameterName = "E";
TypeParameter typeParameter = AstTestFactory.typeParameter(parameterName);
typeParameter.beginToken.offset = 50;
ElementHolder holder = buildElementsForAst(typeParameter);
List<TypeParameterElement> typeParameters = holder.typeParameters;
expect(typeParameters, hasLength(1));
TypeParameterElement typeParameterElement = typeParameters[0];
expect(typeParameterElement, isNotNull);
assertHasCodeRange(typeParameterElement, 50, 1);
expect(typeParameterElement.name, parameterName);
expect(typeParameterElement.bound, isNull);
expect(typeParameterElement.isSynthetic, isFalse);
}
void _assertHasVariableInitializer(VariableElement element) {
expect(element.initializer, isNotNull);
}
}
abstract class _BaseTest extends ParserTestCase {
CompilationUnitElement compilationUnitElement;
CompilationUnit _compilationUnit;
CompilationUnit get compilationUnit => _compilationUnit;
void assertHasCodeRange(Element element, int offset, int length) {
ElementImpl elementImpl = element;
expect(elementImpl.codeOffset, offset);
expect(elementImpl.codeLength, length);
}
/**
* Build elements using [ApiElementBuilder].
*/
ElementHolder buildElementsForAst(AstNode node) {
ElementHolder holder = new ElementHolder();
AstVisitor builder = createElementBuilder(holder);
node.accept(builder);
return holder;
}
/**
* Parse the given [code], and build elements using [ApiElementBuilder].
*/
ElementHolder buildElementsForText(String code) {
ElementHolder holder = new ElementHolder();
AstVisitor builder = createElementBuilder(holder);
_visitAstOfCode(code, builder);
return holder;
}
/**
* Verify that the given [metadata] has exactly one annotation, and that its
* [ElementAnnotationImpl] is unresolved.
*/
void checkAnnotation(NodeList<Annotation> metadata) {
expect(metadata, hasLength(1));
expect(metadata[0], new TypeMatcher<AnnotationImpl>());
AnnotationImpl annotation = metadata[0];
expect(
annotation.elementAnnotation, new TypeMatcher<ElementAnnotationImpl>());
ElementAnnotationImpl elementAnnotation = annotation.elementAnnotation;
expect(elementAnnotation.element, isNull); // Not yet resolved
expect(elementAnnotation.compilationUnit, isNotNull);
expect(elementAnnotation.compilationUnit, compilationUnitElement);
}
/**
* Verify that the given [element] has exactly one annotation, and that its
* [ElementAnnotationImpl] is unresolved.
*/
void checkMetadata(Element element) {
expect(element.metadata, hasLength(1));
expect(element.metadata[0], new TypeMatcher<ElementAnnotationImpl>());
ElementAnnotationImpl elementAnnotation = element.metadata[0];
expect(elementAnnotation.element, isNull); // Not yet resolved
expect(elementAnnotation.compilationUnit, isNotNull);
expect(elementAnnotation.compilationUnit, compilationUnitElement);
}
AstVisitor createElementBuilder(ElementHolder holder);
SimpleIdentifier findIdentifier(String code, String prefix) {
return EngineTestCase.findSimpleIdentifier(compilationUnit, code, prefix);
}
LabelElement findLabel(String code, String prefix) {
return findIdentifier(code, prefix).staticElement;
}
FunctionElement findLocalFunction(String code, String prefix) {
return findIdentifier(code, prefix).staticElement;
}
LocalVariableElement findLocalVariable(String code, String prefix) {
return findIdentifier(code, prefix).staticElement;
}
void setUp() {
compilationUnitElement = new CompilationUnitElementImpl();
}
void _assertVisibleRange(LocalElement element, int offset, int end) {
SourceRange visibleRange = element.visibleRange;
expect(visibleRange.offset, offset);
expect(visibleRange.end, end);
}
/**
* Parse the given [code], and visit it with the given [visitor].
* Fail if any error is logged.
*/
void _visitAstOfCode(String code, AstVisitor visitor) {
TestLogger logger = new TestLogger();
AnalysisEngine.instance.logger = logger;
try {
_compilationUnit = parseCompilationUnit(code);
compilationUnit.accept(visitor);
} finally {
expect(logger.log, hasLength(0));
AnalysisEngine.instance.logger = Logger.NULL;
}
}
}