37f915543f
Change-Id: I8d709fcb9be1b3a89e617a0c7b35f47813787f06 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99966 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2706 lines
98 KiB
Dart
2706 lines
98 KiB
Dart
// 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.compilationUnit2(
|
|
beginToken: topLevelVariableDeclaration.beginToken,
|
|
declarations: [topLevelVariableDeclaration],
|
|
endToken: topLevelVariableDeclaration.endToken,
|
|
featureSet: null);
|
|
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;
|
|
}
|
|
}
|
|
}
|