Skip to content

Commit

Permalink
Elements. Migrate lib/src/search/type_hierarchy.dart
Browse files Browse the repository at this point in the history
Change-Id: Ic5ef83f214167da062f7dc1326361527235262bb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/399030
Reviewed-by: Phil Quitslund <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
  • Loading branch information
scheglov authored and Commit Queue committed Dec 7, 2024
1 parent 8aa8608 commit 1cca342
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 69 deletions.
1 change: 0 additions & 1 deletion pkg/analysis_server/analyzer_use_new_elements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ lib/src/lsp/handlers/handler_rename.dart
lib/src/operation/operation_analysis.dart
lib/src/protocol_server.dart
lib/src/search/element_references.dart
lib/src/search/type_hierarchy.dart
lib/src/services/correction/namespace.dart
lib/src/services/kythe/kythe_visitors.dart
lib/src/services/refactoring/agnostic/change_method_signature.dart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:analysis_server/protocol/protocol.dart' as protocol;
import 'package:analysis_server/protocol/protocol_generated.dart' as protocol;
import 'package:analysis_server/src/handler/legacy/legacy_handler.dart';
import 'package:analysis_server/src/search/type_hierarchy.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';

/// The handler for the `search.getTypeHierarchy` request.
class SearchGetTypeHierarchyHandler extends LegacyHandler {
Expand Down Expand Up @@ -36,7 +37,7 @@ class SearchGetTypeHierarchyHandler extends LegacyHandler {
}
// maybe supertype hierarchy only
if (params.superOnly == true) {
var computer = TypeHierarchyComputer(searchEngine, element);
var computer = TypeHierarchyComputer(searchEngine, element.asElement2!);
var items = computer.computeSuper();
var response = protocol.SearchGetTypeHierarchyResult(
hierarchyItems: items,
Expand All @@ -45,7 +46,7 @@ class SearchGetTypeHierarchyHandler extends LegacyHandler {
return;
}
// prepare type hierarchy
var computer = TypeHierarchyComputer(searchEngine, element);
var computer = TypeHierarchyComputer(searchEngine, element.asElement2!);
var items = await computer.compute();
var response = protocol.SearchGetTypeHierarchyResult(
hierarchyItems: items,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';

typedef StaticOptions =
Either3<bool, ImplementationOptions, ImplementationRegistrationOptions>;
Expand Down Expand Up @@ -68,7 +69,7 @@ class ImplementationHandler
return success([]);
}

var helper = TypeHierarchyComputerHelper.fromElement(element);
var helper = TypeHierarchyComputerHelper.fromElement(element.asElement2!);
var interfaceElement = helper.pivotClass;
if (interfaceElement == null) {
return success([]);
Expand All @@ -79,7 +80,7 @@ class ImplementationHandler
await performance.runAsync(
'appendAllSubtypes',
(performance) => server.searchEngine.appendAllSubtypes(
interfaceElement,
interfaceElement.asElement,
allSubtypes,
performance,
),
Expand All @@ -94,23 +95,32 @@ class ImplementationHandler
// Filter based on type, so when searching for members we don't
// include any intermediate classes that don't have
// implementations for the method.
? helper.findMemberElement(element)?.nonSynthetic
: element;
? helper.findMemberElement(element.asElement2)?.nonSynthetic2
: element.asElement2;
})
.nonNulls
.toSet()
.map((element) {
var unitElement =
element.thisOrAncestorOfType<CompilationUnitElement>();
if (unitElement == null) {
var firstFragment = element.firstFragment;
var libraryFragment = firstFragment.libraryFragment;
if (libraryFragment == null) {
return null;
}

var nameOffset = firstFragment.nameOffset2;
var name = firstFragment.name2;
if (nameOffset == null || name == null) {
return null;
}

return Location(
uri: uriConverter.toClientUri(unitElement.source.fullName),
uri: uriConverter.toClientUri(
libraryFragment.source.fullName,
),
range: toRange(
unitElement.lineInfo,
element.nameOffset,
element.nameLength,
libraryFragment.lineInfo,
nameOffset,
name.length,
),
);
})
Expand Down
103 changes: 51 additions & 52 deletions pkg/analysis_server/lib/src/search/type_hierarchy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,23 @@
import 'dart:collection';

import 'package:analysis_server/src/protocol_server.dart'
show TypeHierarchyItem, convertElement;
show TypeHierarchyItem, convertElement2;
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/utilities/extensions/element.dart';

/// A computer for a type hierarchy of an [Element].
/// A computer for a type hierarchy of an [Element2].
class TypeHierarchyComputer {
final SearchEngine _searchEngine;
final TypeHierarchyComputerHelper helper;

final List<TypeHierarchyItem> _items = <TypeHierarchyItem>[];
final List<InterfaceElement> _itemClassElements = [];
final Map<Element, TypeHierarchyItem> _elementItemMap =
HashMap<Element, TypeHierarchyItem>();
final List<InterfaceElement2> _itemClassElements = [];
final Map<Element2, TypeHierarchyItem> _elementItemMap =
HashMap<Element2, TypeHierarchyItem>();

TypeHierarchyComputer(this._searchEngine, Element pivotElement)
TypeHierarchyComputer(this._searchEngine, Element2 pivotElement)
: helper = TypeHierarchyComputerHelper.fromElement(pivotElement);

/// Returns the computed type hierarchy, maybe `null`.
Expand Down Expand Up @@ -50,39 +49,39 @@ class TypeHierarchyComputer {
Future<void> _createSubclasses(
TypeHierarchyItem item,
int itemId,
InterfaceElement classElement,
InterfaceElement2 classElement,
SearchEngineCache searchEngineCache,
) async {
var subElements = await getDirectSubClasses(
_searchEngine,
classElement.asElement2,
classElement,
searchEngineCache,
);
var subItemIds = <int>[];
for (var subElement in subElements) {
// check for recursion
var subItem = _elementItemMap[subElement.asElement];
var subItem = _elementItemMap[subElement];
if (subItem != null) {
var id = _items.indexOf(subItem);
item.subclasses.add(id);
continue;
}
// create a subclass item
var subMemberElement = helper.findMemberElement(subElement.asElement);
var subMemberElementDeclared = subMemberElement?.nonSynthetic;
var subMemberElement = helper.findMemberElement(subElement);
var subMemberElementDeclared = subMemberElement?.nonSynthetic2;
subItem = TypeHierarchyItem(
convertElement(subElement.asElement),
convertElement2(subElement),
memberElement:
subMemberElementDeclared != null
? convertElement(subMemberElementDeclared)
? convertElement2(subMemberElementDeclared)
: null,
superclass: itemId,
);
var subItemId = _items.length;
// remember
_elementItemMap[subElement.asElement] = subItem;
_elementItemMap[subElement] = subItem;
_items.add(subItem);
_itemClassElements.add(subElement.asElement);
_itemClassElements.add(subElement);
// add to hierarchy
item.subclasses.add(subItemId);
subItemIds.add(subItemId);
Expand All @@ -101,7 +100,7 @@ class TypeHierarchyComputer {
}

int _createSuperItem(
InterfaceElement classElement,
InterfaceElement2 classElement,
List<DartType>? typeArguments,
) {
// check for recursion
Expand All @@ -121,13 +120,13 @@ class TypeHierarchyComputer {
displayName = '${classElement.displayName}<$typeArgumentsStr>';
}
var memberElement = helper.findMemberElement(classElement);
var memberElementDeclared = memberElement?.nonSynthetic;
var memberElementDeclared = memberElement?.nonSynthetic2;
item = TypeHierarchyItem(
convertElement(classElement),
convertElement2(classElement),
displayName: displayName,
memberElement:
memberElementDeclared != null
? convertElement(memberElementDeclared)
? convertElement2(memberElementDeclared)
: null,
);
_elementItemMap[classElement] = item;
Expand All @@ -140,19 +139,19 @@ class TypeHierarchyComputer {
var superType = classElement.supertype;
if (superType != null) {
item.superclass = _createSuperItem(
superType.element,
superType.element3,
superType.typeArguments,
);
}
}
// mixins
for (var type in classElement.mixins) {
var id = _createSuperItem(type.element, type.typeArguments);
var id = _createSuperItem(type.element3, type.typeArguments);
item.mixins.add(id);
}
// interfaces
for (var type in classElement.interfaces) {
var id = _createSuperItem(type.element, type.typeArguments);
var id = _createSuperItem(type.element3, type.typeArguments);
item.interfaces.add(id);
}
// done
Expand All @@ -161,12 +160,12 @@ class TypeHierarchyComputer {
}

class TypeHierarchyComputerHelper {
final Element pivotElement;
final LibraryElement pivotLibrary;
final Element2 pivotElement;
final LibraryElement2 pivotLibrary;
final ElementKind pivotKind;
final String? pivotName;
final bool pivotFieldFinal;
final InterfaceElement? pivotClass;
final InterfaceElement2? pivotClass;

TypeHierarchyComputerHelper(
this.pivotElement,
Expand All @@ -177,85 +176,85 @@ class TypeHierarchyComputerHelper {
this.pivotClass,
);

factory TypeHierarchyComputerHelper.fromElement(Element pivotElement) {
factory TypeHierarchyComputerHelper.fromElement(Element2 pivotElement) {
// try to find enclosing ClassElement
Element? element = pivotElement;
Element2? element = pivotElement;
bool pivotFieldFinal = false;
if (pivotElement is FieldElement) {
if (pivotElement is FieldElement2) {
pivotFieldFinal = pivotElement.isFinal;
element = pivotElement.enclosingElement3;
element = pivotElement.enclosingElement2;
}
if (pivotElement is ExecutableElement) {
element = pivotElement.enclosingElement3;
if (pivotElement is ExecutableElement2) {
element = pivotElement.enclosingElement2;
}
InterfaceElement? pivotClass;
if (element is InterfaceElement) {
InterfaceElement2? pivotClass;
if (element is InterfaceElement2) {
pivotClass = element;
}

return TypeHierarchyComputerHelper(
pivotElement,
pivotElement.library!,
pivotElement.library2!,
pivotElement.kind,
pivotElement.name,
pivotElement.name3,
pivotFieldFinal,
pivotClass,
);
}

ExecutableElement? findMemberElement(InterfaceElement clazz) {
ExecutableElement2? findMemberElement(InterfaceElement2 clazz) {
// Members of extension types don't override anything.
// They redeclare, and resolved statically.
if (pivotClass is ExtensionTypeElement || clazz is ExtensionTypeElement) {
if (pivotClass is ExtensionTypeElement2 || clazz is ExtensionTypeElement2) {
return null;
}

var pivotName = this.pivotName;
if (pivotName == null) {
return null;
}
ExecutableElement? result;
ExecutableElement2? result;
// try to find in the class itself
if (pivotKind == ElementKind.METHOD) {
result = clazz.getMethod(pivotName);
result = clazz.getMethod2(pivotName);
} else if (pivotKind == ElementKind.GETTER) {
result = clazz.getGetter(pivotName);
result = clazz.getGetter2(pivotName);
} else if (pivotKind == ElementKind.SETTER) {
result = clazz.getSetter(pivotName);
result = clazz.getSetter2(pivotName);
} else if (pivotKind == ElementKind.FIELD) {
result = clazz.getGetter(pivotName);
result = clazz.getGetter2(pivotName);
if (result == null && !pivotFieldFinal) {
result = clazz.getSetter(pivotName);
result = clazz.getSetter2(pivotName);
}
}
if (result != null && result.isAccessibleIn(pivotLibrary)) {
if (result != null && result.isAccessibleIn2(pivotLibrary)) {
return result;
}
// try to find in the class mixin
for (var mixin in clazz.mixins.reversed) {
var mixinElement = mixin.element;
var mixinElement = mixin.element3;
if (pivotKind == ElementKind.METHOD) {
result = mixinElement.augmented.lookUpMethod(
result = mixinElement.lookUpMethod2(
name: pivotName,
library: pivotLibrary,
);
} else if (pivotKind == ElementKind.GETTER) {
result = mixinElement.augmented.lookUpGetter(
result = mixinElement.lookUpGetter2(
name: pivotName,
library: pivotLibrary,
);
} else if (pivotKind == ElementKind.SETTER) {
result = mixinElement.augmented.lookUpSetter(
result = mixinElement.lookUpSetter2(
name: pivotName,
library: pivotLibrary,
);
} else if (pivotKind == ElementKind.FIELD) {
result = mixinElement.augmented.lookUpGetter(
result = mixinElement.lookUpGetter2(
name: pivotName,
library: pivotLibrary,
);
if (result == null && !pivotFieldFinal) {
result = mixinElement.augmented.lookUpSetter(
result = mixinElement.lookUpSetter2(
name: pivotName,
library: pivotLibrary,
);
Expand Down
13 changes: 12 additions & 1 deletion pkg/analyzer/lib/dart/element/element2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1177,7 +1177,7 @@ abstract class InstanceElement2
///
/// The behavior of this method is defined by the Dart Language Specification
/// in section 17.18 Lookup.
PropertyAccessorElement2? lookUpGetter2({
GetterElement? lookUpGetter2({
required String name,
required LibraryElement2 library,
});
Expand All @@ -1192,6 +1192,17 @@ abstract class InstanceElement2
required String name,
required LibraryElement2 library,
});

/// Returns the element representing the setter that results from looking up
/// the given [name] in this class with respect to the given [library],
/// or `null` if the look up fails.
///
/// The behavior of this method is defined by the Dart Language Specification
/// in section 17.18 Lookup.
SetterElement? lookUpSetter2({
required String name,
required LibraryElement2 library,
});
}

/// The portion of an [InstanceElement2] contributed by a single declaration.
Expand Down
Loading

0 comments on commit 1cca342

Please sign in to comment.