@@ -311,32 +311,28 @@ class InMemoryPackageIndex {
311311 // We cannot update the main `packages` variable yet, as the dartdoc API
312312 // symbols are added on top of the core results, and `packages` is used
313313 // there too.
314- final coreScores = < Score > [];
315- var wordScopedPackages = packages;
314+ final coreScores = IndexedScore (_packageNameIndex._packageNames);
315+ for (var i = 0 ; i < _documents.length; i++ ) {
316+ if (packages.contains (_documents[i].package)) {
317+ coreScores.setValue (i, 1.0 );
318+ }
319+ }
320+
316321 for (final word in words) {
317- final nameScore = _packageNameIndex.searchWord (word,
318- filterOnPackages: wordScopedPackages);
319322 if (includeNameMatches && _documentsByName.containsKey (word)) {
320323 nameMatches ?? = < String > {};
321324 nameMatches.add (word);
322325 }
323326
324- final descr = _descrIndex
325- .searchWords ([word], weight: 0.90 , limitToIds: wordScopedPackages);
326- final readme = _readmeIndex
327- .searchWords ([word], weight: 0.75 , limitToIds: wordScopedPackages);
328- final score = Score .max ([nameScore, descr, readme]);
329- coreScores.add (score);
330- // don't update if the query is single-word
331- if (words.length > 1 ) {
332- wordScopedPackages = score.keys.toSet ();
333- if (wordScopedPackages.isEmpty) {
334- break ;
335- }
336- }
327+ final wordScore =
328+ _packageNameIndex.searchWord (word, filterOnNonZeros: coreScores);
329+ _descrIndex.searchAndAccumulate (word,
330+ weight: 0.90 .toDouble (), score: wordScore);
331+ _readmeIndex.searchAndAccumulate (word,
332+ weight: 0.75 .toDouble (), score: wordScore);
333+ coreScores.multiplyAllFrom (wordScore);
337334 }
338-
339- final core = Score .multiply (coreScores);
335+ final core = coreScores.toScore ();
340336
341337 var symbolPages = Score .empty;
342338 if (! checkAborted ()) {
@@ -502,16 +498,13 @@ class _TextResults {
502498@visibleForTesting
503499class PackageNameIndex {
504500 final List <String > _packageNames;
505- late final Map < String , _PkgNameData > _data;
501+ late final List < _PkgNameData > _data;
506502
507503 PackageNameIndex (this ._packageNames) {
508- _data = Map . fromEntries ( _packageNames.map ((package) {
504+ _data = _packageNames.map ((package) {
509505 final collapsed = _collapseName (package);
510- return MapEntry (
511- package,
512- _PkgNameData (collapsed, trigrams (collapsed).toSet ()),
513- );
514- }));
506+ return _PkgNameData (collapsed, trigrams (collapsed).toSet ());
507+ }).toList ();
515508 }
516509
517510 /// Maps package name to a reduced form of the name:
@@ -522,45 +515,43 @@ class PackageNameIndex {
522515 /// Search [text] and return the matching packages with scores.
523516 @visibleForTesting
524517 Score search (String text) {
525- Score ? score;
518+ IndexedScore ? score;
526519 for (final w in splitForQuery (text)) {
527- final s = searchWord (w, filterOnPackages : score? .keys );
520+ final s = searchWord (w, filterOnNonZeros : score);
528521 if (score == null ) {
529522 score = s;
530523 } else {
531- // Note: on one hand, it is inefficient to multiply the [Score] on each
532- // iteration. However, (1) this is only happening in test, (2) it may be
533- // better for the next iteration to work on a more limited `filterOnPackages`,
534- // and (3) it will be updated to a more efficient in-place update (#8225).
535- score = Score .multiply ([score, s]);
524+ score.multiplyAllFrom (s);
536525 }
537526 }
538- return score ?? Score .empty;
527+ return score? .toScore () ?? Score .empty;
528+
539529 }
540530
541531 /// Search using the parsed [word] and return the matching packages with scores
542- /// as a new [Score ] instance.
532+ /// as a new [IndexedScore ] instance.
543533 ///
544- /// When [filterOnPackages] is present, only the names present are evaluated.
545- Score searchWord (
534+ /// When [filterOnNonZeros] is present, only the indexes with an already
535+ /// non-zero value are evaluated.
536+ IndexedScore searchWord (
546537 String word, {
547- Iterable < String > ? filterOnPackages ,
538+ IndexedScore ? filterOnNonZeros ,
548539 }) {
549- final pkgNamesToCheck = filterOnPackages ?? _packageNames;
550- final values = < String , double > {};
540+ final score = IndexedScore (_packageNames);
551541 final singularWord = word.length <= 3 || ! word.endsWith ('s' )
552542 ? word
553543 : word.substring (0 , word.length - 1 );
554544 final collapsedWord = _collapseName (singularWord);
555545 final parts =
556546 collapsedWord.length <= 3 ? [collapsedWord] : trigrams (collapsedWord);
557- for (final pkg in pkgNamesToCheck) {
558- final entry = _data[pkg];
559- if (entry == null ) {
547+ for (var i = 0 ; i < _data.length; i++ ) {
548+ if (filterOnNonZeros? .isNotPositive (i) ?? false ) {
560549 continue ;
561550 }
551+
552+ final entry = _data[i];
562553 if (entry.collapsed.contains (collapsedWord)) {
563- values[pkg] = 1.0 ;
554+ score. setValue (i, 1.0 ) ;
564555 continue ;
565556 }
566557 var matched = 0 ;
@@ -574,11 +565,11 @@ class PackageNameIndex {
574565 if (matched > 0 ) {
575566 final v = matched / parts.length;
576567 if (v >= 0.5 ) {
577- values[pkg] = v ;
568+ score. setValue (i, v) ;
578569 }
579570 }
580571 }
581- return Score (values) ;
572+ return score ;
582573 }
583574}
584575
0 commit comments