| // 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. | |
| import 'dart:async'; | |
| import 'package:analysis_server/src/protocol_server.dart' | |
| show SearchResult, newSearchResult_fromMatch; | |
| 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'; | |
| /** | |
| * A computer for `search.findElementReferences` request results. | |
| */ | |
| class ElementReferencesComputer { | |
| final SearchEngine searchEngine; | |
| ElementReferencesComputer(this.searchEngine); | |
| /** | |
| * Computes [SearchResult]s for [element] references. | |
| */ | |
| Future<List<SearchResult>> compute( | |
| Element element, bool withPotential) async { | |
| List<SearchResult> results = <SearchResult>[]; | |
| // Add element references. | |
| results.addAll(await _findElementsReferences(element)); | |
| // Add potential references. | |
| if (withPotential && _isMemberElement(element)) { | |
| String name = element.displayName; | |
| List<SearchMatch> matches = | |
| await searchEngine.searchMemberReferences(name); | |
| matches = SearchMatch.withNotNullElement(matches); | |
| results.addAll(matches.where((match) => !match.isResolved).map(toResult)); | |
| } | |
| return results; | |
| } | |
| /** | |
| * Returns a [Future] completing with a [List] of references to [element] or | |
| * to the corresponding hierarchy [Element]s. | |
| */ | |
| Future<List<SearchResult>> _findElementsReferences(Element element) async { | |
| List<SearchResult> allResults = <SearchResult>[]; | |
| Iterable<Element> refElements = await _getRefElements(element); | |
| for (Element refElement in refElements) { | |
| List<SearchResult> elementResults = | |
| await _findSingleElementReferences(refElement); | |
| allResults.addAll(elementResults); | |
| } | |
| return allResults; | |
| } | |
| /** | |
| * Returns a [Future] completing with a [List] of references to [element]. | |
| */ | |
| Future<List<SearchResult>> _findSingleElementReferences( | |
| Element element) async { | |
| List<SearchMatch> matches = await searchEngine.searchReferences(element); | |
| matches = SearchMatch.withNotNullElement(matches); | |
| return matches.map(toResult).toList(); | |
| } | |
| /** | |
| * Returns a [Future] completing with [Element]s to search references to. | |
| * | |
| * If a [ClassMemberElement] or a named [ParameterElement] is given, each | |
| * corresponding [Element] in the hierarchy is returned. | |
| * | |
| * Otherwise, only references to [element] should be searched. | |
| */ | |
| Future<Iterable<Element>> _getRefElements(Element element) { | |
| if (element is ParameterElement && element.isNamed) { | |
| return getHierarchyNamedParameters(searchEngine, element); | |
| } | |
| if (element is ClassMemberElement) { | |
| return getHierarchyMembers(searchEngine, element); | |
| } | |
| return new Future.value([element]); | |
| } | |
| static SearchResult toResult(SearchMatch match) { | |
| return newSearchResult_fromMatch(match); | |
| } | |
| static bool _isMemberElement(Element element) { | |
| if (element is ConstructorElement) { | |
| return false; | |
| } | |
| return element.enclosingElement is ClassElement; | |
| } | |
| } |