[analysis_server] Always show type parameters in LSP type hierarchy, not type arguments
The change at 27ba8fce6c (to fix https://github.com/Dart-Code/Dart-Code/issues/4217) added type arguments to the LSP Type Hierarchy (before, neither type args or type params were shown).
Showing type arguments seemed reasonable when looking at supertypes, but behaves oddly for subtypes (and also when invoked on a type with arguments), so this partly reverts that and shows type parameters in all cases instead.
This simplified the code a bit and removed the `TypeHierarchyAnchor` class we were round-tripping in order to preserve the type arguments.
Fixes https://github.com/dart-lang/sdk/issues/60549
Change-Id: I4e0e92d4c73712fde7a9526c51699ecdae0f4ab1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/423020
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
Commit Queue
parent
5b8b52422f
commit
823947b857
+2
-141
@@ -343,32 +343,6 @@ bool _canParseListFlutterOutlineAttribute(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _canParseListInt(
|
||||
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
|
||||
{required bool allowsUndefined, required bool allowsNull}) {
|
||||
reporter.push(fieldName);
|
||||
try {
|
||||
if (!allowsUndefined && !map.containsKey(fieldName)) {
|
||||
reporter.reportError('must not be undefined');
|
||||
return false;
|
||||
}
|
||||
final value = map[fieldName];
|
||||
final nullCheck = allowsNull || allowsUndefined;
|
||||
if (!nullCheck && value == null) {
|
||||
reporter.reportError('must not be null');
|
||||
return false;
|
||||
}
|
||||
if ((!nullCheck || value != null) &&
|
||||
(value is! List<Object?> || value.any((item) => item is! int))) {
|
||||
reporter.reportError('must be of type List<int>');
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
reporter.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _canParseListOutline(
|
||||
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
|
||||
{required bool allowsUndefined, required bool allowsNull}) {
|
||||
@@ -651,31 +625,6 @@ bool _canParseTextDocumentIdentifier(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _canParseTypeHierarchyAnchor(
|
||||
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
|
||||
{required bool allowsUndefined, required bool allowsNull}) {
|
||||
reporter.push(fieldName);
|
||||
try {
|
||||
if (!allowsUndefined && !map.containsKey(fieldName)) {
|
||||
reporter.reportError('must not be undefined');
|
||||
return false;
|
||||
}
|
||||
final value = map[fieldName];
|
||||
final nullCheck = allowsNull || allowsUndefined;
|
||||
if (!nullCheck && value == null) {
|
||||
reporter.reportError('must not be null');
|
||||
return false;
|
||||
}
|
||||
if ((!nullCheck || value != null) &&
|
||||
!TypeHierarchyAnchor.canParse(value, reporter)) {
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
reporter.pop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _canParseUri(
|
||||
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
|
||||
{required bool allowsUndefined, required bool allowsNull}) {
|
||||
@@ -3414,112 +3363,33 @@ class SnippetTextEdit implements TextEdit, ToJsonable {
|
||||
}
|
||||
}
|
||||
|
||||
class TypeHierarchyAnchor implements ToJsonable {
|
||||
static const jsonHandler = LspJsonHandler(
|
||||
TypeHierarchyAnchor.canParse,
|
||||
TypeHierarchyAnchor.fromJson,
|
||||
);
|
||||
|
||||
/// Indices used to navigate from this anchor to the element.
|
||||
final List<int> path;
|
||||
|
||||
/// The ElementLocation for this anchor element.
|
||||
final String ref;
|
||||
|
||||
TypeHierarchyAnchor({
|
||||
required this.path,
|
||||
required this.ref,
|
||||
});
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
lspHashCode(path),
|
||||
ref,
|
||||
);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is TypeHierarchyAnchor &&
|
||||
other.runtimeType == TypeHierarchyAnchor &&
|
||||
const DeepCollectionEquality().equals(path, other.path) &&
|
||||
ref == other.ref;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Object?> toJson() {
|
||||
var result = <String, Object?>{};
|
||||
result['path'] = path;
|
||||
result['ref'] = ref;
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => jsonEncoder.convert(toJson());
|
||||
|
||||
static bool canParse(Object? obj, LspJsonReporter reporter) {
|
||||
if (obj is Map<String, Object?>) {
|
||||
if (!_canParseListInt(obj, reporter, 'path',
|
||||
allowsUndefined: false, allowsNull: false)) {
|
||||
return false;
|
||||
}
|
||||
return _canParseString(obj, reporter, 'ref',
|
||||
allowsUndefined: false, allowsNull: false);
|
||||
} else {
|
||||
reporter.reportError('must be of type TypeHierarchyAnchor');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static TypeHierarchyAnchor fromJson(Map<String, Object?> json) {
|
||||
final pathJson = json['path'];
|
||||
final path =
|
||||
(pathJson as List<Object?>).map((item) => item as int).toList();
|
||||
final refJson = json['ref'];
|
||||
final ref = refJson as String;
|
||||
return TypeHierarchyAnchor(
|
||||
path: path,
|
||||
ref: ref,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TypeHierarchyItemInfo implements ToJsonable {
|
||||
static const jsonHandler = LspJsonHandler(
|
||||
TypeHierarchyItemInfo.canParse,
|
||||
TypeHierarchyItemInfo.fromJson,
|
||||
);
|
||||
|
||||
/// An anchor element that can be used to navigate to this element preserving
|
||||
/// type arguments.
|
||||
final TypeHierarchyAnchor? anchor;
|
||||
|
||||
/// The ElementLocation for this element, used to re-locate the element when
|
||||
/// subtypes/supertypes are fetched later.
|
||||
final String ref;
|
||||
|
||||
TypeHierarchyItemInfo({
|
||||
this.anchor,
|
||||
required this.ref,
|
||||
});
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
anchor,
|
||||
ref,
|
||||
);
|
||||
int get hashCode => ref.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is TypeHierarchyItemInfo &&
|
||||
other.runtimeType == TypeHierarchyItemInfo &&
|
||||
anchor == other.anchor &&
|
||||
ref == other.ref;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Object?> toJson() {
|
||||
var result = <String, Object?>{};
|
||||
if (anchor != null) {
|
||||
result['anchor'] = anchor?.toJson();
|
||||
}
|
||||
result['ref'] = ref;
|
||||
return result;
|
||||
}
|
||||
@@ -3529,10 +3399,6 @@ class TypeHierarchyItemInfo implements ToJsonable {
|
||||
|
||||
static bool canParse(Object? obj, LspJsonReporter reporter) {
|
||||
if (obj is Map<String, Object?>) {
|
||||
if (!_canParseTypeHierarchyAnchor(obj, reporter, 'anchor',
|
||||
allowsUndefined: true, allowsNull: false)) {
|
||||
return false;
|
||||
}
|
||||
return _canParseString(obj, reporter, 'ref',
|
||||
allowsUndefined: false, allowsNull: false);
|
||||
} else {
|
||||
@@ -3542,14 +3408,9 @@ class TypeHierarchyItemInfo implements ToJsonable {
|
||||
}
|
||||
|
||||
static TypeHierarchyItemInfo fromJson(Map<String, Object?> json) {
|
||||
final anchorJson = json['anchor'];
|
||||
final anchor = anchorJson != null
|
||||
? TypeHierarchyAnchor.fromJson(anchorJson as Map<String, Object?>)
|
||||
: null;
|
||||
final refJson = json['ref'];
|
||||
final ref = refJson as String;
|
||||
return TypeHierarchyItemInfo(
|
||||
anchor: anchor,
|
||||
ref: ref,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user