Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(797)

Unified Diff: pkg/analysis_services/lib/search/hierarchy.dart

Issue 395623006: Add hierarchy utils and use them in search. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analysis_services/lib/search/hierarchy.dart
diff --git a/pkg/analysis_services/lib/search/hierarchy.dart b/pkg/analysis_services/lib/search/hierarchy.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8612912902bce40f4b07ac6a4b741d60ff74a274
--- /dev/null
+++ b/pkg/analysis_services/lib/search/hierarchy.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2014, 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.
+
+// This code was auto-generated, is not intended to be edited, and is subject to
+// significant change. Please see the README file for more information.
+
+library services.hierarchy;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'package:analysis_services/search/search_engine.dart';
+import 'package:analyzer/src/generated/element.dart';
+
+
+/**
+ * Returns direct non-synthetic children of the given [ClassElement].
+ *
+ * Includes: fields, accessors and methods.
+ * Excludes: constructors and synthetic elements.
+ */
+List<Element> getClassMembers(ClassElement clazz, [String name]) {
+ List<Element> members = <Element>[];
+ clazz.accept(new _ElementVisitorAdapter((Element element) {
Brian Wilkerson 2014/07/15 19:56:16 If you used 'visitChildren' instead of 'accept' yo
scheglov 2014/07/15 20:30:12 Done.
+ if (element == clazz) {
+ return true;
+ }
+ if (element.isSynthetic) {
+ return false;
+ }
+ if (element is ConstructorElement) {
+ return false;
+ }
+ if (name != null && element.displayName != name) {
+ return false;
+ }
+ if (element is ExecutableElement) {
+ members.add(element);
+ }
+ if (element is FieldElement) {
+ members.add(element);
+ }
+ return false;
+ }));
+ return members;
+}
+
+
+/**
+ * Returns direct children of [parent].
+ */
+List<Element> getChildren(Element parent, [String name]) {
+ List<Element> children = <Element>[];
+ parent.accept(new _ElementVisitorAdapter((Element element) {
Brian Wilkerson 2014/07/15 19:56:16 If you used 'visitChildren' instead of 'accept' yo
scheglov 2014/07/15 20:30:12 Done.
+ if (element == parent) {
+ return true;
+ } else {
+ if (name == null || element.displayName == name) {
+ children.add(element);
+ }
+ return false;
+ }
+ }));
+ return children;
+}
+
+
+/**
+ * Returns a [Set] with direct subclasses of [seed].
+ */
+Future<Set<ClassElement>> getDirectSubClasses(SearchEngine searchEngine,
+ ClassElement seed) {
+ return searchEngine.searchSubtypes(seed).then((List<SearchMatch> matches) {
+ Set<ClassElement> subClasses = new HashSet<ClassElement>();
+ for (SearchMatch match in matches) {
+ ClassElement subClass = match.element;
+ if (subClass.context == seed.context) {
+ subClasses.add(subClass);
+ }
+ }
+ return subClasses;
+ });
+}
+
+
+/**
+ * Returns a [Set] with all direct and indirect subclasses of [seed].
+ */
+Future<Set<ClassElement>> getSubClasses(SearchEngine searchEngine,
+ ClassElement seed) {
+ Set<ClassElement> subs = new HashSet<ClassElement>();
+ // prepare queue
+ List<ClassElement> queue = new List<ClassElement>();
+ queue.add(seed);
+ // schedule subclasss search
+ addSubClasses() {
+ // queue is empty, done
+ if (queue.isEmpty) {
+ subs.remove(seed);
+ return subs;
+ }
+ // add direct subclasses of the next class
+ while (true) {
+ ClassElement clazz = queue.removeLast();
+ if (subs.add(clazz)) {
+ return getDirectSubClasses(searchEngine, clazz).then((directSubs) {
+ queue.addAll(directSubs);
+ return new Future(addSubClasses);
+ });
+ }
+ }
+ }
+ return new Future(addSubClasses);
+}
+
+
+/**
+ * @return all implementations of the given {@link ClassMemberElement} is its superclasses and
+ * their subclasses.
+ */
+Future<Set<ClassMemberElement>> getHierarchyMembers(SearchEngine searchEngine,
+ ClassMemberElement member) {
+ Set<ClassMemberElement> result = new HashSet<ClassMemberElement>();
+ // constructor
+ if (member is ConstructorElement) {
+ result.add(member);
+ return new Future.value(result);
+ }
+ // method, field, etc
+ String name = member.displayName;
+ ClassElement memberClass = member.enclosingElement;
+ List<Future> futures = <Future>[];
+ Set<ClassElement> searchClasses = getSuperClasses(memberClass);
+ searchClasses.add(memberClass);
+ for (ClassElement superClass in searchClasses) {
+ // ignore if super- class does not declare member
+ if (getClassMembers(superClass, name).isEmpty) {
+ continue;
+ }
+ // check all sub- classes
+ var subClassFuture = getSubClasses(searchEngine, superClass);
+ var membersFuture = subClassFuture.then((Set<ClassElement> subClasses) {
+ subClasses.add(superClass);
+ for (ClassElement subClass in subClasses) {
+ List<Element> subClassMembers = getChildren(subClass, name);
+ for (Element member in subClassMembers) {
+ if (member is ClassMemberElement) {
+ result.add(member);
+ }
+ }
+ }
+ });
+ futures.add(membersFuture);
+ }
+ return Future.wait(futures).then((_) {
+ return result;
+ });
+}
+
+
+/**
+ * Returns a [Set] with all direct and indirect superclasses of [seed].
+ */
+Set<ClassElement> getSuperClasses(ClassElement seed) {
+ Set<ClassElement> result = new HashSet<ClassElement>();
+ // prepare queue
+ List<ClassElement> queue = new List<ClassElement>();
+ queue.add(seed);
+ // process queue
+ while (!queue.isEmpty) {
+ ClassElement current = queue.removeLast();
+ // add if not checked already
+ if (!result.add(current)) {
+ continue;
+ }
+ // append supertype
+ {
+ InterfaceType superType = current.supertype;
+ if (superType != null) {
+ queue.add(superType.element);
+ }
+ }
+ // append interfaces
+ for (InterfaceType intf in current.interfaces) {
+ queue.add(intf.element);
+ }
+ }
+ // we don't need "seed" itself
+ result.remove(seed);
+ return result;
+}
+
+
+typedef bool ElementProcessor(Element element);
+
+/**
+ * A [GeneralizingElementVisitor] that adapter for [ElementProcessor].
+ */
+class _ElementVisitorAdapter extends GeneralizingElementVisitor {
+ final ElementProcessor processor;
+
+ _ElementVisitorAdapter(this.processor);
+
+ @override
+ void visitElement(Element element) {
+ bool visitChildren = processor(element);
+ if (visitChildren) {
+ super.visitElement(element);
+ }
+ }
+}
« no previous file with comments | « pkg/analysis_services/lib/index/local_memory_index.dart ('k') | pkg/analysis_services/lib/search/search_engine.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698