Skip to content

Commit 4b85176

Browse files
DanTupCommit Queue
authored and
Commit Queue
committed
[analysis_server] Add a new LSP command for "Go to Augmentation"
This adds a custom command similar to `dart/textDocument/super` but for augmentations. This won't show up anywhere on its own, but it will be added to the command palette in Dart-Code based on the server capabilities (and in the future, maybe CodeLens - although that will require some additional work in the server first since it will be the source of CodeLens even if they trigger client-side actions). See #54742 Change-Id: Ib3a3fd08702e14b8bd251991035ef0b8d06ad996 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/358452 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Phil Quitslund <[email protected]>
1 parent bebee99 commit 4b85176

11 files changed

+332
-4
lines changed

pkg/analysis_server/lib/src/lsp/constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ abstract class Commands {
120120

121121
abstract class CustomMethods {
122122
static const augmented = Method('dart/textDocument/augmented');
123+
static const augmentation = Method('dart/textDocument/augmentation');
123124
static const diagnosticServer = Method('dart/diagnosticServer');
124125
static const reanalyze = Method('dart/reanalyze');
125126
static const openUri = Method('dart/openUri');

pkg/analysis_server/lib/src/lsp/handlers/custom/abstract_go_to.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ abstract class AbstractGoToHandler
5353
return success(null);
5454
}
5555

56-
var targetElement = findRelatedElement(element);
56+
var targetElement = findRelatedElement(element)?.nonSynthetic;
5757
var sourcePath = targetElement?.declaration?.source?.fullName;
5858

5959
if (targetElement == null || sourcePath == null) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Element;
6+
import 'package:analysis_server/src/lsp/constants.dart';
7+
import 'package:analysis_server/src/lsp/handlers/custom/abstract_go_to.dart';
8+
import 'package:analyzer/dart/element/element.dart';
9+
import 'package:analyzer/src/utilities/extensions/element.dart';
10+
11+
class AugmentationHandler extends AbstractGoToHandler {
12+
AugmentationHandler(super.server);
13+
14+
@override
15+
Method get handlesMessage => CustomMethods.augmentation;
16+
17+
@override
18+
Element? findRelatedElement(Element element) {
19+
return element.augmentation;
20+
}
21+
}

pkg/analysis_server/lib/src/lsp/handlers/custom/handler_augmented.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class AugmentedHandler extends AbstractGoToHandler {
1414
Method get handlesMessage => CustomMethods.augmented;
1515

1616
@override
17-
Element? findRelatedElement(Element? element) {
17+
Element? findRelatedElement(Element element) {
1818
return switch (element) {
1919
ExecutableElement element => element.augmentationTarget,
2020
InstanceElement element => element.augmentationTarget,

pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class SuperHandler extends AbstractGoToHandler {
1818

1919
@override
2020
Element? findRelatedElement(Element element) {
21-
return _SuperComputer().computeSuper(element)?.nonSynthetic;
21+
return _SuperComputer().computeSuper(element);
2222
}
2323
}
2424

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:async';
77
import 'package:analysis_server/lsp_protocol/protocol.dart';
88
import 'package:analysis_server/src/analysis_server.dart';
99
import 'package:analysis_server/src/lsp/constants.dart';
10+
import 'package:analysis_server/src/lsp/handlers/custom/handler_augmentation.dart';
1011
import 'package:analysis_server/src/lsp/handlers/custom/handler_augmented.dart';
1112
import 'package:analysis_server/src/lsp/handlers/custom/handler_diagnostic_server.dart';
1213
import 'package:analysis_server/src/lsp/handlers/custom/handler_reanalyze.dart';
@@ -112,6 +113,8 @@ class InitializedStateMessageHandler extends ServerStateMessageHandler {
112113
/// Generators for handlers that work with any [AnalysisServer].
113114
static const sharedHandlerGenerators =
114115
<_RequestHandlerGenerator<AnalysisServer>>[
116+
AugmentationHandler.new,
117+
AugmentedHandler.new,
115118
DartTextDocumentContentProviderHandler.new,
116119
DocumentColorHandler.new,
117120
DocumentColorPresentationHandler.new,
@@ -128,7 +131,6 @@ class InitializedStateMessageHandler extends ServerStateMessageHandler {
128131
PrepareTypeHierarchyHandler.new,
129132
SignatureHelpHandler.new,
130133
SuperHandler.new,
131-
AugmentedHandler.new,
132134
TypeDefinitionHandler.new,
133135
TypeHierarchySubtypesHandler.new,
134136
TypeHierarchySupertypesHandler.new,

pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ class ServerCapabilitiesComputer {
213213
// These fields are objects to allow for future expansion.
214214
'super': {},
215215
'augmented': {},
216+
'augmentation': {},
216217
},
217218
},
218219
);
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analysis_server/lsp_protocol/protocol.dart';
6+
import 'package:analyzer/src/test_utilities/test_code_format.dart';
7+
import 'package:test/test.dart';
8+
import 'package:test_reflective_loader/test_reflective_loader.dart';
9+
10+
import '../utils/test_code_extensions.dart';
11+
import 'server_abstract.dart';
12+
13+
void main() {
14+
defineReflectiveSuite(() {
15+
defineReflectiveTests(AugmentationTest);
16+
});
17+
}
18+
19+
@reflectiveTest
20+
class AugmentationTest extends AbstractLspAnalysisServerTest {
21+
Future<void> test_class_body_augmentationToAugmentation() async {
22+
await verifyGoToAugmentation('''
23+
class A {}
24+
25+
augment class A {
26+
^
27+
}
28+
29+
augment class [!A!] {}
30+
''');
31+
}
32+
33+
Future<void> test_class_body_declarationToAugmentation() async {
34+
await verifyGoToAugmentation('''
35+
class A {
36+
^
37+
}
38+
39+
augment class [!A!] {}
40+
''');
41+
}
42+
43+
Future<void> test_class_name_augmentationToAugmentation() async {
44+
await verifyGoToAugmentation('''
45+
class A {}
46+
47+
augment class A^ {}
48+
49+
augment class [!A!] {}
50+
''');
51+
}
52+
53+
Future<void> test_class_name_declarationToAugmentation() async {
54+
await verifyGoToAugmentation('''
55+
class A^ {}
56+
57+
augment class [!A!] {}
58+
''');
59+
}
60+
61+
Future<void> test_constructor_body_augmentationToAugmentation() async {
62+
await verifyGoToAugmentation('''
63+
class A {
64+
A();
65+
}
66+
67+
augment class A {
68+
augment A() {
69+
^
70+
}
71+
}
72+
73+
augment class A {
74+
augment [!A!]();
75+
}
76+
''');
77+
}
78+
79+
Future<void> test_constructor_body_declarationToAugmentation() async {
80+
await verifyGoToAugmentation('''
81+
class A {
82+
A() {
83+
^
84+
}
85+
}
86+
87+
augment class A {
88+
augment [!A!]();
89+
}
90+
''');
91+
}
92+
93+
Future<void> test_constructor_name_augmentationToAugmentation() async {
94+
await verifyGoToAugmentation('''
95+
class A {
96+
A();
97+
}
98+
99+
augment class A {
100+
augment A^();
101+
}
102+
103+
augment class A {
104+
augment [!A!]();
105+
}
106+
''');
107+
}
108+
109+
Future<void> test_constructor_name_declarationToAugmentation() async {
110+
await verifyGoToAugmentation('''
111+
class A {
112+
A^();
113+
}
114+
115+
augment class A {
116+
augment [!A!]();
117+
}
118+
''');
119+
}
120+
121+
Future<void> test_getter_body() async {
122+
await verifyGoToAugmentation('''
123+
class A {
124+
String get foo => '^';
125+
}
126+
127+
augment class A {
128+
augment String get [!foo!] => '';
129+
}
130+
''');
131+
}
132+
133+
Future<void> test_getter_name() async {
134+
await verifyGoToAugmentation('''
135+
class A {
136+
String get fo^o => '';
137+
}
138+
139+
augment class A {
140+
augment String get [!foo!] => '';
141+
}
142+
''');
143+
}
144+
145+
Future<void> test_invalidLocation() async {
146+
await verifyNoAugmentation('''
147+
class A {}
148+
149+
^
150+
''');
151+
}
152+
153+
Future<void> test_method_body_augmentationToAugmentation() async {
154+
await verifyGoToAugmentation('''
155+
class A {
156+
void foo() {}
157+
}
158+
159+
augment class A {
160+
augment void foo() {
161+
^
162+
}
163+
}
164+
165+
augment class A {
166+
augment void [!foo!]() {}
167+
}
168+
''');
169+
}
170+
171+
Future<void> test_method_body_declarationToAugmentation() async {
172+
await verifyGoToAugmentation('''
173+
class A {
174+
void foo() {
175+
^
176+
}
177+
}
178+
179+
augment class A {
180+
augment void [!foo!]() {}
181+
}
182+
''');
183+
}
184+
185+
Future<void> test_method_name_augmentationToAugmentation() async {
186+
await verifyGoToAugmentation('''
187+
class A {
188+
void foo() {}
189+
}
190+
191+
augment class A {
192+
augment void fo^o() {}
193+
}
194+
195+
augment class A {
196+
augment void [!foo!]() {}
197+
}
198+
''');
199+
}
200+
201+
Future<void> test_method_name_declarationToAugmentation() async {
202+
await verifyGoToAugmentation('''
203+
class A {
204+
void foo^() {}
205+
}
206+
207+
augment class A {
208+
augment void [!foo!]() {}
209+
}
210+
''');
211+
}
212+
213+
Future<void> test_setter_body() async {
214+
await verifyGoToAugmentation('''
215+
class A {
216+
set foo(String value) {
217+
^
218+
}
219+
}
220+
221+
augment class A {
222+
augment set [!foo!](String value) {}
223+
}
224+
''');
225+
}
226+
227+
Future<void> test_setter_name() async {
228+
await verifyGoToAugmentation('''
229+
class A {
230+
set fo^o(String value) {}
231+
}
232+
233+
augment class A {
234+
augment set [!foo!](String value) {}
235+
}
236+
''');
237+
}
238+
239+
Future<void> verifyGoToAugmentation(String content) async {
240+
// Build an augmentation library for mainFileUri.
241+
var code = TestCode.parse('''
242+
augment library '$mainFileUri';
243+
244+
$content
245+
''');
246+
247+
await initialize();
248+
await openFile(mainFileUri, "import augment 'main_augmentation.dart';");
249+
await openFile(mainFileAugmentationUri, code.code);
250+
var res = await getAugmentation(
251+
mainFileAugmentationUri,
252+
code.position.position,
253+
);
254+
255+
expect(
256+
res,
257+
equals(Location(uri: mainFileAugmentationUri, range: code.range.range)),
258+
);
259+
}
260+
261+
Future<void> verifyNoAugmentation(String content) async {
262+
// Build an augmentation library for mainFileUri.
263+
var code = TestCode.parse('''
264+
augment library '$mainFileUri';
265+
266+
$content
267+
''');
268+
269+
await initialize();
270+
await openFile(mainFileUri, "import augment 'main_augmentation.dart';");
271+
await openFile(mainFileAugmentationUri, code.code);
272+
var res = await getAugmentation(
273+
mainFileAugmentationUri,
274+
code.position.position,
275+
);
276+
277+
expect(res, isNull);
278+
}
279+
}

pkg/analysis_server/test/lsp/request_helpers_mixin.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,20 @@ mixin LspRequestHelpersMixin {
198198
request, _fromJsonList(TextEdit.fromJson));
199199
}
200200

201+
Future<Location?> getAugmentation(
202+
Uri uri,
203+
Position pos,
204+
) {
205+
final request = makeRequest(
206+
CustomMethods.augmentation,
207+
TextDocumentPositionParams(
208+
textDocument: TextDocumentIdentifier(uri: uri),
209+
position: pos,
210+
),
211+
);
212+
return expectSuccessfulResponseTo(request, Location.fromJson);
213+
}
214+
201215
Future<Location?> getAugmented(
202216
Uri uri,
203217
Position pos,

0 commit comments

Comments
 (0)