@@ -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 =
318- _packageNameIndex.searchWord (word, packages: 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:
@@ -520,27 +513,44 @@ class PackageNameIndex {
520513 package.replaceAll ('_' , '' ).toLowerCase ();
521514
522515 /// Search [text] and return the matching packages with scores.
516+ @visibleForTesting
523517 Score search (String text) {
524- return Score .multiply (splitForQuery (text).map (searchWord).toList ());
518+ IndexedScore ? score;
519+ for (final w in splitForQuery (text)) {
520+ final s = searchWord (w, filterOnNonZeros: score);
521+ if (score == null ) {
522+ score = s;
523+ } else {
524+ score.multiplyAllFrom (s);
525+ }
526+ }
527+ return score? .toScore () ?? Score .empty;
525528 }
526529
527- /// Search using the parsed [word] and return the match packages with scores.
528- Score searchWord (String word, {Set <String >? packages}) {
529- final pkgNamesToCheck = packages ?? _packageNames;
530- final values = < String , double > {};
530+ /// Search using the parsed [word] and return the matching packages with scores
531+ /// as a new [IndexedScore] instance.
532+ ///
533+ /// When [filterOnNonZeros] is present, only the indexes with an already
534+ /// non-zero value are evaluated.
535+ IndexedScore searchWord (
536+ String word, {
537+ IndexedScore ? filterOnNonZeros,
538+ }) {
539+ final scoreore = IndexedScore (_packageNames);
531540 final singularWord = word.length <= 3 || ! word.endsWith ('s' )
532541 ? word
533542 : word.substring (0 , word.length - 1 );
534543 final collapsedWord = _collapseName (singularWord);
535544 final parts =
536545 collapsedWord.length <= 3 ? [collapsedWord] : trigrams (collapsedWord);
537- for (final pkg in pkgNamesToCheck) {
538- final entry = _data[pkg];
539- if (entry == null ) {
546+ for (var i = 0 ; i < _data.length; i++ ) {
547+ if (filterOnNonZeros? .isNotPositive (i) ?? false ) {
540548 continue ;
541549 }
550+
551+ final entry = _data[i];
542552 if (entry.collapsed.contains (collapsedWord)) {
543- values[pkg] = 1.0 ;
553+ scoreore. setValue (i, 1.0 ) ;
544554 continue ;
545555 }
546556 var matched = 0 ;
@@ -549,11 +559,15 @@ class PackageNameIndex {
549559 matched++ ;
550560 }
551561 }
562+ // making sure that match score is minimum 0.5
552563 if (matched > 0 ) {
553- values[pkg] = matched / parts.length;
564+ final v = matched / parts.length;
565+ if (v >= 0.5 ) {
566+ scoreore.setValue (i, v);
567+ }
554568 }
555569 }
556- return Score (values). removeLowValues (fraction : 0.5 , minValue : 0.5 ) ;
570+ return scoreore ;
557571 }
558572}
559573
0 commit comments