[analyzer] Dot shorthands: Update indexing. Adds implementation for dot shorthand invocations, property accesses and constructors in indexing and added search tests. Unit tests passing for index and search. Bug: https://github.com/dart-lang/sdk/issues/59835 Change-Id: I2ee3ddbabb7f8ee0ead6538906a9a55f54bf20a2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430563 Commit-Queue: Kallen Tu <kallentu@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart index 7a22d00..dd085c2 100644 --- a/pkg/analyzer/lib/src/dart/analysis/index.dart +++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -861,6 +861,41 @@ } @override + void visitDotShorthandConstructorInvocation( + DotShorthandConstructorInvocation node, + ) { + var element = _getActualConstructorElement(node.element?.baseElement); + recordRelation( + element, + IndexRelationKind.IS_INVOKED_BY, + node.constructorName, + true, + ); + } + + @override + void visitDotShorthandInvocation(DotShorthandInvocation node) { + var name = node.memberName; + var element = name.element; + recordRelation(element, IndexRelationKind.IS_INVOKED_BY, name, true); + node.typeArguments?.accept(this); + node.argumentList.accept(this); + } + + @override + void visitDotShorthandPropertyAccess(DotShorthandPropertyAccess node) { + IndexRelationKind kind; + var element = node.propertyName.element; + if (element is ConstructorElementMixin2) { + element = _getActualConstructorElement(element); + kind = IndexRelationKind.IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF; + } else { + kind = IndexRelationKind.IS_REFERENCED_BY; + } + recordRelation(element, kind, node.propertyName, true); + } + + @override void visitEnumConstantDeclaration(EnumConstantDeclaration node) { var constructorElement = node.constructorElement2; if (constructorElement != null) {
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart index 29d9081..b882549 100644 --- a/pkg/analyzer/test/src/dart/analysis/index_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -1280,6 +1280,21 @@ // No additional validation, but it should not fail with stack overflow. } + test_isReferencedBy_ConstructorElement_dotShorthand() async { + await _indexTestUnit(''' +class A {} +void f() { + A a = .new(); // 1 + A tearOff = .new; // 2, is also a compile-time error +} +'''); + var element = findElement2.unnamedConstructor('A'); + assertElementIndexText(element, r''' +31 3:10 |new| IS_INVOKED_BY qualified +58 4:16 |new| IS_REFERENCED_BY_CONSTRUCTOR_TEAR_OFF qualified +'''); + } + test_isReferencedBy_ConstructorElement_enum_named() async { await _indexTestUnit(''' /// [new E.foo] 1 @@ -1706,6 +1721,21 @@ '''); } + test_isReferencedBy_FieldElement_dotShorthand() async { + await _indexTestUnit(''' +class A { + static A field = A(); +} +void f() { + A a = .field; // 1 +} +'''); + var element = findElement2.field('field').getter2!; + assertElementIndexText(element, r''' +56 5:10 |field| IS_REFERENCED_BY qualified +'''); + } + test_isReferencedBy_FieldElement_enum() async { await _indexTestUnit(''' enum E { @@ -1953,6 +1983,21 @@ '''); } + test_isReferencedBy_MethodElement_dotShorthand() async { + await _indexTestUnit(''' +class A { + static A method() => A(); +} +void f() { + A a = .method(); // 1 +} +'''); + var element = findElement2.method('method'); + assertElementIndexText(element, r''' +60 5:10 |method| IS_INVOKED_BY qualified +'''); + } + test_isReferencedBy_MethodElement_enum() async { await _indexTestUnit(''' enum E {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart index 80a529c..98e5ee5 100644 --- a/pkg/analyzer/test/src/dart/analysis/search_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -1304,6 +1304,22 @@ '''); } + test_searchReferences_ConstructorElement_dotShorthand() async { + await resolveTestCode(''' +class A {} +void main() { + A a = .new(); // 1 + A tearOff = .new; // 2, is also a compile-time error +} +'''); + var element = findElement2.unnamedConstructor('A'); + await assertElementReferencesText(element, r''' +<testLibraryFragment>::@function::main + 34 3:10 |new| INVOCATION qualified + 61 4:16 |new| REFERENCE_BY_CONSTRUCTOR_TEAR_OFF qualified +'''); + } + test_searchReferences_ConstructorElement_enum_named() async { await resolveTestCode(''' /// [new E.named] 1 @@ -1496,6 +1512,22 @@ '''); } + test_searchReferences_FieldElement_dotShorthand() async { + await resolveTestCode(''' +class A { + static A field = A(); +} +void main() { + A a = .field; // 1 +} +'''); + var element = findElement2.field('field'); + await assertElementReferencesText(element, r''' +<testLibraryFragment>::@function::main + 59 5:10 |field| READ qualified +'''); + } + test_searchReferences_FieldElement_enum() async { await resolveTestCode(''' enum E { @@ -1938,6 +1970,24 @@ '''); } + test_searchReferences_MethodElement_dotShorthand() async { + await resolveTestCode(''' +class A { + static A method() => A(); +} +void main() { + A a = .method(); // 1 + A aa = .method; // 2, is also a compile-time error +} +'''); + var element = findElement2.method('method'); + await assertElementReferencesText(element, r''' +<testLibraryFragment>::@function::main + 63 5:10 |method| INVOCATION qualified + 88 6:11 |method| REFERENCE qualified +'''); + } + test_searchReferences_MethodElement_enum() async { await resolveTestCode(''' enum E {