| OLD | NEW |
| 1 /** | 1 /** |
| 2 * A library for searching and filtering documentation. | 2 * A library for searching and filtering documentation. |
| 3 * | 3 * |
| 4 * Given a search query, a set of ranked results is created to determine the | 4 * Given a search query, a set of ranked results is created to determine the |
| 5 * best member to match that query. Priority is given in the following order: | 5 * best member to match that query. Priority is given in the following order: |
| 6 * library, class, typedef, and class member or top-level library member. | 6 * library, class, typedef, and class member or top-level library member. |
| 7 * Results with matches in the last section of their qualified names are | 7 * Results with matches in the last section of their qualified names are |
| 8 * given a higher rank than those with matches in inner members of the | 8 * given a higher rank than those with matches in inner members of the |
| 9 * qualified name. | 9 * qualified name. |
| 10 */ | 10 */ |
| 11 library search; | 11 library search; |
| 12 | 12 |
| 13 import 'dart:async'; |
| 14 import 'package:web_ui/web_ui.dart'; |
| 15 |
| 13 /** Search Index */ | 16 /** Search Index */ |
| 14 Map<String, String> index = {}; | 17 Map<String, String> index = {}; |
| 15 | 18 |
| 19 /** Search query. */ |
| 20 @observable String searchQuery = ""; |
| 21 |
| 16 class SearchResult implements Comparable { | 22 class SearchResult implements Comparable { |
| 17 | 23 |
| 18 /** Qualified name of this search result references. */ | 24 /** Qualified name of this search result references. */ |
| 19 String element; | 25 String element; |
| 20 | 26 |
| 21 /** This element's member type. */ | 27 /** This element's member type. */ |
| 22 String type; | 28 String type; |
| 23 | 29 |
| 24 /** Score of the search result match. Higher is better. */ | 30 /** Score of the search result match. Higher is better. */ |
| 25 int score; | 31 int score; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 48 'constructor' : 4 | 54 'constructor' : 4 |
| 49 }; | 55 }; |
| 50 | 56 |
| 51 /** | 57 /** |
| 52 * Returns a list of up to [maxResults] number of [SearchResult]s based off the | 58 * Returns a list of up to [maxResults] number of [SearchResult]s based off the |
| 53 * searchQuery. | 59 * searchQuery. |
| 54 * | 60 * |
| 55 * A score is given to each potential search result based off how likely it is | 61 * A score is given to each potential search result based off how likely it is |
| 56 * the appropriate qualified name to return for the search query. | 62 * the appropriate qualified name to return for the search query. |
| 57 */ | 63 */ |
| 58 List<SearchResult> lookupSearchResults(String searchQuery, int maxResults) { | 64 List<SearchResult> lookupSearchResults(String query, int maxResults) { |
| 59 | 65 |
| 66 var stopwatch = new Stopwatch()..start(); |
| 67 |
| 60 var scoredResults = <SearchResult>[]; | 68 var scoredResults = <SearchResult>[]; |
| 61 var resultSet = new Set<String>(); | 69 var resultSet = new Set<String>(); |
| 62 var queryList = searchQuery.trim().toLowerCase().split(' '); | 70 var queryList = query.trim().toLowerCase().split(' '); |
| 63 queryList.forEach((q) => resultSet.addAll(index.keys.where((e) => | 71 queryList.forEach((q) => resultSet.addAll(index.keys.where((e) => |
| 64 e.toLowerCase().contains(q)))); | 72 e.toLowerCase().contains(q)))); |
| 65 | 73 |
| 66 for (var r in resultSet) { | 74 for (var r in resultSet) { |
| 75 /// If it is taking too long to compute the search results, time out and |
| 76 /// return an empty list of results. |
| 77 if (stopwatch.elapsedMilliseconds > 500) { |
| 78 return []; |
| 79 } |
| 67 int score = 0; | 80 int score = 0; |
| 68 var lowerCaseResult = r.toLowerCase(); | 81 var lowerCaseResult = r.toLowerCase(); |
| 69 var type = index[r]; | 82 var type = index[r]; |
| 70 | 83 |
| 71 var splitDotQueries = []; | 84 var splitDotQueries = []; |
| 72 // If the search was for a named constructor (Map.fromIterable), give it a | 85 // If the search was for a named constructor (Map.fromIterable), give it a |
| 73 // score boost of 200. | 86 // score boost of 200. |
| 74 queryList.forEach((q) { | 87 queryList.forEach((q) { |
| 75 if (q.contains('.') && lowerCaseResult.endsWith(q)) { | 88 if (q.contains('.') && lowerCaseResult.endsWith(q)) { |
| 76 score += 100; | 89 score += 100; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 } | 129 } |
| 117 | 130 |
| 118 // If the result item is part of the dart library, give it a small boost. | 131 // If the result item is part of the dart library, give it a small boost. |
| 119 if (qualifiedNameParts.first == 'dart') { | 132 if (qualifiedNameParts.first == 'dart') { |
| 120 score += 50; | 133 score += 50; |
| 121 } | 134 } |
| 122 }); | 135 }); |
| 123 scoredResults.add(new SearchResult(r, type, score)); | 136 scoredResults.add(new SearchResult(r, type, score)); |
| 124 } | 137 } |
| 125 | 138 |
| 139 /// If it is taking too long to compute the search results, time out and |
| 140 /// return an empty list of results. |
| 141 if (stopwatch.elapsedMilliseconds > 500) { |
| 142 return []; |
| 143 } |
| 126 scoredResults.sort(); | 144 scoredResults.sort(); |
| 127 updatePositions(scoredResults); | 145 updatePositions(scoredResults); |
| 128 if (scoredResults.length > maxResults) { | 146 if (scoredResults.length > maxResults) { |
| 129 return scoredResults.take(maxResults).toList(); | 147 return scoredResults.take(maxResults).toList(); |
| 130 } else { | 148 } else { |
| 131 return scoredResults; | 149 return scoredResults; |
| 132 } | 150 } |
| 133 } | 151 } |
| 134 | 152 |
| 135 void updatePositions(List<SearchResult> list) { | 153 void updatePositions(List<SearchResult> list) { |
| 136 for(int i = 0; i < list.length; i++) { | 154 for(int i = 0; i < list.length; i++) { |
| 137 list[i].position = i; | 155 list[i].position = i; |
| 138 } | 156 } |
| 139 } | 157 } |
| OLD | NEW |