3
3
// BSD-style license that can be found in the LICENSE file.
4
4
5
5
import 'dart:async' ;
6
- import 'dart:io' ;
7
6
import 'dart:math' as math;
8
7
9
8
import 'package:gcloud/service_scope.dart' as ss;
@@ -24,20 +23,19 @@ void registerPackageIndex(PackageIndex index) =>
24
23
ss.register (#packageIndexService, index);
25
24
26
25
class SimplePackageIndex implements PackageIndex {
27
- final bool enableApiIndex;
28
26
final Map <String , PackageDocument > _packages = < String , PackageDocument > {};
29
27
final Map <String , String > _normalizedPackageText = < String , String > {};
30
28
final TokenIndex _nameIndex = new TokenIndex (minLength: 2 );
31
29
final TokenIndex _descrIndex = new TokenIndex (minLength: 3 );
32
30
final TokenIndex _readmeIndex = new TokenIndex (minLength: 3 );
33
31
final TokenIndex _apiDocIndex = new TokenIndex (minLength: 3 );
34
32
final StringInternPool _internPool = new StringInternPool ();
33
+ final bool _apiSearchEnabled;
35
34
DateTime _lastUpdated;
36
35
bool _isReady = false ;
37
36
38
- SimplePackageIndex ({bool enableApiIndex})
39
- : this .enableApiIndex =
40
- enableApiIndex ?? Platform .environment['SEARCH_API_INDEX' ] == '1' ;
37
+ SimplePackageIndex ({bool apiSearchEnabled: false })
38
+ : _apiSearchEnabled = apiSearchEnabled;
41
39
42
40
@override
43
41
bool get isReady => _isReady;
@@ -74,17 +72,20 @@ class SimplePackageIndex implements PackageIndex {
74
72
@override
75
73
Future addPackage (PackageDocument document) async {
76
74
final PackageDocument doc = document.intern (_internPool.intern);
77
- await removePackage (doc.package);
78
- if (document.isDiscontinued == true ) return ; // isDiscontinued may be null
75
+
76
+ // isDiscontinued may be null
77
+ if (document.isDiscontinued == true ) {
78
+ await removePackage (doc.package);
79
+ return ;
80
+ }
81
+
79
82
_packages[doc.package] = doc;
80
83
_nameIndex.add (doc.package, doc.package);
81
84
_descrIndex.add (doc.package, doc.description);
82
85
_readmeIndex.add (doc.package, doc.readme);
83
- if (enableApiIndex) {
84
- for (ApiDocPage page in doc.apiDocPages ?? const []) {
85
- _apiDocIndex.add (
86
- _apiDocPageId (doc.package, page), page.symbols? .join (' ' ));
87
- }
86
+ for (ApiDocPage page in doc.apiDocPages ?? const []) {
87
+ _apiDocIndex.add (
88
+ _apiDocPageId (doc.package, page), page.symbols? .join (' ' ));
88
89
}
89
90
final String allText = [doc.package, doc.description, doc.readme]
90
91
.where ((s) => s != null )
@@ -179,7 +180,8 @@ class SimplePackageIndex implements PackageIndex {
179
180
}
180
181
181
182
// do text matching
182
- final Score textScore = _searchText (packages, query.parsedQuery.text);
183
+ final Score textScore = _searchText (packages, query.parsedQuery.text,
184
+ _apiSearchEnabled || query.parsedQuery.isApiEnabled);
183
185
184
186
// filter packages that doesn't match text query
185
187
if (textScore != null ) {
@@ -299,15 +301,16 @@ class SimplePackageIndex implements PackageIndex {
299
301
return new Score (values);
300
302
}
301
303
302
- Score _searchText (Set <String > packages, String text) {
304
+ Score _searchText (Set <String > packages, String text, bool isExperimental ) {
303
305
if (text != null && text.isNotEmpty) {
304
306
final List <String > words = splitForIndexing (text).toList ();
305
307
final int wordCount = words.length;
306
308
final List <Score > wordScores = words.map ((String word) {
307
309
final nameTokens = _nameIndex.lookupTokens (word);
308
310
final descrTokens = _descrIndex.lookupTokens (word);
309
311
final readmeTokens = _readmeIndex.lookupTokens (word);
310
- final apiDocTokens = _apiDocIndex.lookupTokens (word);
312
+ final apiDocTokens =
313
+ isExperimental ? _apiDocIndex.lookupTokens (word) : new TokenMatch ();
311
314
final maxTokenLength = [
312
315
nameTokens.maxLength,
313
316
descrTokens.maxLength,
@@ -326,15 +329,20 @@ class SimplePackageIndex implements PackageIndex {
326
329
final readme = new Score (_readmeIndex.scoreDocs (readmeTokens,
327
330
weight: 0.90 , wordCount: wordCount));
328
331
329
- final apiPages = new Score (_apiDocIndex.scoreDocs (apiDocTokens,
330
- weight: 0.80 , wordCount: wordCount));
331
- final apiPackages = < String , double > {};
332
- for (String key in apiPages.getKeys ()) {
333
- final pkg = _apiDocPkg (key);
334
- final value = apiPages[key];
335
- apiPackages[pkg] = math.max (value, apiPackages[pkg] ?? 0.0 );
332
+ Score apiScore;
333
+ if (isExperimental) {
334
+ final apiPages = new Score (_apiDocIndex.scoreDocs (apiDocTokens,
335
+ weight: 0.80 , wordCount: wordCount));
336
+ final apiPackages = < String , double > {};
337
+ for (String key in apiPages.getKeys ()) {
338
+ final pkg = _apiDocPkg (key);
339
+ final value = apiPages[key];
340
+ apiPackages[pkg] = math.max (value, apiPackages[pkg] ?? 0.0 );
341
+ }
342
+ apiScore = new Score (apiPackages);
343
+ } else {
344
+ apiScore = new Score ({});
336
345
}
337
- final apiScore = new Score (apiPackages);
338
346
339
347
return Score .max ([name, descr, readme, apiScore]).removeLowValues (
340
348
fraction: 0.01 , minValue: 0.001 );
@@ -528,6 +536,7 @@ class TokenMatch {
528
536
}
529
537
530
538
class TokenIndex {
539
+ final Map <String , String > _textHashes = < String , String > {};
531
540
final Map <String , Set <String >> _inverseIds = < String , Set <String >> {};
532
541
final Map <String , double > _docSizes = < String , double > {};
533
542
final int _minLength;
@@ -541,17 +550,28 @@ class TokenIndex {
541
550
542
551
void add (String id, String text) {
543
552
final Set <String > tokens = _tokenize (text, _minLength);
544
- if (tokens == null || tokens.isEmpty) return ;
553
+ if (tokens == null || tokens.isEmpty) {
554
+ if (_textHashes.containsKey (id)) {
555
+ remove (id);
556
+ }
557
+ return ;
558
+ }
559
+ final String textHash = '${text .hashCode }/${tokens .length }' ;
560
+ if (_textHashes.containsKey (id) && _textHashes[id] != textHash) {
561
+ remove (id);
562
+ }
545
563
for (String token in tokens) {
546
564
final Set <String > set = _inverseIds.putIfAbsent (token, () => new Set ());
547
565
set .add (id);
548
566
}
549
567
// Document size is a highly scaled-down proxy of the length.
550
568
final docSize = 1 + math.log (1 + tokens.length) / 100 ;
551
569
_docSizes[id] = docSize;
570
+ _textHashes[id] = textHash;
552
571
}
553
572
554
573
void remove (String id) {
574
+ _textHashes.remove (id);
555
575
_docSizes.remove (id);
556
576
final List <String > removeKeys = [];
557
577
_inverseIds.forEach ((String key, Set <String > set ) {
0 commit comments