Skip to content

Commit 3a08da0

Browse files
srawlinsCommit Queue
authored and
Commit Queue
committed
analyzer: Support comment references of members of aliased type
Work towards #56109 (specifically support for #56109 (comment)). Currently, instance (and static) members of a type can be referenced in a comment reference. This change adds support to referencing instance (and static) members of a type via a type alias. Change-Id: Ic789a0185cb8c56236346ef3ae658481fbd4cd70 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429226 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 9ff77fd commit 3a08da0

File tree

3 files changed

+185
-7
lines changed

3 files changed

+185
-7
lines changed

pkg/analyzer/lib/src/dart/resolver/comment_reference_resolver.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ class CommentReferenceResolver {
6565

6666
var name = expression.identifier;
6767

68+
if (prefixElement is TypeAliasElement) {
69+
// When resolving `name`, use the aliased element.
70+
prefixElement = prefixElement.aliasedType.element3;
71+
}
72+
6873
if (prefixElement is PrefixElement) {
6974
var prefixScope = prefixElement.scope;
7075
var lookupResult = prefixScope.lookup(name.name);
@@ -132,6 +137,12 @@ class CommentReferenceResolver {
132137
name.element = element;
133138

134139
var propertyName = expression.propertyName;
140+
141+
if (element is TypeAliasElement) {
142+
// When resolving `propertyName`, use the aliased element.
143+
element = element.aliasedType.element3;
144+
}
145+
135146
if (element is InterfaceElement) {
136147
propertyName.element =
137148
element.getMethod(propertyName.name) ??

pkg/analyzer/test/src/dart/resolution/comment_test.dart

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,34 @@ CommentReference
102102
''');
103103
}
104104

105+
test_class_instanceGetter_onTypedef() async {
106+
await assertNoErrorsInCode('''
107+
class A {
108+
int get foo => 0;
109+
}
110+
typedef B = A;
111+
112+
/// [B.foo]
113+
void f() {}
114+
''');
115+
116+
assertResolvedNodeText(findNode.commentReference('B.foo]'), r'''
117+
CommentReference
118+
expression: PrefixedIdentifier
119+
prefix: SimpleIdentifier
120+
token: B
121+
element: <testLibrary>::@typeAlias::B
122+
staticType: null
123+
period: .
124+
identifier: SimpleIdentifier
125+
token: foo
126+
element: <testLibraryFragment>::@class::A::@getter::foo#element
127+
staticType: null
128+
element: <testLibraryFragment>::@class::A::@getter::foo#element
129+
staticType: null
130+
''');
131+
}
132+
105133
test_class_instanceMethod() async {
106134
await assertNoErrorsInCode('''
107135
class A {
@@ -221,6 +249,35 @@ CommentReference
221249
''');
222250
}
223251

252+
test_class_staticGetter_onTypedef() async {
253+
await assertNoErrorsInCode('''
254+
class A {
255+
static int get foo => 0;
256+
}
257+
258+
typedef B = A;
259+
260+
/// [B.foo]
261+
void f() {}
262+
''');
263+
264+
assertResolvedNodeText(findNode.commentReference('B.foo]'), r'''
265+
CommentReference
266+
expression: PrefixedIdentifier
267+
prefix: SimpleIdentifier
268+
token: B
269+
element: <testLibrary>::@typeAlias::B
270+
staticType: null
271+
period: .
272+
identifier: SimpleIdentifier
273+
token: foo
274+
element: <testLibraryFragment>::@class::A::@getter::foo#element
275+
staticType: null
276+
element: <testLibraryFragment>::@class::A::@getter::foo#element
277+
staticType: null
278+
''');
279+
}
280+
224281
test_class_staticMethod() async {
225282
await assertNoErrorsInCode('''
226283
class A {
@@ -949,6 +1006,42 @@ CommentReference
9491006
''');
9501007
}
9511008

1009+
test_class_instanceGetter_onTypedef() async {
1010+
await assertNoErrorsInCode('''
1011+
import '' as self;
1012+
class A {
1013+
int get foo => 0;
1014+
}
1015+
typedef B = A;
1016+
1017+
/// [self.B.foo]
1018+
void f() {}
1019+
''');
1020+
1021+
assertResolvedNodeText(findNode.commentReference('B.foo]'), r'''
1022+
CommentReference
1023+
expression: PropertyAccess
1024+
target: PrefixedIdentifier
1025+
prefix: SimpleIdentifier
1026+
token: self
1027+
element: <testLibraryFragment>::@prefix2::self
1028+
staticType: null
1029+
period: .
1030+
identifier: SimpleIdentifier
1031+
token: B
1032+
element: <testLibrary>::@typeAlias::B
1033+
staticType: null
1034+
element: <testLibrary>::@typeAlias::B
1035+
staticType: null
1036+
operator: .
1037+
propertyName: SimpleIdentifier
1038+
token: foo
1039+
element: <testLibraryFragment>::@class::A::@getter::foo#element
1040+
staticType: null
1041+
staticType: null
1042+
''');
1043+
}
1044+
9521045
test_class_instanceMethod() async {
9531046
await assertNoErrorsInCode('''
9541047
import '' as self;
@@ -1054,6 +1147,42 @@ CommentReference
10541147
''');
10551148
}
10561149

1150+
test_class_staticGetter_onTypedef() async {
1151+
await assertNoErrorsInCode('''
1152+
import '' as self;
1153+
class A {
1154+
static int get foo => 0;
1155+
}
1156+
typedef B = A;
1157+
1158+
/// [self.B.foo]
1159+
void f() {}
1160+
''');
1161+
1162+
assertResolvedNodeText(findNode.commentReference('B.foo]'), r'''
1163+
CommentReference
1164+
expression: PropertyAccess
1165+
target: PrefixedIdentifier
1166+
prefix: SimpleIdentifier
1167+
token: self
1168+
element: <testLibraryFragment>::@prefix2::self
1169+
staticType: null
1170+
period: .
1171+
identifier: SimpleIdentifier
1172+
token: B
1173+
element: <testLibrary>::@typeAlias::B
1174+
staticType: null
1175+
element: <testLibrary>::@typeAlias::B
1176+
staticType: null
1177+
operator: .
1178+
propertyName: SimpleIdentifier
1179+
token: foo
1180+
element: <testLibraryFragment>::@class::A::@getter::foo#element
1181+
staticType: null
1182+
staticType: null
1183+
''');
1184+
}
1185+
10571186
test_class_staticMethod() async {
10581187
await assertNoErrorsInCode('''
10591188
import '' as self;

pkg/linter/test/rules/comment_references_test.dart

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,6 @@ class CommentReferencesTest extends LintRuleTest {
1717
@override
1818
String get lintRule => LintNames.comment_references;
1919

20-
test_constructorTearoff() async {
21-
await assertNoDiagnostics(r'''
22-
/// Text [Future.delayed].
23-
class C {}
24-
''');
25-
}
26-
2720
test_false() async {
2821
await assertDiagnostics(
2922
r'''
@@ -184,6 +177,13 @@ class B extends A {
184177
''');
185178
}
186179

180+
test_prefixedIdentifier_constructorTearoff() async {
181+
await assertNoDiagnostics(r'''
182+
/// Text [Future.delayed].
183+
class C {}
184+
''');
185+
}
186+
187187
test_prefixedIdentifier_importPrefix() async {
188188
await assertNoDiagnostics(r'''
189189
import 'dart:async' as async;
@@ -192,6 +192,22 @@ class C {}
192192
''');
193193
}
194194

195+
test_prefixedIdentifier_instanceMember() async {
196+
await assertNoDiagnostics(r'''
197+
/// Text [int.isEven].
198+
class C {}
199+
''');
200+
}
201+
202+
test_prefixedIdentifier_instanceMember_onTypedef() async {
203+
await assertNoDiagnostics(r'''
204+
typedef int2 = int;
205+
206+
/// Text [int2.isEven].
207+
class C {}
208+
''');
209+
}
210+
195211
test_prefixedIdentifier_staticMethod() async {
196212
await assertNoDiagnostics(r'''
197213
/// Text [Future.wait].
@@ -214,6 +230,19 @@ class C {}
214230
''');
215231
}
216232

233+
test_propertyAccess_onTypedef() async {
234+
await assertNoDiagnostics(r'''
235+
import '' as self;
236+
class A {
237+
int get x => 7;
238+
}
239+
typedef B = A;
240+
241+
/// Text [self.B.x].
242+
class C {}
243+
''');
244+
}
245+
217246
test_this() async {
218247
await assertDiagnostics(
219248
r'''
@@ -234,6 +263,15 @@ class C {}
234263
);
235264
}
236265

266+
test_typeAlias() async {
267+
await assertNoDiagnostics(r'''
268+
/// Text [Td].
269+
class C {}
270+
271+
typedef Td = C;
272+
''');
273+
}
274+
237275
test_typeName() async {
238276
await assertNoDiagnostics(r'''
239277
/// Text [Future].

0 commit comments

Comments
 (0)