Skip to content

Commit 5a17591

Browse files
kallentuCommit Queue
authored andcommitted
[analysis_server] Dot shorthands: Hover work and tests.
Added some extra logic for handling dot shorthands in hovers. They should show the same information in the hover as if we had added the type in front of `.`. Added a new line "Declared in:" to show the containing class information. Bug: #59836, #60864 Change-Id: If159d53b7c4443d8a8311125ceef66c441d39d4f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431944 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent bd2a0e6 commit 5a17591

File tree

3 files changed

+226
-5
lines changed

3 files changed

+226
-5
lines changed

pkg/analysis_server/lib/src/computer/computer_hover.dart

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,14 @@ class DartUnitHoverComputer {
112112
String? _elementDisplayString(AstNode node, Element? element) {
113113
var displayString = element?.displayString2(multiline: true);
114114

115-
if (displayString != null &&
116-
node is InstanceCreationExpression &&
117-
node.keyword == null) {
118-
var prefix = node.isConst ? '(const) ' : '(new) ';
119-
displayString = prefix + displayString;
115+
if (displayString != null) {
116+
if (node is InstanceCreationExpression && node.keyword == null) {
117+
var prefix = node.isConst ? '(const) ' : '(new) ';
118+
displayString = prefix + displayString;
119+
} else if (node is DotShorthandConstructorInvocation) {
120+
var prefix = node.isConst ? '(const) ' : '(new) ';
121+
displayString = prefix + displayString;
122+
}
120123
}
121124

122125
return displayString;
@@ -134,6 +137,8 @@ class DartUnitHoverComputer {
134137
offset: node.constructorName.offset,
135138
length: node.constructorName.length,
136139
);
140+
} else if (node is DotShorthandConstructorInvocation) {
141+
return (offset: node.offset, length: node.length);
137142
} else if (node is ConstructorDeclaration) {
138143
var offset = node.returnType.offset;
139144
var end = node.name?.end ?? node.returnType.end;
@@ -237,6 +242,9 @@ class DartUnitHoverComputer {
237242
parent is ConstructorDeclaration &&
238243
parent.name != null) {
239244
return parent;
245+
} else if (node is SimpleIdentifier &&
246+
parent is DotShorthandConstructorInvocation) {
247+
return parent;
240248
}
241249
return node;
242250
}
@@ -258,6 +266,11 @@ class DartUnitHoverComputer {
258266
if (staticType != null && staticType is DynamicType) {
259267
staticType = null;
260268
}
269+
} else if (parent is DotShorthandInvocation && parent.memberName == node) {
270+
staticType = parent.staticInvokeType;
271+
if (staticType != null && staticType is DynamicType) {
272+
staticType = null;
273+
}
261274
} else if (node is PatternFieldName && parent is PatternField) {
262275
staticType = parent.pattern.matchedValueType;
263276
} else if (node is DartPattern) {

pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ class HoverHandler
8787
..writeln();
8888
}
8989

90+
var containingClassDescription = hover.containingClassDescription;
91+
if (containingClassDescription != null &&
92+
containingClassDescription.isNotEmpty) {
93+
content
94+
..writeln('Declared in: `$containingClassDescription`')
95+
..writeln();
96+
}
97+
9098
// Source library.
9199
var containingLibraryName = hover.containingLibraryName;
92100
if (containingLibraryName != null && containingLibraryName.isNotEmpty) {

pkg/analysis_server/test/lsp/hover_test.dart

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,188 @@ class HoverTest extends AbstractLspAnalysisServerTest {
163163
Future<void> test_dartDocPreference_unset() =>
164164
assertDocumentation(null, includesSummary: true, includesFull: true);
165165

166+
Future<void> test_dotShorthand_constructor_named() async {
167+
var content = '''
168+
class A {
169+
A.named();
170+
}
171+
void f() {
172+
A a = [!.nam^ed()!];
173+
}
174+
''';
175+
var expected = '''
176+
```dart
177+
(new) A A.named()
178+
```
179+
Declared in: `A`
180+
181+
*package:test/main.dart*''';
182+
await assertStringContents(content, equals(expected));
183+
}
184+
185+
Future<void> test_dotShorthand_constructor_named_const() async {
186+
var content = '''
187+
class A {
188+
const A.named();
189+
}
190+
void f() {
191+
const A a = [!.nam^ed()!];
192+
}
193+
''';
194+
var expected = '''
195+
```dart
196+
(const) A A.named()
197+
```
198+
Declared in: `A`
199+
200+
*package:test/main.dart*''';
201+
await assertStringContents(content, equals(expected));
202+
}
203+
204+
Future<void> test_dotShorthand_constructor_unnamed() async {
205+
var content = '''
206+
class A {}
207+
void f() {
208+
A a = [!.ne^w()!];
209+
}
210+
''';
211+
var expected = '''
212+
```dart
213+
(new) A A()
214+
```
215+
Declared in: `A`
216+
217+
*package:test/main.dart*''';
218+
await assertStringContents(content, equals(expected));
219+
}
220+
221+
Future<void> test_dotShorthand_constructor_unnamed_const() async {
222+
var content = '''
223+
class A {
224+
const A();
225+
}
226+
void f() {
227+
const A a = [!.ne^w()!];
228+
}
229+
''';
230+
var expected = '''
231+
```dart
232+
(const) A A()
233+
```
234+
Declared in: `A`
235+
236+
*package:test/main.dart*''';
237+
await assertStringContents(content, equals(expected));
238+
}
239+
240+
Future<void> test_dotShorthand_method() async {
241+
var content = '''
242+
class A {
243+
static A method() => A();
244+
}
245+
void f() {
246+
A a = .[!meth^od!]();
247+
}
248+
''';
249+
var expected = '''
250+
```dart
251+
A method()
252+
```
253+
Type: `A Function()`
254+
255+
Declared in: `A`
256+
257+
*package:test/main.dart*''';
258+
await assertStringContents(content, equals(expected));
259+
}
260+
261+
Future<void> test_dotShorthand_method_subclass() async {
262+
var content = '''
263+
class A {
264+
static B method() => B();
265+
}
266+
267+
class B extends A {}
268+
269+
void g(A a) {}
270+
271+
void f() {
272+
g(.[!met^hod!]());
273+
}
274+
''';
275+
var expected = '''
276+
```dart
277+
B method()
278+
```
279+
Type: `B Function()`
280+
281+
Declared in: `A`
282+
283+
*package:test/main.dart*''';
284+
await assertStringContents(content, equals(expected));
285+
}
286+
287+
Future<void> test_dotShorthand_propertyAccess() async {
288+
var content = '''
289+
class A {
290+
static A field = A();
291+
}
292+
void f() {
293+
A a = .[!fie^ld!];
294+
}
295+
''';
296+
var expected = '''
297+
```dart
298+
A get field
299+
```
300+
Type: `A`
301+
302+
Declared in: `A`
303+
304+
*package:test/main.dart*''';
305+
await assertStringContents(content, equals(expected));
306+
}
307+
308+
Future<void> test_dotShorthand_propertyAccess_enum() async {
309+
var content = '''
310+
enum A { one }
311+
void f() {
312+
A a = .[!on^e!];
313+
}
314+
''';
315+
var expected = '''
316+
```dart
317+
A get one
318+
```
319+
Type: `A`
320+
321+
Declared in: `A`
322+
323+
*package:test/main.dart*''';
324+
await assertStringContents(content, equals(expected));
325+
}
326+
327+
Future<void> test_dotShorthand_propertyAccess_extensionType() async {
328+
var content = '''
329+
extension type A(int x) {
330+
static A get getter => A(1);
331+
}
332+
void f() {
333+
A a = .[!gette^r!];
334+
}
335+
''';
336+
var expected = '''
337+
```dart
338+
A get getter
339+
```
340+
Type: `A`
341+
342+
Declared in: `A`
343+
344+
*package:test/main.dart*''';
345+
await assertStringContents(content, equals(expected));
346+
}
347+
166348
Future<void> test_enum_member() async {
167349
var content = '''
168350
enum MyEnum { one }
@@ -177,6 +359,8 @@ MyEnum get one
177359
```
178360
Type: `MyEnum`
179361
362+
Declared in: `MyEnum`
363+
180364
*package:test/main.dart*''';
181365
await assertStringContents(content, equals(expected));
182366
}
@@ -195,6 +379,8 @@ List<MyEnum> get values
195379
```
196380
Type: `List<MyEnum>`
197381
382+
Declared in: `MyEnum`
383+
198384
*package:test/main.dart*''';
199385
await assertStringContents(content, equals(expected));
200386
}
@@ -212,6 +398,8 @@ int get _
212398
```
213399
Type: `int`
214400
401+
Declared in: `A`
402+
215403
*package:test/main.dart*''';
216404
await assertStringContents(content, equals(expected));
217405
}
@@ -460,6 +648,8 @@ int _()
460648
```
461649
Type: `int Function()`
462650
651+
Declared in: `A`
652+
463653
*package:test/main.dart*''';
464654
await assertStringContents(content, equals(expected));
465655
}
@@ -749,6 +939,8 @@ String? get myField
749939
```
750940
Type: `String?`
751941
942+
Declared in: `A`
943+
752944
*package:test/main.dart*
753945
'''.trim();
754946

@@ -771,6 +963,8 @@ String get myGetter
771963
```
772964
Type: `String`
773965
966+
Declared in: `A`
967+
774968
*package:test/main.dart*
775969
'''.trim();
776970

@@ -794,6 +988,8 @@ String? get myGetter
794988
```
795989
Type: `String?`
796990
991+
Declared in: `A`
992+
797993
*package:test/main.dart*
798994
'''.trim();
799995

@@ -818,6 +1014,8 @@ set mySetter(String value)
8181014
```
8191015
Type: `String`
8201016
1017+
Declared in: `A`
1018+
8211019
*package:test/main.dart*
8221020
'''.trim();
8231021

@@ -842,6 +1040,8 @@ set mySetter(String value)
8421040
```
8431041
Type: `String`
8441042
1043+
Declared in: `A`
1044+
8451045
*package:test/main.dart*
8461046
'''.trim();
8471047

0 commit comments

Comments
 (0)