Skip to content

Commit d38e0ff

Browse files
DanTupCommit Queue
authored andcommitted
[analysis_server] Migrate LSP "Go to Type Definition" to new element model
Change-Id: I4de207adc9301b2533885d51329ccc0b6600b86d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/395380 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
1 parent 0ebb4fe commit d38e0ff

File tree

4 files changed

+78
-58
lines changed

4 files changed

+78
-58
lines changed

pkg/analysis_server/analyzer_use_new_elements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ lib/src/lsp/handlers/handler_document_color_presentation.dart
2424
lib/src/lsp/handlers/handler_implementation.dart
2525
lib/src/lsp/handlers/handler_references.dart
2626
lib/src/lsp/handlers/handler_rename.dart
27-
lib/src/lsp/handlers/handler_type_definition.dart
2827
lib/src/operation/operation_analysis.dart
2928
lib/src/protocol_server.dart
3029
lib/src/search/element_references.dart

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

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,12 @@ import 'package:analysis_server/src/lsp/mapping.dart';
99
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
1010
import 'package:analyzer/dart/ast/ast.dart';
1111
import 'package:analyzer/dart/ast/syntactic_entity.dart';
12-
import 'package:analyzer/dart/element/element.dart' as analyzer;
13-
import 'package:analyzer/dart/element/element.dart';
12+
import 'package:analyzer/dart/element/element2.dart';
1413
import 'package:analyzer/dart/element/type.dart';
1514
import 'package:analyzer/source/line_info.dart';
1615
import 'package:analyzer/src/dart/ast/extensions.dart';
1716
import 'package:analyzer/src/dart/ast/utilities.dart';
18-
import 'package:analyzer/src/dart/element/element.dart' as analyzer;
19-
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
20-
import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
17+
import 'package:analyzer/src/dart/element/element.dart';
2118

2219
typedef StaticOptions =
2320
Either3<bool, TypeDefinitionOptions, TypeDefinitionRegistrationOptions>;
@@ -87,126 +84,128 @@ class TypeDefinitionHandler
8784
DartType? type;
8885
if (node is NamedType) {
8986
originEntity = node.name2;
90-
var element = node.element;
91-
if (element is InterfaceElement) {
87+
var element = node.element2;
88+
if (element case InterfaceElement2 element) {
9289
type = element.thisType;
9390
}
9491
} else if (node is VariableDeclaration) {
9592
originEntity = node.name;
96-
type = node.declaredElement?.type;
93+
type = node.declaredFragment?.element.type;
9794
} else if (node is DeclaredIdentifier) {
9895
originEntity = node.name;
99-
type = node.declaredElement?.type;
96+
type = node.declaredFragment?.element.type;
10097
} else if (node is Expression) {
10198
originEntity = node;
10299
type = _getType(node);
103100
} else if (node is FormalParameter) {
104101
originEntity = node.name;
105-
type = node.declaredElement?.type;
102+
type = node.declaredFragment?.element.type;
106103
}
107104
if (originEntity == null) {
108105
return success(_emptyResult);
109106
}
110107

111-
analyzer.Element? element;
108+
Element2? element;
112109
if (type is InterfaceType) {
113-
element = type.element;
110+
element = type.element3;
114111
} else if (type is TypeParameterType) {
115-
element = type.element;
112+
element = type.element3;
116113
}
117-
if (element is! analyzer.ElementImpl) {
114+
if (element is! Element2) {
118115
return success(_emptyResult);
119116
}
120117

121-
// Obtain a `LineInfo` for the targets file to map offsets.
122-
var targetUnitElement =
123-
element.thisOrAncestorOfType<CompilationUnitElement>();
124-
var targetLineInfo = targetUnitElement?.lineInfo;
125-
if (targetLineInfo == null) {
118+
// TODO(dantup): Consider returning all fragments for the type instead
119+
// of only the first.
120+
var targetFragment = element.nonSynthetic2.firstFragment;
121+
var targetUnit = targetFragment.libraryFragment;
122+
if (targetUnit == null) {
126123
return success(_emptyResult);
127124
}
128125

129-
var converter = AnalyzerConverter();
130-
var location = converter.locationFromElement(element);
131-
if (location == null) {
126+
var nameOffset = targetFragment.nameOffset2;
127+
var nameLength = targetFragment.name2?.length;
128+
if (nameOffset == null || nameLength == null) {
132129
return success(_emptyResult);
133130
}
134131

132+
var nameRange = toRange(targetUnit.lineInfo, nameOffset, nameLength);
135133
if (supportsLocationLink) {
136134
return success(
137135
TextDocumentTypeDefinitionResult.t2([
138136
_toLocationLink(
139-
result.lineInfo,
140-
targetLineInfo,
141137
originEntity,
142-
element,
143-
location,
138+
result.lineInfo,
139+
targetFragment,
140+
nameRange,
141+
targetUnit,
144142
),
145143
]),
146144
);
147145
} else {
148146
return success(
149147
TextDocumentTypeDefinitionResult.t1(
150-
Definition.t2(_toLocation(location, targetLineInfo)),
148+
Definition.t2(_toLocation(targetFragment, nameRange, targetUnit)),
151149
),
152150
);
153151
}
154152
});
155153
});
156154
}
157155

158-
/// Creates an LSP [Location] for the server [location].
159-
Location _toLocation(plugin.Location location, LineInfo lineInfo) {
156+
/// Creates an LSP [Location] for navigating to [targetFragment].
157+
Location _toLocation(
158+
Fragment targetFragment,
159+
Range targetNameRange,
160+
LibraryFragment targetUnit,
161+
) {
160162
return Location(
161-
uri: uriConverter.toClientUri(location.file),
162-
range: toRange(lineInfo, location.offset, location.length),
163+
uri: uriConverter.toClientUri(targetUnit.source.fullName),
164+
range: targetNameRange,
163165
);
164166
}
165167

166-
/// Creates an LSP [LocationLink] for the server [targetLocation].
168+
/// Creates an LSP [LocationLink] for navigating to [targetFragment].
167169
///
168170
/// Uses [originLineInfo] and [originEntity] to compute `originSelectionRange`
169-
/// and [targetLineInfo] and [targetElement] for code ranges.
171+
/// and [targetFragment] and [targetUnit] for code ranges.
170172
LocationLink _toLocationLink(
171-
LineInfo originLineInfo,
172-
LineInfo targetLineInfo,
173173
SyntacticEntity originEntity,
174-
analyzer.ElementImpl targetElement,
175-
plugin.Location targetLocation,
174+
LineInfo originLineInfo,
175+
Fragment targetFragment,
176+
Range targetNameRange,
177+
LibraryFragment targetUnit,
176178
) {
177-
var nameRange = toRange(
178-
targetLineInfo,
179-
targetLocation.offset,
180-
targetLocation.length,
181-
);
179+
var (codeOffset, codeLength) = switch (targetFragment) {
180+
ElementImpl e => (e.codeOffset, e.codeLength),
181+
_ => (null, null),
182+
};
182183

183-
var codeOffset = targetElement.codeOffset;
184-
var codeLength = targetElement.codeLength;
185184
var codeRange =
186185
codeOffset != null && codeLength != null
187-
? toRange(targetLineInfo, codeOffset, codeLength)
188-
: nameRange;
186+
? toRange(targetUnit.lineInfo, codeOffset, codeLength)
187+
: targetNameRange;
189188

190189
return LocationLink(
191190
originSelectionRange: toRange(
192191
originLineInfo,
193192
originEntity.offset,
194193
originEntity.length,
195194
),
196-
targetUri: uriConverter.toClientUri(targetLocation.file),
195+
targetUri: uriConverter.toClientUri(targetUnit.source.fullName),
197196
targetRange: codeRange,
198-
targetSelectionRange: nameRange,
197+
targetSelectionRange: targetNameRange,
199198
);
200199
}
201200

202201
/// Returns the [DartType] most appropriate for navigating to from [node] when
203202
/// invoking Go to Type Definition.
204203
static DartType? _getType(Expression node) {
205204
if (node is SimpleIdentifier) {
206-
var element = node.staticElement;
207-
if (element is InterfaceElement) {
205+
var element = node.element;
206+
if (element case InterfaceElement2 element) {
208207
return element.thisType;
209-
} else if (element is VariableElement) {
208+
} else if (element case VariableElement2 element) {
210209
if (node.inDeclarationContext()) {
211210
return element.type;
212211
}
@@ -215,9 +214,11 @@ class TypeDefinitionHandler
215214
return element.type;
216215
}
217216
} else if (node.inSetterContext()) {
218-
var writeElement = node.writeElement;
219-
if (writeElement is PropertyAccessorElement) {
220-
return writeElement.variable2?.type;
217+
var writeElement = node.writeOrReadElement2;
218+
if (writeElement
219+
case GetterElement(:var variable3) ||
220+
SetterElement(:var variable3)) {
221+
return variable3?.type;
221222
}
222223
}
223224
}

pkg/analysis_server/test/lsp/type_definition_test.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@ class A {
7373
String get aaa => '';
7474
}
7575
76+
void f() {
77+
final a = A();
78+
print(a.[!a^aa!]);
79+
}
80+
''');
81+
82+
var result = await _getResult(code);
83+
expect(result.originSelectionRange, code.range.range);
84+
_expectSdkCoreType(result, 'String');
85+
}
86+
87+
Future<void> test_getter_synthetic() async {
88+
var code = TestCode.parse('''
89+
class A {
90+
String aaa = '';
91+
}
92+
7693
void f() {
7794
final a = A();
7895
print(a.[!a^aa!]);

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4834,6 +4834,9 @@ abstract final class DeclaredIdentifier implements Declaration {
48344834
@experimental
48354835
LocalVariableElement2? get declaredElement2;
48364836

4837+
@override
4838+
LocalVariableFragment? get declaredFragment;
4839+
48374840
/// Whether this variable was declared with the 'const' modifier.
48384841
bool get isConst;
48394842

@@ -4868,9 +4871,6 @@ final class DeclaredIdentifierImpl extends DeclarationImpl
48684871
@override
48694872
LocalVariableElementImpl? declaredElement;
48704873

4871-
@override
4872-
LocalVariableElementImpl? declaredFragment;
4873-
48744874
/// Initializes a newly created formal parameter.
48754875
///
48764876
/// Either or both of the [comment] and [metadata] can be `null` if the
@@ -4895,6 +4895,9 @@ final class DeclaredIdentifierImpl extends DeclarationImpl
48954895
return declaredElement.asElement2 as LocalVariableElementImpl2?;
48964896
}
48974897

4898+
@override
4899+
LocalVariableFragment? get declaredFragment => declaredElement;
4900+
48984901
@override
48994902
Token get endToken => name;
49004903

0 commit comments

Comments
 (0)