Skip to content

Commit 2b8c2f6

Browse files
DanTupCommit Queue
authored and
Commit Queue
committed
[analysis_server] Add a new LSP command for "Go to Augmented"
This adds a custom command similar to `dart/textDocument/super` but for augmentation targets ("augmented"). 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: I11ca115c61ade40bf51478f58b39b7caedac19c9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/358451 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent 53957bf commit 2b8c2f6

11 files changed

+434
-69
lines changed

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

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

121121
abstract class CustomMethods {
122+
static const augmented = Method('dart/textDocument/augmented');
122123
static const diagnosticServer = Method('dart/diagnosticServer');
123124
static const reanalyze = Method('dart/reanalyze');
124125
static const openUri = Method('dart/openUri');
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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/handlers/handlers.dart';
7+
import 'package:analysis_server/src/lsp/mapping.dart';
8+
import 'package:analyzer/dart/element/element.dart';
9+
import 'package:analyzer/src/dart/ast/utilities.dart';
10+
import 'package:meta/meta.dart';
11+
12+
/// A common base for commands that accept a position in a document and return
13+
/// a location to navigate to a particular kind of related element, such as
14+
/// Super, Augmentation Target or Augmentation.
15+
abstract class AbstractGoToHandler
16+
extends SharedMessageHandler<TextDocumentPositionParams, Location?> {
17+
AbstractGoToHandler(super.server);
18+
19+
@override
20+
LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
21+
TextDocumentPositionParams.jsonHandler;
22+
23+
@protected
24+
Element? findRelatedElement(Element element);
25+
26+
@override
27+
Future<ErrorOr<Location?>> handle(TextDocumentPositionParams params,
28+
MessageInfo message, CancellationToken token) async {
29+
if (!isDartDocument(params.textDocument)) {
30+
return success(null);
31+
}
32+
33+
var pos = params.position;
34+
var path = pathOfDoc(params.textDocument);
35+
var unit = await path.mapResult(requireResolvedUnit);
36+
var offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
37+
38+
return offset.mapResult((offset) async {
39+
var node = NodeLocator(offset).searchWithin(unit.result.unit);
40+
if (node == null) {
41+
return success(null);
42+
}
43+
44+
// Walk up the nodes until we find one that has an element so we can
45+
// find target even if the cursor location was inside a method or on a
46+
// return type.
47+
var element = server.getElementOfNode(node);
48+
while (element == null && node?.parent != null) {
49+
node = node?.parent;
50+
element = server.getElementOfNode(node);
51+
}
52+
if (element == null) {
53+
return success(null);
54+
}
55+
56+
var targetElement = findRelatedElement(element);
57+
var sourcePath = targetElement?.declaration?.source?.fullName;
58+
59+
if (targetElement == null || sourcePath == null) {
60+
return success(null);
61+
}
62+
63+
var locationLineInfo = server.getLineInfo(sourcePath);
64+
if (locationLineInfo == null) {
65+
return success(null);
66+
}
67+
68+
return success(Location(
69+
uri: uriConverter.toClientUri(sourcePath),
70+
range: toRange(
71+
locationLineInfo,
72+
targetElement.nameOffset,
73+
targetElement.nameLength,
74+
),
75+
));
76+
});
77+
}
78+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
10+
class AugmentedHandler extends AbstractGoToHandler {
11+
AugmentedHandler(super.server);
12+
13+
@override
14+
Method get handlesMessage => CustomMethods.augmented;
15+
16+
@override
17+
Element? findRelatedElement(Element? element) {
18+
return switch (element) {
19+
ExecutableElement element => element.augmentationTarget,
20+
InstanceElement element => element.augmentationTarget,
21+
PropertyInducingElement element => element.augmentationTarget,
22+
_ => null,
23+
};
24+
}
25+
}

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

Lines changed: 6 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,78 +2,23 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
import 'package:analysis_server/lsp_protocol/protocol.dart'
6-
hide Element, TypeHierarchyItem;
5+
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Element;
76
import 'package:analysis_server/src/lsp/constants.dart';
8-
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
9-
import 'package:analysis_server/src/lsp/mapping.dart';
7+
import 'package:analysis_server/src/lsp/handlers/custom/abstract_go_to.dart';
108
import 'package:analyzer/dart/element/element.dart';
119
import 'package:analyzer/src/dart/analysis/session.dart';
12-
import 'package:analyzer/src/dart/ast/utilities.dart';
1310
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
1411
import 'package:analyzer/src/utilities/extensions/element.dart';
1512

16-
class SuperHandler
17-
extends LspMessageHandler<TextDocumentPositionParams, Location?> {
13+
class SuperHandler extends AbstractGoToHandler {
1814
SuperHandler(super.server);
19-
@override
20-
Method get handlesMessage => CustomMethods.super_;
2115

2216
@override
23-
LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
24-
TextDocumentPositionParams.jsonHandler;
17+
Method get handlesMessage => CustomMethods.super_;
2518

2619
@override
27-
Future<ErrorOr<Location?>> handle(TextDocumentPositionParams params,
28-
MessageInfo message, CancellationToken token) async {
29-
if (!isDartDocument(params.textDocument)) {
30-
return success(null);
31-
}
32-
33-
var pos = params.position;
34-
var path = pathOfDoc(params.textDocument);
35-
var unit = await path.mapResult(requireResolvedUnit);
36-
var offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
37-
38-
return offset.mapResult((offset) async {
39-
var node = NodeLocator(offset).searchWithin(unit.result.unit);
40-
if (node == null) {
41-
return success(null);
42-
}
43-
44-
// Walk up the nodes until we find one that has an element so we can support
45-
// finding supers even if the cursor location was inside a method or on its
46-
// return type.
47-
var element = server.getElementOfNode(node);
48-
while (element == null && node?.parent != null) {
49-
node = node?.parent;
50-
element = server.getElementOfNode(node);
51-
}
52-
if (element == null) {
53-
return success(null);
54-
}
55-
56-
var superElement = _SuperComputer().computeSuper(element)?.nonSynthetic;
57-
var sourcePath = superElement?.declaration?.source?.fullName;
58-
59-
if (superElement == null || sourcePath == null) {
60-
return success(null);
61-
}
62-
63-
var locationLineInfo = server.getLineInfo(sourcePath);
64-
if (locationLineInfo == null) {
65-
return success(null);
66-
}
67-
68-
return success(Location(
69-
uri: uriConverter.toClientUri(sourcePath),
70-
range: toRange(
71-
locationLineInfo,
72-
superElement.nameOffset,
73-
superElement.nameLength,
74-
),
75-
));
76-
});
20+
Element? findRelatedElement(Element element) {
21+
return _SuperComputer().computeSuper(element)?.nonSynthetic;
7722
}
7823
}
7924

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_augmented.dart';
1011
import 'package:analysis_server/src/lsp/handlers/custom/handler_diagnostic_server.dart';
1112
import 'package:analysis_server/src/lsp/handlers/custom/handler_reanalyze.dart';
1213
import 'package:analysis_server/src/lsp/handlers/custom/handler_super.dart';
@@ -77,7 +78,6 @@ class InitializedLspStateMessageHandler extends InitializedStateMessageHandler {
7778
CompletionResolveHandler.new,
7879
DefinitionHandler.new,
7980
DocumentLinkHandler.new,
80-
SuperHandler.new,
8181
ReferencesHandler.new,
8282
CodeActionHandler.new,
8383
ExecuteCommandHandler.new,
@@ -127,6 +127,8 @@ class InitializedStateMessageHandler extends ServerStateMessageHandler {
127127
PrepareCallHierarchyHandler.new,
128128
PrepareTypeHierarchyHandler.new,
129129
SignatureHelpHandler.new,
130+
SuperHandler.new,
131+
AugmentedHandler.new,
130132
TypeDefinitionHandler.new,
131133
TypeHierarchySubtypesHandler.new,
132134
TypeHierarchySupertypesHandler.new,

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,20 @@ class ServerCapabilitiesComputer {
201201
)
202202
: null,
203203
),
204-
experimental: clientCapabilities
205-
.supportsDartExperimentalTextDocumentContentProvider
206-
? {
207-
'dartTextDocumentContentProvider':
208-
features.dartTextDocumentContentProvider.staticRegistration,
209-
}
210-
: null,
204+
experimental: {
205+
if (clientCapabilities
206+
.supportsDartExperimentalTextDocumentContentProvider)
207+
'dartTextDocumentContentProvider':
208+
features.dartTextDocumentContentProvider.staticRegistration,
209+
'textDocument': {
210+
// These properties can be used by the client to know that we support
211+
// custom methods like `dart/textDocument/augmented`.
212+
//
213+
// These fields are objects to allow for future expansion.
214+
'super': {},
215+
'augmented': {},
216+
},
217+
},
211218
);
212219
}
213220

0 commit comments

Comments
 (0)