[analysis_server] Extract TypeHierarchyItemLocation as ElementLocation2 and use for completion resolution
This moves completion resolution off `ElementLocation` onto the class recently created as `TypeHierarchyItemLocation`, which is now renamed to `ElementLocation2` and extracted to its own file. Change-Id: I1f0b831ded7b08d6c09f97fcfd66f38f1dd4750e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/401021 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
committed by
Commit Queue
parent
466fa5593d
commit
76623a6541
@@ -6,15 +6,14 @@
|
||||
library;
|
||||
|
||||
import 'package:analysis_server/src/services/search/search_engine.dart';
|
||||
import 'package:analysis_server/src/utilities/element_location2.dart';
|
||||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/source/source_range.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/utilities/extensions/ast.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
/// A lazy computer for Type Hierarchies.
|
||||
///
|
||||
@@ -36,9 +35,9 @@ class DartLazyTypeHierarchyComputer {
|
||||
|
||||
DartLazyTypeHierarchyComputer(this._result);
|
||||
|
||||
/// Finds subtypes for [Element] at [location].
|
||||
/// Finds subtypes for the [Element2] at [location].
|
||||
Future<List<TypeHierarchyRelatedItem>?> findSubtypes(
|
||||
TypeHierarchyItemLocation location,
|
||||
ElementLocation2 location,
|
||||
SearchEngine searchEngine,
|
||||
) async {
|
||||
var targetElement = await _findTargetElement(location);
|
||||
@@ -49,7 +48,7 @@ class DartLazyTypeHierarchyComputer {
|
||||
return _getSubtypes(targetElement, searchEngine);
|
||||
}
|
||||
|
||||
/// Finds supertypes for the [Element] at [location].
|
||||
/// Finds supertypes for the [Element2] at [location].
|
||||
///
|
||||
/// If [anchor] is provided, it will be used to navigate to the element at
|
||||
/// [location] to preserve type arguments that have been provided along the
|
||||
@@ -58,7 +57,7 @@ class DartLazyTypeHierarchyComputer {
|
||||
/// Anchors are included in returned types (where necessary to preserve type
|
||||
/// arguments) that can be used when calling for the next level of types.
|
||||
Future<List<TypeHierarchyRelatedItem>?> findSupertypes(
|
||||
TypeHierarchyItemLocation location, {
|
||||
ElementLocation2 location, {
|
||||
TypeHierarchyAnchor? anchor,
|
||||
}) async {
|
||||
var targetElement = await _findTargetElement(location);
|
||||
@@ -105,11 +104,11 @@ class DartLazyTypeHierarchyComputer {
|
||||
return type is InterfaceType ? TypeHierarchyItem.forType(type) : null;
|
||||
}
|
||||
|
||||
/// Locate the [Element] referenced by [location].
|
||||
/// Locate the [Element2] referenced by [location].
|
||||
Future<InterfaceElement2?> _findTargetElement(
|
||||
TypeHierarchyItemLocation location,
|
||||
ElementLocation2 location,
|
||||
) async {
|
||||
var element = await location._locateIn(_result.session);
|
||||
var element = await location.locateIn(_result.session);
|
||||
return element is InterfaceElement2 ? element : null;
|
||||
}
|
||||
|
||||
@@ -119,7 +118,7 @@ class DartLazyTypeHierarchyComputer {
|
||||
SearchEngine searchEngine,
|
||||
) async {
|
||||
/// Helper to convert a [SearchMatch] to a [TypeHierarchyRelatedItem].
|
||||
TypeHierarchyRelatedItem toHierarchyItem(SearchMatch match) {
|
||||
TypeHierarchyRelatedItem? toHierarchyItem(SearchMatch match) {
|
||||
var element = match.element2 as InterfaceElement2;
|
||||
var type = element.thisType;
|
||||
switch (match.kind) {
|
||||
@@ -145,6 +144,7 @@ class DartLazyTypeHierarchyComputer {
|
||||
return matches
|
||||
.where((match) => seenElements.add(match.element2))
|
||||
.map(toHierarchyItem)
|
||||
.nonNulls
|
||||
.toList();
|
||||
}
|
||||
|
||||
@@ -162,12 +162,13 @@ class DartLazyTypeHierarchyComputer {
|
||||
var mixins = type.mixins;
|
||||
var superclassConstraints = type.superclassConstraints;
|
||||
|
||||
var supertypes = [
|
||||
if (supertype != null) TypeHierarchyRelatedItem.extends_(supertype),
|
||||
...superclassConstraints.map(TypeHierarchyRelatedItem.constrainedTo),
|
||||
...interfaces.map(TypeHierarchyRelatedItem.implements),
|
||||
...mixins.map(TypeHierarchyRelatedItem.mixesIn),
|
||||
];
|
||||
var supertypes =
|
||||
[
|
||||
if (supertype != null) TypeHierarchyRelatedItem.extends_(supertype),
|
||||
...superclassConstraints.map(TypeHierarchyRelatedItem.constrainedTo),
|
||||
...interfaces.map(TypeHierarchyRelatedItem.implements),
|
||||
...mixins.map(TypeHierarchyRelatedItem.mixesIn),
|
||||
].nonNulls.toList();
|
||||
|
||||
if (anchor != null) {
|
||||
for (var (index, item) in supertypes.indexed) {
|
||||
@@ -219,7 +220,7 @@ class DartLazyTypeHierarchyComputer {
|
||||
|
||||
class TypeHierarchyAnchor {
|
||||
/// The location of the anchor element.
|
||||
final TypeHierarchyItemLocation location;
|
||||
final ElementLocation2 location;
|
||||
|
||||
/// The supertype path from [location] to the target element.
|
||||
final List<int> path;
|
||||
@@ -238,7 +239,7 @@ class TypeHierarchyItem {
|
||||
/// `findSubtypes`/`findSupertypes` so that if code has been modified since
|
||||
/// the `findTarget` call the element can still be located (provided the
|
||||
/// names/identifiers have not changed).
|
||||
final TypeHierarchyItemLocation location;
|
||||
final ElementLocation2 location;
|
||||
|
||||
/// The type being displayed.
|
||||
final InterfaceType _type;
|
||||
@@ -261,15 +262,21 @@ class TypeHierarchyItem {
|
||||
required this.codeRange,
|
||||
}) : _type = type;
|
||||
|
||||
TypeHierarchyItem.forType(InterfaceType type)
|
||||
: this(
|
||||
type: type,
|
||||
displayName: _displayNameForType(type),
|
||||
location: TypeHierarchyItemLocation.forElement(type.element3),
|
||||
nameRange: _nameRangeForElement(type.element3),
|
||||
codeRange: _codeRangeForElement(type.element3),
|
||||
file: type.element3.firstFragment.libraryFragment.source.fullName,
|
||||
);
|
||||
TypeHierarchyItem._forType({
|
||||
required InterfaceType type,
|
||||
required this.location,
|
||||
}) : _type = type,
|
||||
displayName = _displayNameForType(type),
|
||||
nameRange = _nameRangeForElement(type.element3),
|
||||
codeRange = _codeRangeForElement(type.element3),
|
||||
file = type.element3.firstFragment.libraryFragment.source.fullName;
|
||||
|
||||
static TypeHierarchyItem? forType(InterfaceType type) {
|
||||
var location = ElementLocation2.forElement(type.element3);
|
||||
if (location == null) return null;
|
||||
|
||||
return TypeHierarchyItem._forType(type: type, location: location);
|
||||
}
|
||||
|
||||
/// Returns the [SourceRange] of the code for [element].
|
||||
static SourceRange _codeRangeForElement(Element2 element) {
|
||||
@@ -296,58 +303,6 @@ class TypeHierarchyItem {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the location of an item that can appear in Type Hierarchy that
|
||||
/// can be encoded to/from a [String] for round-tripping to the client.
|
||||
class TypeHierarchyItemLocation {
|
||||
/// The URI of the Library that contains this type.
|
||||
final String _libraryUri;
|
||||
|
||||
/// The [Element2.name3] for this type.
|
||||
final String _name;
|
||||
|
||||
factory TypeHierarchyItemLocation.decode(String encoded) {
|
||||
var parts = encoded.split(';');
|
||||
if (parts.length != 2) {
|
||||
throw ArgumentError(
|
||||
"Encoded string should be in format 'libraryUri;name' encoded",
|
||||
);
|
||||
}
|
||||
return TypeHierarchyItemLocation._(libraryUri: parts[0], name: parts[1]);
|
||||
}
|
||||
|
||||
factory TypeHierarchyItemLocation.forElement(InterfaceElement2 element) {
|
||||
var name = element.name3;
|
||||
|
||||
if (name == null) {
|
||||
throw ArgumentError(
|
||||
'Cannot create TypeHierarchyItemLocation for an element with no name: $element',
|
||||
);
|
||||
}
|
||||
|
||||
return TypeHierarchyItemLocation._(
|
||||
libraryUri: element.library2.uri.toString(),
|
||||
name: name,
|
||||
);
|
||||
}
|
||||
|
||||
TypeHierarchyItemLocation._({
|
||||
required String libraryUri,
|
||||
required String name,
|
||||
}) : _name = name,
|
||||
_libraryUri = libraryUri;
|
||||
|
||||
String get encoding => '$_libraryUri;$_name';
|
||||
|
||||
Future<InterfaceElement2?> _locateIn(AnalysisSession session) async {
|
||||
var result = await session.getLibraryByUri(_libraryUri);
|
||||
return result is LibraryElementResult
|
||||
? result.element2.children2
|
||||
.whereType<InterfaceElement2>()
|
||||
.firstWhereOrNull((element2) => element2.name3 == _name)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
enum TypeHierarchyItemRelationship {
|
||||
unknown,
|
||||
implements,
|
||||
@@ -363,29 +318,51 @@ class TypeHierarchyRelatedItem extends TypeHierarchyItem {
|
||||
|
||||
TypeHierarchyAnchor? _anchor;
|
||||
|
||||
TypeHierarchyRelatedItem.constrainedTo(InterfaceType type)
|
||||
: this._forType(
|
||||
type,
|
||||
relationship: TypeHierarchyItemRelationship.constrainedTo,
|
||||
);
|
||||
TypeHierarchyRelatedItem.extends_(InterfaceType type)
|
||||
: this._forType(type, relationship: TypeHierarchyItemRelationship.extends_);
|
||||
TypeHierarchyRelatedItem({
|
||||
required super.type,
|
||||
required this.relationship,
|
||||
required super.displayName,
|
||||
required super.location,
|
||||
required super.file,
|
||||
required super.nameRange,
|
||||
required super.codeRange,
|
||||
});
|
||||
|
||||
TypeHierarchyRelatedItem.implements(InterfaceType type)
|
||||
: this._forType(
|
||||
type,
|
||||
relationship: TypeHierarchyItemRelationship.implements,
|
||||
);
|
||||
|
||||
TypeHierarchyRelatedItem.mixesIn(InterfaceType type)
|
||||
: this._forType(type, relationship: TypeHierarchyItemRelationship.mixesIn);
|
||||
|
||||
TypeHierarchyRelatedItem.unknown(InterfaceType type)
|
||||
: this._forType(type, relationship: TypeHierarchyItemRelationship.unknown);
|
||||
|
||||
TypeHierarchyRelatedItem._forType(super.type, {required this.relationship})
|
||||
: super.forType();
|
||||
TypeHierarchyRelatedItem.forType({
|
||||
required super.type,
|
||||
required this.relationship,
|
||||
required super.location,
|
||||
}) : super._forType();
|
||||
|
||||
/// An optional anchor element used to preserve type args.
|
||||
TypeHierarchyAnchor? get anchor => _anchor;
|
||||
|
||||
static TypeHierarchyRelatedItem? constrainedTo(InterfaceType type) =>
|
||||
_forType(type, relationship: TypeHierarchyItemRelationship.constrainedTo);
|
||||
|
||||
static TypeHierarchyRelatedItem? extends_(InterfaceType type) =>
|
||||
_forType(type, relationship: TypeHierarchyItemRelationship.extends_);
|
||||
|
||||
static TypeHierarchyRelatedItem? implements(InterfaceType type) =>
|
||||
_forType(type, relationship: TypeHierarchyItemRelationship.implements);
|
||||
|
||||
static TypeHierarchyRelatedItem? mixesIn(InterfaceType type) =>
|
||||
_forType(type, relationship: TypeHierarchyItemRelationship.mixesIn);
|
||||
|
||||
static TypeHierarchyRelatedItem? unknown(InterfaceType type) =>
|
||||
_forType(type, relationship: TypeHierarchyItemRelationship.unknown);
|
||||
|
||||
static TypeHierarchyRelatedItem? _forType(
|
||||
InterfaceType type, {
|
||||
required TypeHierarchyItemRelationship relationship,
|
||||
}) {
|
||||
var location = ElementLocation2.forElement(type.element3);
|
||||
if (location == null) return null;
|
||||
|
||||
return TypeHierarchyRelatedItem.forType(
|
||||
type: type,
|
||||
relationship: relationship,
|
||||
location: location,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.d
|
||||
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
|
||||
import 'package:analysis_server/src/services/snippets/dart_snippet_request.dart';
|
||||
import 'package:analysis_server/src/services/snippets/snippet_manager.dart';
|
||||
import 'package:analysis_server/src/utilities/element_location2.dart';
|
||||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart' as ast;
|
||||
import 'package:analyzer/source/line_info.dart';
|
||||
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
|
||||
import 'package:analyzer/src/util/performance/operation_performance.dart';
|
||||
import 'package:analyzer/src/utilities/extensions/element.dart';
|
||||
import 'package:analyzer/src/utilities/fuzzy_matcher.dart';
|
||||
import 'package:analyzer_plugin/protocol/protocol_common.dart';
|
||||
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
|
||||
@@ -478,27 +478,26 @@ class CompletionHandler
|
||||
CompletionItemResolutionInfo? resolutionInfo;
|
||||
|
||||
if (item is ElementBasedSuggestion && item is ImportableSuggestion) {
|
||||
var elementLocation =
|
||||
(item as ElementBasedSuggestion).element.asElement!.location;
|
||||
var importUri = item.importData?.libraryUri;
|
||||
var element = (item as ElementBasedSuggestion).element;
|
||||
|
||||
var importUri = item.importData?.libraryUri;
|
||||
if (importUri != null) {
|
||||
resolutionInfo = DartCompletionResolutionInfo(
|
||||
file: unit.path,
|
||||
importUris: [importUri.toString()],
|
||||
ref: elementLocation?.encoding,
|
||||
ref: ElementLocation2.forElement(element)?.encoding,
|
||||
);
|
||||
}
|
||||
} else if (item is OverrideSuggestion) {
|
||||
var overrideData = item.data;
|
||||
if (overrideData != null && overrideData.imports.isNotEmpty) {
|
||||
var elementLocation =
|
||||
(item as ElementBasedSuggestion).element.location;
|
||||
var element = (item as ElementBasedSuggestion).element;
|
||||
|
||||
var importUris = overrideData.imports;
|
||||
resolutionInfo = DartCompletionResolutionInfo(
|
||||
file: unit.path,
|
||||
importUris: importUris.map((uri) => uri.toString()).toList(),
|
||||
ref: elementLocation?.encoding,
|
||||
ref: ElementLocation2.forElement(element)?.encoding,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,9 @@ import 'package:analysis_server/src/lsp/constants.dart';
|
||||
import 'package:analysis_server/src/lsp/error_or.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
|
||||
import 'package:analysis_server/src/lsp/mapping.dart';
|
||||
import 'package:analysis_server/src/utilities/element_location2.dart';
|
||||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/utilities/extensions/analysis_session.dart';
|
||||
import 'package:analyzer/src/utilities/extensions/element.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
|
||||
class CompletionResolveHandler
|
||||
@@ -63,11 +61,7 @@ class CompletionResolveHandler
|
||||
) async {
|
||||
var file = data.file;
|
||||
var importUris = data.importUris.map(Uri.parse).toList();
|
||||
var elementLocationReference = data.ref;
|
||||
var elementLocation =
|
||||
elementLocationReference != null
|
||||
? ElementLocationImpl.con2(elementLocationReference)
|
||||
: null;
|
||||
var elementReference = data.ref;
|
||||
|
||||
const timeout = Duration(milliseconds: 1000);
|
||||
var timer = Stopwatch()..start();
|
||||
@@ -130,8 +124,10 @@ class CompletionResolveHandler
|
||||
// Look up documentation if we can get an element for this item.
|
||||
Either2<MarkupContent, String>? documentation;
|
||||
var element =
|
||||
elementLocation != null
|
||||
? (await session.locateElement(elementLocation)).asElement2
|
||||
elementReference != null
|
||||
? await ElementLocation2.decode(
|
||||
elementReference,
|
||||
).locateIn(session)
|
||||
: null;
|
||||
if (element != null) {
|
||||
var formats = clientCapabilities.completionDocumentationFormats;
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:analysis_server/src/lsp/error_or.dart';
|
||||
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
|
||||
import 'package:analysis_server/src/lsp/mapping.dart';
|
||||
import 'package:analysis_server/src/lsp/registration/feature_registration.dart';
|
||||
import 'package:analysis_server/src/utilities/element_location2.dart';
|
||||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/source/line_info.dart';
|
||||
@@ -140,7 +141,7 @@ class TypeHierarchySubtypesHandler
|
||||
);
|
||||
}
|
||||
|
||||
var location = type_hierarchy.TypeHierarchyItemLocation.decode(data.ref);
|
||||
var location = ElementLocation2.decode(data.ref);
|
||||
var calls = await computer.findSubtypes(location, server.searchEngine);
|
||||
var results = calls != null ? _convertItems(unit, calls) : null;
|
||||
return success(results);
|
||||
@@ -188,7 +189,7 @@ class TypeHierarchySupertypesHandler
|
||||
);
|
||||
}
|
||||
|
||||
var location = type_hierarchy.TypeHierarchyItemLocation.decode(data.ref);
|
||||
var location = ElementLocation2.decode(data.ref);
|
||||
var anchor = _toServerAnchor(data);
|
||||
var calls = await computer.findSupertypes(location, anchor: anchor);
|
||||
var results = calls != null ? _convertItems(unit, calls) : null;
|
||||
@@ -204,7 +205,7 @@ class TypeHierarchySupertypesHandler
|
||||
var anchor = data.anchor;
|
||||
return anchor != null
|
||||
? type_hierarchy.TypeHierarchyAnchor(
|
||||
location: type_hierarchy.TypeHierarchyItemLocation.decode(anchor.ref),
|
||||
location: ElementLocation2.decode(anchor.ref),
|
||||
path: anchor.path,
|
||||
)
|
||||
: null;
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/dart/analysis/results.dart';
|
||||
import 'package:analyzer/dart/analysis/session.dart';
|
||||
import 'package:analyzer/dart/element/element2.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
/// Represents the location of an [Element2] that exists in a chain of elements
|
||||
/// from a [LibraryElement2].
|
||||
///
|
||||
/// Elements with [Fragment]s or Elements with `null` names anywhere in the
|
||||
/// chain are not representable.
|
||||
class ElementLocation2 {
|
||||
/// The library that this element belongs to.
|
||||
final String _libraryUri;
|
||||
|
||||
/// The [Element2.lookupName] for this element, or the containing element if
|
||||
/// this location is a [_MemberElementLocation2].
|
||||
final String _topLevelName;
|
||||
|
||||
factory ElementLocation2.decode(String encoded) {
|
||||
var components = encoded.split(';');
|
||||
return switch (components) {
|
||||
[String library, String topName] => ElementLocation2._(library, topName),
|
||||
[String library, String topName, String memberName] =>
|
||||
_MemberElementLocation2._(library, topName, memberName),
|
||||
_ =>
|
||||
throw ArgumentError.value(
|
||||
encoded,
|
||||
'encoded',
|
||||
"Encoded string should be in the format 'libraryUri;topLevelName[;memberName]'",
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
ElementLocation2._(this._libraryUri, this._topLevelName);
|
||||
|
||||
String get encoding => '$_libraryUri;$_topLevelName';
|
||||
|
||||
/// Locates the [Element2] represented by this [ElementLocation2] in
|
||||
/// [session].
|
||||
///
|
||||
/// Returns `null` if the [Element2] cannot be located.
|
||||
Future<Element2?> locateIn(AnalysisSession session) async {
|
||||
var result = await session.getLibraryByUri(_libraryUri);
|
||||
if (result is! LibraryElementResult) return null;
|
||||
|
||||
return result.element2.children2.firstWhereOrNull(
|
||||
(child) => child.lookupName == _topLevelName,
|
||||
);
|
||||
}
|
||||
|
||||
/// Gets an [ElementLocation2] for this element.
|
||||
///
|
||||
/// Returns `null` if this element is neither a top level element or a
|
||||
/// member of a top level element, or if either do not have a `lookupName`.
|
||||
static ElementLocation2? forElement(Element2 element) {
|
||||
var library = element.library2;
|
||||
if (library == null) return null;
|
||||
var libraryUri = library.uri.toString();
|
||||
|
||||
if (element.enclosingElement2 == library) {
|
||||
var topName = element.lookupName;
|
||||
|
||||
return topName != null ? ElementLocation2._(libraryUri, topName) : null;
|
||||
} else if (element.enclosingElement2?.enclosingElement2 == library) {
|
||||
var memberName = element.lookupName;
|
||||
var topName = element.enclosingElement2?.lookupName;
|
||||
|
||||
return topName != null && memberName != null
|
||||
? _MemberElementLocation2._(libraryUri, topName, memberName)
|
||||
: null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _MemberElementLocation2 extends ElementLocation2 {
|
||||
/// The [Element2.lookupName] for this member within [_topLevelName].
|
||||
final String _memberName;
|
||||
|
||||
_MemberElementLocation2._(
|
||||
super.libraryUri,
|
||||
super.topLevelName,
|
||||
this._memberName,
|
||||
) : super._();
|
||||
|
||||
@override
|
||||
String get encoding => '${super.encoding};$_memberName';
|
||||
|
||||
/// Locates the [Element2] represented by this [_MemberElementLocation2] in
|
||||
/// [session].
|
||||
///
|
||||
/// Returns `null` if the [Element2] cannot be located.
|
||||
@override
|
||||
Future<Element2?> locateIn(AnalysisSession session) async {
|
||||
var topLevel = await super.locateIn(session);
|
||||
|
||||
return topLevel?.children2.firstWhereOrNull(
|
||||
(child) => child.lookupName == _memberName,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -369,7 +369,7 @@ List<LspEntity> getCustomClasses() {
|
||||
type: 'string',
|
||||
canBeUndefined: true,
|
||||
comment:
|
||||
'The ElementLocation of the item being completed.\n\n'
|
||||
'The encoded ElementLocation2 of the item being completed.\n\n'
|
||||
'This is used to provide documentation in the resolved response.',
|
||||
),
|
||||
], baseType: 'CompletionItemResolutionInfo'),
|
||||
|
||||
+1
-1
@@ -1106,7 +1106,7 @@ class DartCompletionResolutionInfo
|
||||
/// The URIs to be imported if this completion is selected.
|
||||
final List<String> importUris;
|
||||
|
||||
/// The ElementLocation of the item being completed.
|
||||
/// The encoded ElementLocation2 of the item being completed.
|
||||
///
|
||||
/// This is used to provide documentation in the resolved response.
|
||||
final String? ref;
|
||||
|
||||
Reference in New Issue
Block a user