| // Copyright (c) 2019, 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/element/element.dart'; |
| import 'package:analyzer/src/dart/ast/element_locator.dart'; |
| import 'package:analyzer_utilities/testing/tree_string_sink.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../../../util/element_printer.dart'; |
| import '../resolution/context_collection_resolution.dart'; |
| import '../resolution/node_text_expectations.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(ElementLocatorTest2); |
| defineReflectiveTests(UpdateNodeTextExpectations); |
| }); |
| } |
| |
| @reflectiveTest |
| class ElementLocatorTest2 extends PubPackageResolutionTest { |
| test_locate_AssignedVariablePattern() async { |
| await resolveTestCode(r''' |
| void f() { |
| int foo; |
| (foo, _) = (0, 1); |
| } |
| '''); |
| var node = findNode.assignedVariablePattern('foo,'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| foo@17 |
| '''); |
| } |
| |
| test_locate_AssignmentExpression() async { |
| await resolveTestCode(r''' |
| int x = 0; |
| void main() { |
| x += 1; |
| } |
| '''); |
| var node = findNode.assignment('+='); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::@class::num::@method::+ |
| '''); |
| } |
| |
| test_locate_BinaryExpression() async { |
| await resolveTestCode('var x = 3 + 4'); |
| var node = findNode.binary('+'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::@class::num::@method::+ |
| '''); |
| } |
| |
| test_locate_CatchClauseParameter() async { |
| await resolveTestCode(r''' |
| void f() { |
| try {} catch (e, s) {} |
| } |
| '''); |
| var node = findNode.catchClauseParameter('e'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| e@27 |
| '''); |
| node = findNode.catchClauseParameter('s'); |
| element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| s@30 |
| '''); |
| } |
| |
| test_locate_ClassDeclaration() async { |
| await resolveTestCode('class A {}'); |
| var node = findNode.classDeclaration('class'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::A |
| '''); |
| } |
| |
| test_locate_ConstructorDeclaration_named() async { |
| await resolveTestCode(r''' |
| class A { |
| A.foo(); |
| } |
| '''); |
| var node = findNode.constructor('A.foo()'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::foo#element |
| '''); |
| } |
| |
| test_locate_ConstructorDeclaration_unnamed() async { |
| await resolveTestCode(r''' |
| class A { |
| A(); |
| } |
| '''); |
| var node = findNode.constructor('A()'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_ConstructorSelector_EnumConstantArguments_EnumConstantDeclaration() async { |
| await resolveTestCode(r''' |
| enum E { |
| v.named(); // 0 |
| const E.named(); |
| } |
| '''); |
| var node = findNode.constructorSelector('named(); // 0'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@enum::E::@constructor::named#element |
| '''); |
| } |
| |
| test_locate_DeclaredVariablePattern() async { |
| await resolveTestCode(r''' |
| void f(Object? x) { |
| if (x case int foo) {} |
| } |
| '''); |
| var node = findNode.declaredVariablePattern('foo'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| foo@37 |
| '''); |
| } |
| |
| test_locate_DotShorthandConstructorInvocation() async { |
| await resolveTestCode(r''' |
| class A {} |
| |
| void main() { |
| A a = .new(); |
| } |
| '''); |
| var node = findNode.singleDotShorthandConstructorInvocation; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_DotShorthandInvocation() async { |
| await resolveTestCode(r''' |
| class A { |
| static A foo() => A(); |
| } |
| |
| void main() { |
| A a = .foo(); |
| } |
| '''); |
| var node = findNode.singleDotShorthandInvocation; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::A::@method::foo |
| '''); |
| } |
| |
| test_locate_DotShorthandPropertyAccess() async { |
| await resolveTestCode(r''' |
| class A { |
| static A foo = A(); |
| } |
| |
| void main() { |
| A a = .foo; |
| } |
| '''); |
| var node = findNode.singleDotShorthandPropertyAccess; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@getter::foo#element |
| '''); |
| } |
| |
| test_locate_EnumConstantDeclaration() async { |
| await resolveTestCode(r''' |
| enum E { |
| one |
| } |
| '''); |
| var node = findNode.enumConstantDeclaration('one'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@enum::E::@field::one#element |
| '''); |
| } |
| |
| test_locate_ExportDirective() async { |
| await resolveTestCode("export 'dart:core';"); |
| var node = findNode.export('export'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core |
| '''); |
| } |
| |
| test_locate_ExtensionDeclaration() async { |
| await resolveTestCode('extension A on int {}'); |
| var node = findNode.singleExtensionDeclaration; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@extension::A |
| '''); |
| } |
| |
| test_locate_ExtensionTypeDeclaration() async { |
| await resolveTestCode('extension type A(int it) {}'); |
| var node = findNode.singleExtensionTypeDeclaration; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@extensionType::A |
| '''); |
| } |
| |
| test_locate_FunctionDeclaration_local() async { |
| await resolveTestCode(r''' |
| void f() { |
| int g() => 3; |
| } |
| '''); |
| var node = findNode.functionDeclaration('g'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| g@17 |
| '''); |
| } |
| |
| test_locate_FunctionDeclaration_topLevel() async { |
| await resolveTestCode('int f() => 3;'); |
| var node = findNode.functionDeclaration('f'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@function::f |
| '''); |
| } |
| |
| test_locate_Identifier_annotationClass_namedConstructor() async { |
| await resolveTestCode(r''' |
| class Class { |
| const Class.name(); |
| } |
| void main(@Class.name() parameter) {} |
| '''); |
| var node = findNode.simple('Class.name() parameter'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::Class |
| '''); |
| } |
| |
| test_locate_Identifier_annotationClass_unnamedConstructor() async { |
| await resolveTestCode(r''' |
| class Class { |
| const Class(); |
| } |
| void main(@Class() parameter) {} |
| '''); |
| var node = findNode.simple('Class() parameter'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::Class::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_Identifier_className() async { |
| await resolveTestCode('class A {}'); |
| var node = findNode.classDeclaration('A'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::A |
| '''); |
| } |
| |
| test_locate_Identifier_constructor_named() async { |
| await resolveTestCode(r''' |
| class A { |
| A.bar(); |
| } |
| '''); |
| var node = findNode.constructor('bar'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::bar#element |
| '''); |
| } |
| |
| test_locate_Identifier_constructor_unnamed() async { |
| await resolveTestCode(r''' |
| class A { |
| A(); |
| } |
| '''); |
| var node = findNode.simple('A()'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_Identifier_fieldName() async { |
| await resolveTestCode(''' |
| class A { |
| var x; |
| } |
| '''); |
| var node = findNode.variableDeclaration('x;'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@field::x#element |
| '''); |
| } |
| |
| test_locate_Identifier_libraryDirective() async { |
| await resolveTestCode('library foo.bar;'); |
| var node = findNode.simple('foo'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary> |
| '''); |
| } |
| |
| test_locate_Identifier_propertyAccess() async { |
| await resolveTestCode(r''' |
| void main() { |
| int x = 'foo'.length; |
| } |
| '''); |
| var node = findNode.simple('length'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::<fragment>::@class::String::@getter::length#element |
| '''); |
| } |
| |
| test_locate_ImportDirective() async { |
| await resolveTestCode("import 'dart:core';"); |
| var node = findNode.import('import'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core |
| '''); |
| } |
| |
| test_locate_IndexExpression() async { |
| await resolveTestCode(r''' |
| void main() { |
| var x = [1, 2]; |
| var y = x[0]; |
| } |
| '''); |
| var node = findNode.index('[0]'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| MethodMember |
| baseElement: dart:core::@class::List::@method::[] |
| substitution: {E: int} |
| '''); |
| } |
| |
| test_locate_InstanceCreationExpression() async { |
| await resolveTestCode(r''' |
| class A {} |
| |
| void main() { |
| new A(); |
| } |
| '''); |
| var node = findNode.instanceCreation('new A()'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_InstanceCreationExpression_type_prefixedIdentifier() async { |
| newFile('$testPackageLibPath/a.dart', r''' |
| class A {} |
| '''); |
| await resolveTestCode(r''' |
| import 'a.dart' as pref; |
| |
| void main() { |
| new pref.A(); |
| } |
| '''); |
| var node = findNode.instanceCreation('A();'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| package:test/a.dart::<fragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_InstanceCreationExpression_type_simpleIdentifier() async { |
| newFile('$testPackageLibPath/a.dart', r''' |
| '''); |
| await resolveTestCode(r''' |
| class A {} |
| |
| void main() { |
| new A(); |
| } |
| '''); |
| var node = findNode.instanceCreation('A();'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@class::A::@constructor::new#element |
| '''); |
| } |
| |
| test_locate_LibraryDirective() async { |
| await resolveTestCode('library foo;'); |
| var node = findNode.library('library'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary> |
| '''); |
| } |
| |
| test_locate_LibraryElement() async { |
| await resolveTestCode('// only comment'); |
| |
| var element = ElementLocator.locate2(result.unit); |
| _assertElement(element, r''' |
| <testLibrary> |
| '''); |
| } |
| |
| test_locate_MethodDeclaration() async { |
| await resolveTestCode(r''' |
| class A { |
| void foo() {} |
| } |
| '''); |
| var node = findNode.methodDeclaration('foo'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::A::@method::foo |
| '''); |
| } |
| |
| test_locate_MethodInvocation_method() async { |
| await resolveTestCode(r''' |
| class A { |
| void foo() {} |
| } |
| |
| void main() { |
| new A().foo(); |
| } |
| '''); |
| var node = findNode.methodInvocation('foo();'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@class::A::@method::foo |
| '''); |
| } |
| |
| test_locate_MethodInvocation_topLevel() async { |
| await resolveTestCode(r''' |
| foo(x) {} |
| |
| void main() { |
| foo(0); |
| } |
| '''); |
| var node = findNode.methodInvocation('foo(0)'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@function::foo |
| '''); |
| } |
| |
| test_locate_MixinDeclaration() async { |
| await resolveTestCode('mixin A {}'); |
| var node = findNode.singleMixinDeclaration; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@mixin::A |
| '''); |
| } |
| |
| test_locate_PatternField() async { |
| await resolveTestCode(r''' |
| void f(Object? x) { |
| if (x case int(isEven: true)) {} |
| } |
| '''); |
| var node = findNode.patternField('isEven:'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::<fragment>::@class::int::@getter::isEven#element |
| '''); |
| } |
| |
| test_locate_PostfixExpression() async { |
| await resolveTestCode('int addOne(int x) => x++;'); |
| var node = findNode.postfix('x++'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::@class::num::@method::+ |
| '''); |
| } |
| |
| test_locate_Prefix() async { |
| await resolveTestCode(r''' |
| import 'dart:math' as math; |
| |
| math.Random? r; |
| '''); |
| var node = findNode.importPrefixReference('math.Random'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@prefix2::math |
| '''); |
| } |
| |
| test_locate_PrefixedIdentifier() async { |
| await resolveTestCode(r''' |
| void f(int a) { |
| a.isEven; |
| } |
| '''); |
| var node = findNode.prefixed('a.isEven'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::<fragment>::@class::int::@getter::isEven#element |
| '''); |
| } |
| |
| test_locate_PrefixExpression() async { |
| await resolveTestCode('int addOne(int x) => ++x;'); |
| var node = findNode.prefix('++x'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| dart:core::@class::num::@method::+ |
| '''); |
| } |
| |
| test_locate_RepresentationDeclaration() async { |
| await resolveTestCode('extension type A(int it) {}'); |
| var node = findNode.singleRepresentationDeclaration; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@extensionType::A::@field::it#element |
| '''); |
| } |
| |
| test_locate_RepresentationDeclaration2() async { |
| await resolveTestCode('extension type A.named(int it) {}'); |
| var node = findNode.singleRepresentationConstructorName; |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibraryFragment>::@extensionType::A::@constructor::named#element |
| '''); |
| } |
| |
| test_locate_StringLiteral_exportUri() async { |
| newFile("$testPackageLibPath/foo.dart", ''); |
| await resolveTestCode("export 'foo.dart';"); |
| var node = findNode.stringLiteral('foo.dart'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| package:test/foo.dart |
| '''); |
| } |
| |
| test_locate_StringLiteral_expression() async { |
| await resolveTestCode("var x = 'abc';"); |
| var node = findNode.stringLiteral('abc'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <null> |
| '''); |
| } |
| |
| test_locate_StringLiteral_importUri() async { |
| newFile("$testPackageLibPath/foo.dart", ''); |
| await resolveTestCode("import 'foo.dart';"); |
| var node = findNode.stringLiteral('foo.dart'); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| package:test/foo.dart |
| '''); |
| } |
| |
| test_locate_VariableDeclaration_Local() async { |
| await resolveTestCode(r''' |
| f() { |
| var x = 42; |
| } |
| '''); |
| var node = findNode.variableDeclaration('x ='); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| x@12 |
| '''); |
| } |
| |
| test_locate_VariableDeclaration_TopLevel() async { |
| await resolveTestCode('var x = 42;'); |
| var node = findNode.variableDeclaration('x ='); |
| var element = ElementLocator.locate2(node); |
| _assertElement(element, r''' |
| <testLibrary>::@topLevelVariable::x |
| '''); |
| } |
| |
| void _assertElement(Element? element, String expected) { |
| var buffer = StringBuffer(); |
| |
| var sink = TreeStringSink(sink: buffer, indent: ''); |
| |
| var elementPrinter = ElementPrinter( |
| sink: sink, |
| configuration: ElementPrinterConfiguration(), |
| ); |
| |
| sink.writeIndent(); |
| elementPrinter.writeElement2(element); |
| |
| var actual = buffer.toString(); |
| if (actual != expected) { |
| print('-------- Actual --------'); |
| print('$actual------------------------'); |
| NodeTextExpectationsCollector.add(actual); |
| } |
| expect(actual, expected); |
| } |
| } |