| // 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'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(ApiElementBuilderTest); |
| defineReflectiveTests(ElementBuilderTest); |
| defineReflectiveTests(LocalElementBuilderTest); |
| }); |
| } |
| |
| @reflectiveTest |
| class ApiElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin { |
| @override |
| AstVisitor createElementBuilder(ElementHolder holder) { |
| return new ApiElementBuilder(holder, compilationUnitElement); |
| } |
| |
| void test_api_class_field() { |
| List<FieldElement> fields = buildElementsForText(r''' |
| class C { |
| var a = 42; |
| var b = () { |
| int v = 0; |
| localFunction() {} |
| }; |
| } |
| ''').types[0].fields; |
| expect(fields, hasLength(2)); |
| { |
| FieldElement a = fields[0]; |
| expect(a.displayName, 'a'); |
| expect(a.initializer, isNull); |
| } |
| { |
| FieldElement b = fields[1]; |
| expect(b.displayName, 'b'); |
| expect(b.initializer, isNull); |
| } |
| } |
| |
| void test_api_class_method_blockBody() { |
| MethodElement method = buildElementsForText(r''' |
| class C { |
| void m(int a, {int b: 42}) { |
| int v = 0; |
| localFunction() {} |
| } |
| } |
| ''').types[0].methods[0]; |
| { |
| expect(method.parameters, hasLength(2)); |
| expect(method.parameters[0].displayName, 'a'); |
| expect(method.parameters[0].initializer, isNull); |
| expect(method.parameters[1].displayName, 'b'); |
| expect(method.parameters[1].initializer, isNull); |
| } |
| expect( |
| findDeclaredIdentifiersByName(compilationUnit, 'v') |
| .single |
| .staticElement, |
| isNull); |
| expect( |
| findDeclaredIdentifiersByName(compilationUnit, 'localFunction') |
| .single |
| .staticElement, |
| isNull); |
| } |
| |
| void test_api_topLevelFunction_blockBody() { |
| FunctionElement topLevelFunction = buildElementsForText(r''' |
| void topLevelFunction() { |
| int v = 0; |
| localFunction() {} |
| } |
| ''').functions[0]; |
| expect(topLevelFunction, isNotNull); |
| expect(topLevelFunction.name, 'topLevelFunction'); |
| expect( |
| findDeclaredIdentifiersByName(compilationUnit, 'v') |
| .single |
| .staticElement, |
| isNull); |
| expect( |
| findDeclaredIdentifiersByName(compilationUnit, 'localFunction') |
| .single |
| .staticElement, |
| isNull); |
| } |
| |
| void test_api_topLevelFunction_expressionBody() { |
| FunctionElement topLevelFunction = buildElementsForText(r''' |
| topLevelFunction() => () { |
| int localVar = 0; |
| }; |
| ''').functions[0]; |
| expect(topLevelFunction, isNotNull); |
| expect(topLevelFunction.name, 'topLevelFunction'); |
| expect( |
| findDeclaredIdentifiersByName(compilationUnit, 'localVar') |
| .single |
| .staticElement, |
| isNull); |
| } |
| |
| void test_api_topLevelFunction_parameters() { |
| FunctionElement function = buildElementsForText(r''' |
| void topLevelFunction(int a, int b(double b2), {c: () {int c2; c3() {} }}) { |
| } |
| ''').functions[0]; |
| List<ParameterElement> parameters = function.parameters; |
| expect(parameters, hasLength(3)); |
| { |
| ParameterElement a = parameters[0]; |
| expect(a.displayName, 'a'); |
| expect(a.initializer, isNull); |
| } |
| { |
| ParameterElement b = parameters[1]; |
| expect(b.displayName, 'b'); |
| expect(b.initializer, isNull); |
| var bTypeElement = b.type.element as GenericFunctionTypeElementImpl; |
| expect(bTypeElement.parameters, hasLength(1)); |
| expect(bTypeElement.parameters[0].displayName, 'b2'); |
| } |
| { |
| var c = parameters[2] as DefaultParameterElementImpl; |
| expect(c.displayName, 'c'); |
| expect(c.initializer, isNull); |
| } |
| } |
| |
| void test_api_topLevelVariable() { |
| List<TopLevelVariableElement> variables = buildElementsForText(r''' |
| var A = 42; |
| var B = () { |
| int v = 0; |
| localFunction(int _) {} |
| }; |
| ''').topLevelVariables; |
| expect(variables, hasLength(2)); |
| { |
| TopLevelVariableElement a = variables[0]; |
| expect(a.displayName, 'A'); |
| expect(a.initializer, isNull); |
| } |
| { |
| TopLevelVariableElement b = variables[1]; |
| expect(b.displayName, 'B'); |
| expect(b.initializer, isNull); |
| } |
| } |
| |
| @override |
| void _assertHasVariableInitializer(VariableElement element) { |
| expect(element.initializer, isNull); |
| } |
| } |
| |
| @reflectiveTest |
| class ElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin { |
| /** |
| * Parse the given [code], pass it through [ElementBuilder], and return the |
| * resulting [ElementHolder]. |
| */ |
| ElementHolder buildElementsForText(String code) { |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = new ElementBuilder(holder, compilationUnitElement); |
| _visitAstOfCode(code, builder); |
| return holder; |
| } |
| |
| AstVisitor createElementBuilder(ElementHolder holder) { |
| return new ElementBuilder(holder, compilationUnitElement); |
| } |
| |
| void fail_visitMethodDeclaration_setter_duplicate() { |
| // https://github.com/dart-lang/sdk/issues/25601 |
| String code = r''' |
| class C { |
| set zzz(x) {} |
| set zzz(y) {} |
| } |
| '''; |
| ClassElement classElement = buildElementsForText(code).types[0]; |
| for (PropertyAccessorElement accessor in classElement.accessors) { |
| expect(accessor.variable.setter, same(accessor)); |
| } |
| } |
| |
| @override |
| void setUp() { |
| super.setUp(); |
| compilationUnitElement = new CompilationUnitElementImpl(); |
| } |
| |
| void test_metadata_localVariableDeclaration() { |
| var code = 'f() { @a int x, y; }'; |
| buildElementsForText(code); |
| var x = findLocalVariable(code, 'x, '); |
| var y = findLocalVariable(code, 'x, '); |
| checkMetadata(x); |
| checkMetadata(y); |
| expect(x.metadata, same(y.metadata)); |
| } |
| |
| void test_metadata_visitDeclaredIdentifier() { |
| var code = 'f() { for (@a var x in y) {} }'; |
| buildElementsForText(code); |
| var x = findLocalVariable(code, 'x in'); |
| checkMetadata(x); |
| } |
| |
| void test_visitCatchClause() { |
| var code = 'f() { try {} catch (e, s) {} }'; |
| buildElementsForText(code); |
| var e = findLocalVariable(code, 'e, '); |
| var s = findLocalVariable(code, 's) {}'); |
| |
| expect(e, isNotNull); |
| expect(e.name, 'e'); |
| expect(e.hasImplicitType, isTrue); |
| expect(e.isSynthetic, isFalse); |
| expect(e.isConst, isFalse); |
| expect(e.isFinal, isFalse); |
| expect(e.initializer, isNull); |
| _assertVisibleRange(e, 13, 28); |
| |
| expect(s, isNotNull); |
| expect(s.name, 's'); |
| expect(s.isSynthetic, isFalse); |
| expect(s.isConst, isFalse); |
| expect(s.isFinal, isFalse); |
| expect(s.initializer, isNull); |
| _assertVisibleRange(s, 13, 28); |
| } |
| |
| void test_visitCatchClause_withType() { |
| var code = 'f() { try {} on E catch (e) {} }'; |
| buildElementsForText(code); |
| var e = findLocalVariable(code, 'e) {}'); |
| expect(e, isNotNull); |
| expect(e.name, 'e'); |
| expect(e.hasImplicitType, isFalse); |
| } |
| |
| void test_visitCompilationUnit_codeRange() { |
| TopLevelVariableDeclaration topLevelVariableDeclaration = |
| AstTestFactory.topLevelVariableDeclaration( |
| null, |
| AstTestFactory.typeName4('int'), |
| [AstTestFactory.variableDeclaration('V')]); |
| CompilationUnit unit = astFactory.compilationUnit( |
| topLevelVariableDeclaration.beginToken, |
| null, |
| [], |
| [topLevelVariableDeclaration], |
| topLevelVariableDeclaration.endToken); |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = _makeBuilder(holder); |
| unit.beginToken.offset = 10; |
| unit.endToken.offset = 40; |
| unit.accept(builder); |
| |
| assertHasCodeRange(compilationUnitElement, 0, 41); |
| } |
| |
| void test_visitDeclaredIdentifier_noType() { |
| var code = 'f() { for (var i in []) {} }'; |
| buildElementsForText(code); |
| var variable = findLocalVariable(code, 'i in'); |
| assertHasCodeRange(variable, 11, 5); |
| expect(variable, isNotNull); |
| expect(variable.hasImplicitType, isTrue); |
| expect(variable.isConst, isFalse); |
| expect(variable.hasDeprecated, isFalse); |
| expect(variable.isFinal, isFalse); |
| expect(variable.hasAlwaysThrows, isFalse); |
| expect(variable.isPrivate, isFalse); |
| expect(variable.isPublic, isTrue); |
| expect(variable.isSynthetic, isFalse); |
| expect(variable.name, 'i'); |
| } |
| |
| void test_visitDeclaredIdentifier_type() { |
| var code = 'f() { for (int i in []) {} }'; |
| buildElementsForText(code); |
| var variable = findLocalVariable(code, 'i in'); |
| assertHasCodeRange(variable, 11, 5); |
| expect(variable.hasImplicitType, isFalse); |
| expect(variable.isConst, isFalse); |
| expect(variable.hasDeprecated, isFalse); |
| expect(variable.isFinal, isFalse); |
| expect(variable.hasOverride, isFalse); |
| expect(variable.isPrivate, isFalse); |
| expect(variable.isPublic, isTrue); |
| expect(variable.isSynthetic, isFalse); |
| expect(variable.name, 'i'); |
| } |
| |
| void test_visitDefaultFormalParameter_noType() { |
| // p = 0 |
| String parameterName = 'p'; |
| DefaultFormalParameter formalParameter = |
| AstTestFactory.positionalFormalParameter( |
| AstTestFactory.simpleFormalParameter3(parameterName), |
| AstTestFactory.integer(0)); |
| formalParameter.beginToken.offset = 50; |
| formalParameter.endToken.offset = 80; |
| |
| ElementHolder holder = buildElementsForAst(formalParameter); |
| List<ParameterElement> parameters = holder.parameters; |
| expect(parameters, hasLength(1)); |
| ParameterElement parameter = parameters[0]; |
| assertHasCodeRange(parameter, 50, 31); |
| expect(parameter.hasImplicitType, isTrue); |
| expect(parameter.initializer, isNotNull); |
| expect(parameter.initializer.type, isNotNull); |
| expect(parameter.initializer.hasImplicitReturnType, isTrue); |
| expect(parameter.isConst, isFalse); |
| expect(parameter.hasDeprecated, isFalse); |
| expect(parameter.isFinal, isFalse); |
| expect(parameter.isInitializingFormal, isFalse); |
| expect(parameter.hasOverride, isFalse); |
| expect(parameter.isPrivate, isFalse); |
| expect(parameter.isPublic, isTrue); |
| expect(parameter.isSynthetic, isFalse); |
| expect(parameter.name, parameterName); |
| } |
| |
| void test_visitDefaultFormalParameter_type() { |
| // E p = 0 |
| String parameterName = 'p'; |
| DefaultFormalParameter formalParameter = |
| AstTestFactory.namedFormalParameter( |
| AstTestFactory.simpleFormalParameter4( |
| AstTestFactory.typeName4('E'), parameterName), |
| AstTestFactory.integer(0)); |
| |
| ElementHolder holder = buildElementsForAst(formalParameter); |
| List<ParameterElement> parameters = holder.parameters; |
| expect(parameters, hasLength(1)); |
| ParameterElement parameter = parameters[0]; |
| expect(parameter.hasImplicitType, isFalse); |
| expect(parameter.initializer, isNotNull); |
| expect(parameter.initializer.type, isNotNull); |
| expect(parameter.initializer.hasImplicitReturnType, isTrue); |
| expect(parameter.isConst, isFalse); |
| expect(parameter.hasDeprecated, isFalse); |
| expect(parameter.isFinal, isFalse); |
| expect(parameter.isInitializingFormal, isFalse); |
| expect(parameter.hasOverride, isFalse); |
| expect(parameter.isPrivate, isFalse); |
| expect(parameter.isPublic, isTrue); |
| expect(parameter.isSynthetic, isFalse); |
| expect(parameter.name, parameterName); |
| } |
| |
| void test_visitFunctionExpression() { |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = _makeBuilder(holder); |
| FunctionExpression expression = AstTestFactory.functionExpression2( |
| AstTestFactory.formalParameterList(), |
| AstTestFactory.blockFunctionBody2()); |
| expression.accept(builder); |
| List<FunctionElement> functions = holder.functions; |
| expect(functions, hasLength(1)); |
| FunctionElement function = functions[0]; |
| expect(function, isNotNull); |
| expect(expression.declaredElement, same(function)); |
| expect(function.hasImplicitReturnType, isTrue); |
| expect(function.isSynthetic, isFalse); |
| expect(function.typeParameters, hasLength(0)); |
| } |
| |
| void test_visitFunctionExpression_inBlockBody() { |
| buildElementsForText('f() { return () => 42; }'); |
| FunctionDeclaration f = compilationUnit.declarations[0]; |
| BlockFunctionBody fBody = f.functionExpression.body; |
| ReturnStatement returnStatement = fBody.block.statements[0]; |
| FunctionExpression closure = returnStatement.expression; |
| FunctionElement function = closure.declaredElement; |
| expect(function, isNotNull); |
| expect(function.hasImplicitReturnType, isTrue); |
| expect(function.isSynthetic, isFalse); |
| expect(function.typeParameters, hasLength(0)); |
| } |
| |
| void test_visitFunctionExpression_inExpressionBody() { |
| buildElementsForText('f() => () => 42;'); |
| FunctionDeclaration f = compilationUnit.declarations[0]; |
| ExpressionFunctionBody fBody = f.functionExpression.body; |
| FunctionExpression closure = fBody.expression; |
| FunctionElement function = closure.declaredElement; |
| expect(function, isNotNull); |
| expect(function.hasImplicitReturnType, isTrue); |
| expect(function.isSynthetic, isFalse); |
| expect(function.typeParameters, hasLength(0)); |
| } |
| |
| void test_visitFunctionTypeAlias() { |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = _makeBuilder(holder); |
| String aliasName = "F"; |
| String parameterName = "E"; |
| FunctionTypeAlias aliasNode = AstTestFactory.typeAlias(null, aliasName, |
| AstTestFactory.typeParameterList([parameterName]), null); |
| aliasNode.documentationComment = AstTestFactory.documentationComment( |
| [TokenFactory.tokenFromString('/// aaa')..offset = 50], []); |
| aliasNode.endToken.offset = 80; |
| aliasNode.accept(builder); |
| |
| List<FunctionTypeAliasElement> aliases = holder.typeAliases; |
| expect(aliases, hasLength(1)); |
| FunctionTypeAliasElement alias = aliases[0]; |
| expect(alias, isNotNull); |
| assertHasCodeRange(alias, 50, 31); |
| expect(alias.documentationComment, '/// aaa'); |
| expect(alias.name, aliasName); |
| expect(alias.parameters, hasLength(0)); |
| List<TypeParameterElement> typeParameters = alias.typeParameters; |
| expect(typeParameters, hasLength(1)); |
| TypeParameterElement typeParameter = typeParameters[0]; |
| expect(typeParameter, isNotNull); |
| expect(typeParameter.name, parameterName); |
| } |
| |
| void test_visitFunctionTypedFormalParameter() { |
| ElementHolder holder = new ElementHolder(); |
| ElementBuilder builder = _makeBuilder(holder); |
| String parameterName = "p"; |
| FunctionTypedFormalParameter formalParameter = |
| AstTestFactory.functionTypedFormalParameter(null, parameterName); |
| _useParameterInMethod(formalParameter, 100, 110); |
| formalParameter.accept(builder); |
| List<ParameterElement> parameters = holder.parameters; |
| expect(parameters, hasLength(1)); |
| ParameterElement parameter = parameters[0]; |
| expect(parameter, isNotNull); |
| expect(parameter.name, parameterName); |
| expect(parameter.initializer, isNull); |
| expect(parameter.isConst, isFalse); |
| expect(parameter.isFinal, isFalse); |
| expect(parameter.isSynthetic, isFalse); |
| expect(parameter.isNotOptional, 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.isNotOptional, 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.isNotOptional, 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.isNotOptional, 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.isNotOptional, 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.isNotOptional, 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.isNotOptional, 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.forEachStatement(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.forStatement2( |
| 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, new TypeMatcher<FunctionElement>()); |
| 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.isNotOptional, 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.isNotOptional, 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; |
| } |
| } |
| } |