Skip to content

Commit

Permalink
[analysis_server] Include type arguments in Type Hierarchy
Browse files Browse the repository at this point in the history
Fixes Dart-Code/Dart-Code#4217.

Change-Id: I8b8dec4ad25a9eb4a4f80dd036e8a9b61bb012d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/264981
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Brian Wilkerson <[email protected]>
  • Loading branch information
DanTup authored and Commit Queue committed Oct 25, 2022
1 parent 9629401 commit 27ba8fc
Show file tree
Hide file tree
Showing 8 changed files with 545 additions and 107 deletions.
193 changes: 193 additions & 0 deletions pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1858,6 +1858,147 @@ class SnippetTextEdit implements TextEdit, ToJsonable {
String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyAnchor implements ToJsonable {
static const jsonHandler = LspJsonHandler(
TypeHierarchyAnchor.canParse,
TypeHierarchyAnchor.fromJson,
);

TypeHierarchyAnchor({
required this.path,
required this.ref,
});
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,
);
}

/// Indices used to navigate from this anchor to the element.
final List<int> path;

/// The ElementLocation for this anchor element.
final String ref;

@override
Map<String, Object?> toJson() {
var result = <String, Object?>{};
result['path'] = path;
result['ref'] = ref;
return result;
}

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;
}
}

@override
bool operator ==(Object other) {
return other is TypeHierarchyAnchor &&
other.runtimeType == TypeHierarchyAnchor &&
listEqual(path, other.path, (int a, int b) => a == b) &&
ref == other.ref;
}

@override
int get hashCode => Object.hash(
lspHashCode(path),
ref,
);

@override
String toString() => jsonEncoder.convert(toJson());
}

class TypeHierarchyItemInfo implements ToJsonable {
static const jsonHandler = LspJsonHandler(
TypeHierarchyItemInfo.canParse,
TypeHierarchyItemInfo.fromJson,
);

TypeHierarchyItemInfo({
this.anchor,
required this.ref,
});
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,
);
}

/// 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;

@override
Map<String, Object?> toJson() {
var result = <String, Object?>{};
if (anchor != null) {
result['anchor'] = anchor?.toJson();
}
result['ref'] = ref;
return result;
}

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 {
reporter.reportError('must be of type TypeHierarchyItemInfo');
return false;
}
}

@override
bool operator ==(Object other) {
return other is TypeHierarchyItemInfo &&
other.runtimeType == TypeHierarchyItemInfo &&
anchor == other.anchor &&
ref == other.ref;
}

@override
int get hashCode => Object.hash(
anchor,
ref,
);

@override
String toString() => jsonEncoder.convert(toJson());
}

class ValidateRefactorResult implements ToJsonable {
static const jsonHandler = LspJsonHandler(
ValidateRefactorResult.canParse,
Expand Down Expand Up @@ -2184,6 +2325,32 @@ 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}) {
Expand Down Expand Up @@ -2395,6 +2562,32 @@ bool _canParseString(
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)) {
reporter.reportError('must be of type TypeHierarchyAnchor');
return false;
}
} finally {
reporter.pop();
}
return true;
}

bool _canParseUri(
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
{required bool allowsUndefined, required bool allowsNull}) {
Expand Down
38 changes: 35 additions & 3 deletions pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31448,7 +31448,9 @@ class TypeHierarchyItem implements ToJsonable {
});
static TypeHierarchyItem fromJson(Map<String, Object?> json) {
final dataJson = json['data'];
final data = dataJson;
final data = dataJson != null
? TypeHierarchyItemInfo.fromJson(dataJson as Map<String, Object?>)
: null;
final detailJson = json['detail'];
final detail = detailJson as String?;
final kindJson = json['kind'];
Expand Down Expand Up @@ -31482,7 +31484,7 @@ class TypeHierarchyItem implements ToJsonable {
/// supertypes or subtypes requests. It could also be used to identify the
/// type hierarchy in the server, helping improve the performance on resolving
/// supertypes and subtypes.
final LSPAny data;
final TypeHierarchyItemInfo? data;

/// More detail for this item, e.g. the signature of a function.
final String? detail;
Expand Down Expand Up @@ -31511,7 +31513,7 @@ class TypeHierarchyItem implements ToJsonable {
Map<String, Object?> toJson() {
var result = <String, Object?>{};
if (data != null) {
result['data'] = data;
result['data'] = data?.toJson();
}
if (detail != null) {
result['detail'] = detail;
Expand All @@ -31529,6 +31531,10 @@ class TypeHierarchyItem implements ToJsonable {

static bool canParse(Object? obj, LspJsonReporter reporter) {
if (obj is Map<String, Object?>) {
if (!_canParseTypeHierarchyItemInfo(obj, reporter, 'data',
allowsUndefined: true, allowsNull: false)) {
return false;
}
if (!_canParseString(obj, reporter, 'detail',
allowsUndefined: true, allowsNull: false)) {
return false;
Expand Down Expand Up @@ -41981,6 +41987,32 @@ bool _canParseTypeHierarchyItem(
return true;
}

bool _canParseTypeHierarchyItemInfo(
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) &&
!TypeHierarchyItemInfo.canParse(value, reporter)) {
reporter.reportError('must be of type TypeHierarchyItemInfo');
return false;
}
} finally {
reporter.pop();
}
return true;
}

bool _canParseUniquenessLevel(
Map<String, Object?> map, LspJsonReporter reporter, String fieldName,
{required bool allowsUndefined, required bool allowsNull}) {
Expand Down
Loading

0 comments on commit 27ba8fc

Please sign in to comment.