@@ -153,15 +153,20 @@ class InMemoryPackageIndex {
153153 }
154154
155155 // do text matching
156- final textResults = _searchText (packages, query.parsedQuery.text);
156+ final parsedQueryText = query.parsedQuery.text;
157+ final textResults = _searchText (
158+ packages,
159+ parsedQueryText,
160+ includeNameMatches: (query.offset ?? 0 ) == 0 ,
161+ );
157162
158163 // filter packages that doesn't match text query
159164 if (textResults != null ) {
160165 final keys = textResults.pkgScore.getKeys ();
161166 packages.removeWhere ((x) => ! keys.contains (x));
162167 }
163168
164- List < String > ? nameMatches;
169+ final nameMatches = textResults ? . nameMatches;
165170 List <PackageHit > packageHits;
166171 switch (query.effectiveOrder ?? SearchOrder .top) {
167172 case SearchOrder .top:
@@ -175,12 +180,6 @@ class InMemoryPackageIndex {
175180 /// multiplication outcomes.
176181 final overallScore = textResults.pkgScore
177182 .map ((key, value) => value * _adjustedOverallScores[key]! );
178- // If the search hits have an exact name match, we move it to the front of the result list.
179- final parsedQueryText = query.parsedQuery.text;
180- if (parsedQueryText != null &&
181- _documentsByName.containsKey (parsedQueryText)) {
182- nameMatches = < String > [parsedQueryText];
183- }
184183 packageHits = _rankWithValues (overallScore.getValues ());
185184 break ;
186185 case SearchOrder .text:
@@ -242,12 +241,16 @@ class InMemoryPackageIndex {
242241 }
243242 }
244243
245- _TextResults ? _searchText (Set <String > packages, String ? text) {
244+ _TextResults ? _searchText (
245+ Set <String > packages,
246+ String ? text, {
247+ required bool includeNameMatches,
248+ }) {
246249 final sw = Stopwatch ()..start ();
247250 if (text != null && text.isNotEmpty) {
248251 final words = splitForQuery (text);
249252 if (words.isEmpty) {
250- return _TextResults ( Score .empty (), {} );
253+ return _TextResults .empty ();
251254 }
252255
253256 bool aborted = false ;
@@ -261,6 +264,12 @@ class InMemoryPackageIndex {
261264 return aborted;
262265 }
263266
267+ Set <String >? nameMatches;
268+ if (includeNameMatches && _documentsByName.containsKey (text)) {
269+ nameMatches ?? = < String > {};
270+ nameMatches.add (text);
271+ }
272+
264273 // Multiple words are scored separately, and then the individual scores
265274 // are multiplied. We can use a package filter that is applied after each
266275 // word to reduce the scope of the later words based on the previous results.
@@ -272,6 +281,11 @@ class InMemoryPackageIndex {
272281 for (final word in words) {
273282 final nameScore =
274283 _packageNameIndex.searchWord (word, packages: wordScopedPackages);
284+ if (includeNameMatches && _documentsByName.containsKey (word)) {
285+ nameMatches ?? = < String > {};
286+ nameMatches.add (word);
287+ }
288+
275289 final descr = _descrIndex
276290 .searchWords ([word], weight: 0.90 , limitToIds: wordScopedPackages);
277291 final readme = _readmeIndex
@@ -343,7 +357,11 @@ class InMemoryPackageIndex {
343357 score = Score (matched);
344358 }
345359
346- return _TextResults (score, topApiPages);
360+ return _TextResults (
361+ score,
362+ topApiPages,
363+ nameMatches: nameMatches? .toList (),
364+ );
347365 }
348366 return null ;
349367 }
@@ -423,8 +441,19 @@ class InMemoryPackageIndex {
423441class _TextResults {
424442 final Score pkgScore;
425443 final Map <String , List <MapEntry <String , double >>> topApiPages;
444+ final List <String >? nameMatches;
445+
446+ factory _TextResults .empty () => _TextResults (
447+ Score .empty (),
448+ {},
449+ nameMatches: null ,
450+ );
426451
427- _TextResults (this .pkgScore, this .topApiPages);
452+ _TextResults (
453+ this .pkgScore,
454+ this .topApiPages, {
455+ required this .nameMatches,
456+ });
428457}
429458
430459/// A simple (non-inverted) index designed for package name lookup.
0 commit comments