| OLD | NEW | 
|    1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file |    1 // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 
|    2 // for details. All rights reserved. Use of this source code is governed by a |    2 // for details. All rights reserved. Use of this source code is governed by a | 
|    3 // BSD-style license that can be found in the LICENSE file. |    3 // BSD-style license that can be found in the LICENSE file. | 
|    4  |    4  | 
|    5 library services.search_engine; |    5 library services.search_engine; | 
|    6  |    6  | 
|    7 import 'dart:async'; |    7 import 'dart:async'; | 
|    8  |    8  | 
|    9 import 'package:analyzer/dart/element/element.dart'; |    9 import 'package:analyzer/dart/element/element.dart'; | 
|   10 import 'package:analyzer/dart/element/visitor.dart'; |  | 
|   11 import 'package:analyzer/src/dart/element/element.dart'; |  | 
|   12 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext; |  | 
|   13 import 'package:analyzer/src/generated/source.dart'; |   10 import 'package:analyzer/src/generated/source.dart'; | 
|   14 import 'package:analyzer/src/generated/utilities_general.dart'; |  | 
|   15  |   11  | 
|   16 /** |   12 /** | 
|   17  * Instances of the enum [MatchKind] represent the kind of reference that was |   13  * Instances of the enum [MatchKind] represent the kind of reference that was | 
|   18  * found when a match represents a reference to an element. |   14  * found when a match represents a reference to an element. | 
|   19  */ |   15  */ | 
|   20 class MatchKind { |   16 class MatchKind { | 
|   21   /** |   17   /** | 
|   22    * A declaration of an element. |   18    * A declaration of an element. | 
|   23    */ |   19    */ | 
|   24   static const MatchKind DECLARATION = const MatchKind('DECLARATION'); |   20   static const MatchKind DECLARATION = const MatchKind('DECLARATION'); | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  103    * [pattern] the regular expression used to match the names of the |   99    * [pattern] the regular expression used to match the names of the | 
|  104    *    declarations to be found. |  100    *    declarations to be found. | 
|  105    */ |  101    */ | 
|  106   Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern); |  102   Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern); | 
|  107 } |  103 } | 
|  108  |  104  | 
|  109 /** |  105 /** | 
|  110  * Instances of the class [SearchMatch] represent a match found by |  106  * Instances of the class [SearchMatch] represent a match found by | 
|  111  * [SearchEngine]. |  107  * [SearchEngine]. | 
|  112  */ |  108  */ | 
|  113 class SearchMatch { |  109 abstract class SearchMatch { | 
|  114   /** |  | 
|  115    * The [AnalysisContext] containing the match. |  | 
|  116    */ |  | 
|  117   final AnalysisContext context; |  | 
|  118  |  | 
|  119   /** |  | 
|  120    * The URI of the source of the library containing the match. |  | 
|  121    */ |  | 
|  122   final String libraryUri; |  | 
|  123  |  | 
|  124   /** |  | 
|  125    * The URI of the source of the unit containing the match. |  | 
|  126    */ |  | 
|  127   final String unitUri; |  | 
|  128  |  | 
|  129   /** |  | 
|  130    * The kind of the match. |  | 
|  131    */ |  | 
|  132   final MatchKind kind; |  | 
|  133  |  | 
|  134   /** |  | 
|  135    * The source range that was matched. |  | 
|  136    */ |  | 
|  137   final SourceRange sourceRange; |  | 
|  138  |  | 
|  139   /** |  | 
|  140    * Is `true` if the match is a resolved reference to some [Element]. |  | 
|  141    */ |  | 
|  142   final bool isResolved; |  | 
|  143  |  | 
|  144   /** |  | 
|  145    * Is `true` if field or method access is done using qualifier. |  | 
|  146    */ |  | 
|  147   final bool isQualified; |  | 
|  148  |  | 
|  149   Source _librarySource; |  | 
|  150   Source _unitSource; |  | 
|  151   LibraryElement _libraryElement; |  | 
|  152   Element _element; |  | 
|  153  |  | 
|  154   SearchMatch(this.context, this.libraryUri, this.unitUri, this.kind, |  | 
|  155       this.sourceRange, this.isResolved, this.isQualified); |  | 
|  156  |  | 
|  157   /** |  110   /** | 
|  158    * Return the [Element] containing the match. Can return `null` if the unit |  111    * Return the [Element] containing the match. Can return `null` if the unit | 
|  159    * does not exist, or its element was invalidated, or the element cannot be |  112    * does not exist, or its element was invalidated, or the element cannot be | 
|  160    * found, etc. |  113    * found, etc. | 
|  161    */ |  114    */ | 
|  162   Element get element { |  115   Element get element; | 
|  163     if (_element == null) { |  | 
|  164       CompilationUnitElement unitElement = |  | 
|  165           context.getCompilationUnitElement(unitSource, librarySource); |  | 
|  166       if (unitElement != null) { |  | 
|  167         _ContainingElementFinder finder = |  | 
|  168             new _ContainingElementFinder(sourceRange.offset); |  | 
|  169         unitElement.accept(finder); |  | 
|  170         _element = finder.containingElement; |  | 
|  171       } |  | 
|  172     } |  | 
|  173     return _element; |  | 
|  174   } |  | 
|  175  |  116  | 
|  176   /** |  117   /** | 
|  177    * The absolute path of the file containing the match. |  118    * The absolute path of the file containing the match. | 
|  178    */ |  119    */ | 
|  179   String get file => unitSource.fullName; |  120   String get file; | 
|  180  |  121  | 
|  181   @override |  122   /** | 
|  182   int get hashCode { |  123    * Is `true` if field or method access is done using qualifier. | 
|  183     return JenkinsSmiHash.hash4(libraryUri.hashCode, unitUri.hashCode, |  124    */ | 
|  184         kind.hashCode, sourceRange.hashCode); |  125   bool get isQualified; | 
|  185   } |  126  | 
 |  127   /** | 
 |  128    * Is `true` if the match is a resolved reference to some [Element]. | 
 |  129    */ | 
 |  130   bool get isResolved; | 
 |  131  | 
 |  132   /** | 
 |  133    * The kind of the match. | 
 |  134    */ | 
 |  135   MatchKind get kind; | 
|  186  |  136  | 
|  187   /** |  137   /** | 
|  188    * Return the [LibraryElement] for the [libraryUri] in the [context]. |  138    * Return the [LibraryElement] for the [libraryUri] in the [context]. | 
|  189    */ |  139    */ | 
|  190   LibraryElement get libraryElement { |  140   LibraryElement get libraryElement; | 
|  191     _libraryElement ??= context.getLibraryElement(librarySource); |  | 
|  192     return _libraryElement; |  | 
|  193   } |  | 
|  194  |  141  | 
|  195   /** |  142   /** | 
|  196    * The library [Source] of the reference. |  143    * The library [Source] of the reference. | 
|  197    */ |  144    */ | 
|  198   Source get librarySource { |  145   Source get librarySource; | 
|  199     _librarySource ??= context.sourceFactory.forUri(libraryUri); |  146  | 
|  200     return _librarySource; |  147   /** | 
|  201   } |  148    * The source range that was matched. | 
 |  149    */ | 
 |  150   SourceRange get sourceRange; | 
|  202  |  151  | 
|  203   /** |  152   /** | 
|  204    * The unit [Source] of the reference. |  153    * The unit [Source] of the reference. | 
|  205    */ |  154    */ | 
|  206   Source get unitSource { |  155   Source get unitSource; | 
|  207     _unitSource ??= context.sourceFactory.forUri(unitUri); |  | 
|  208     return _unitSource; |  | 
|  209   } |  | 
|  210  |  | 
|  211   @override |  | 
|  212   bool operator ==(Object object) { |  | 
|  213     if (identical(object, this)) { |  | 
|  214       return true; |  | 
|  215     } |  | 
|  216     if (object is SearchMatch) { |  | 
|  217       return kind == object.kind && |  | 
|  218           libraryUri == object.libraryUri && |  | 
|  219           unitUri == object.unitUri && |  | 
|  220           isResolved == object.isResolved && |  | 
|  221           isQualified == object.isQualified && |  | 
|  222           sourceRange == object.sourceRange; |  | 
|  223     } |  | 
|  224     return false; |  | 
|  225   } |  | 
|  226  |  | 
|  227   @override |  | 
|  228   String toString() { |  | 
|  229     StringBuffer buffer = new StringBuffer(); |  | 
|  230     buffer.write("SearchMatch(kind="); |  | 
|  231     buffer.write(kind); |  | 
|  232     buffer.write(", libraryUri="); |  | 
|  233     buffer.write(libraryUri); |  | 
|  234     buffer.write(", unitUri="); |  | 
|  235     buffer.write(unitUri); |  | 
|  236     buffer.write(", range="); |  | 
|  237     buffer.write(sourceRange); |  | 
|  238     buffer.write(", isResolved="); |  | 
|  239     buffer.write(isResolved); |  | 
|  240     buffer.write(", isQualified="); |  | 
|  241     buffer.write(isQualified); |  | 
|  242     buffer.write(")"); |  | 
|  243     return buffer.toString(); |  | 
|  244   } |  | 
|  245  |  156  | 
|  246   /** |  157   /** | 
|  247    * Return elements of [matches] which has not-null elements. |  158    * Return elements of [matches] which has not-null elements. | 
|  248    * |  159    * | 
|  249    * When [SearchMatch.element] is not `null` we cache its value, so it cannot |  160    * When [SearchMatch.element] is not `null` we cache its value, so it cannot | 
|  250    * become `null` later. |  161    * become `null` later. | 
|  251    */ |  162    */ | 
|  252   static List<SearchMatch> withNotNullElement(List<SearchMatch> matches) { |  163   static List<SearchMatch> withNotNullElement(List<SearchMatch> matches) { | 
|  253     return matches.where((match) => match.element != null).toList(); |  164     return matches.where((match) => match.element != null).toList(); | 
|  254   } |  165   } | 
|  255 } |  166 } | 
|  256  |  | 
|  257 /** |  | 
|  258  * A visitor that finds the deep-most [Element] that contains the [offset]. |  | 
|  259  */ |  | 
|  260 class _ContainingElementFinder extends GeneralizingElementVisitor { |  | 
|  261   final int offset; |  | 
|  262   Element containingElement; |  | 
|  263  |  | 
|  264   _ContainingElementFinder(this.offset); |  | 
|  265  |  | 
|  266   visitElement(Element element) { |  | 
|  267     if (element is ElementImpl) { |  | 
|  268       if (element.codeOffset != null && |  | 
|  269           element.codeOffset <= offset && |  | 
|  270           offset <= element.codeOffset + element.codeLength) { |  | 
|  271         containingElement = element; |  | 
|  272         super.visitElement(element); |  | 
|  273       } |  | 
|  274     } |  | 
|  275   } |  | 
|  276 } |  | 
| OLD | NEW |