[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>
This commit is contained in:
Kallen Tu
2025-05-27 10:06:22 -07:00
committed by Commit Queue
parent 15f49c9da0
commit 03515b472e
3 changed files with 130 additions and 0 deletions
@@ -860,6 +860,41 @@ class _IndexContributor extends GeneralizingAstVisitor {
node.type.accept(this);
}
@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;
@@ -1280,6 +1280,21 @@ void f() {
// 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 @@ class A {
''');
}
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 @@ class A {
''');
}
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 {
@@ -1304,6 +1304,22 @@ void f() {
''');
}
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 @@ class A {
''');
}
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 @@ class A {
''');
}
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 {