66library dartdoc;
77
88import 'dart:async' ;
9+ import 'dart:convert' ;
910import 'dart:io' ;
1011
1112import 'package:analyzer/dart/element/element.dart' show LibraryElement;
@@ -214,45 +215,61 @@ class DartDoc {
214215 return new DartDocResults (packageMeta, package, outputDir);
215216 }
216217
217- void _warn (Package package, PackageWarning kind, String p, String origin,
218- {String source}) {
218+ /// Warn on file paths.
219+ void _warn (Package package, PackageWarning kind, String warnOn, String origin,
220+ {String referredFrom}) {
219221 // Ordinarily this would go in [Package.warn], but we don't actually know what
220222 // ModelElement to warn on yet.
221- Locatable referenceElement;
222- Set <Locatable > referenceElements;
223+ Locatable referredFromElement;
224+ Locatable warnOnElement;
225+ Set <Locatable > referredFromElements;
226+ Set <Locatable > warnOnElements;
223227
224228 // Make all paths relative to origin.
225- if (path.isWithin (origin, p )) {
226- p = path.relative (p , from: origin);
229+ if (path.isWithin (origin, warnOn )) {
230+ warnOn = path.relative (warnOn , from: origin);
227231 }
228- if (source != null ) {
229- if (path.isWithin (origin, source )) {
230- source = path.relative (source , from: origin);
232+ if (referredFrom != null ) {
233+ if (path.isWithin (origin, referredFrom )) {
234+ referredFrom = path.relative (referredFrom , from: origin);
231235 }
232236 // Source paths are always relative.
233- referenceElements = package.allHrefs[source];
234- } else {
235- referenceElements = package.allHrefs[p];
237+ referredFromElements = _hrefs[referredFrom];
238+ }
239+ warnOnElements = _hrefs[warnOn];
240+
241+ if (referredFromElements != null ) {
242+ if (referredFromElements.any ((e) => e.isCanonical)) {
243+ referredFromElement =
244+ referredFromElements.firstWhere ((e) => e.isCanonical);
245+ } else {
246+ // If we don't have a canonical element, just pick one.
247+ referredFromElement =
248+ referredFromElements.isEmpty ? null : referredFromElements.first;
249+ }
236250 }
237- if (referenceElements != null ) {
238- if (referenceElements .any ((e) => e.isCanonical)) {
239- referenceElement = referenceElements .firstWhere ((e) => e.isCanonical);
251+ if (warnOnElements != null ) {
252+ if (warnOnElements .any ((e) => e.isCanonical)) {
253+ warnOnElement = warnOnElements .firstWhere ((e) => e.isCanonical);
240254 } else {
241255 // If we don't have a canonical element, just pick one.
242- referenceElement =
243- referenceElements.isEmpty ? null : referenceElements.first;
256+ warnOnElement = warnOnElements.isEmpty ? null : warnOnElements.first;
244257 }
245258 }
246- if (referenceElement == null && source == 'index.html' )
247- referenceElement = package;
248- package.warnOnElement (referenceElement, kind, message: p);
259+
260+ if (referredFromElement == null && referredFrom == 'index.html' )
261+ referredFromElement = package;
262+ String message = warnOn;
263+ if (referredFrom == 'index.json' ) message = '$warnOn (from index.json)' ;
264+ package.warnOnElement (warnOnElement, kind,
265+ message: message, referredFrom: referredFromElement);
249266 }
250267
251268 void _doOrphanCheck (Package package, String origin, Set <String > visited) {
252269 String normalOrigin = path.normalize (origin);
253270 String staticAssets = path.joinAll ([normalOrigin, 'static-assets' , '' ]);
254271 String indexJson = path.joinAll ([normalOrigin, 'index.json' ]);
255- bool foundIndex = false ;
272+ bool foundIndexJson = false ;
256273 for (FileSystemEntity f
257274 in new Directory (normalOrigin).listSync (recursive: true )) {
258275 var fullPath = path.normalize (f.path);
@@ -263,7 +280,7 @@ class DartDoc {
263280 continue ;
264281 }
265282 if (fullPath == indexJson) {
266- foundIndex = true ;
283+ foundIndexJson = true ;
267284 _onCheckProgress.add (fullPath);
268285 continue ;
269286 }
@@ -277,7 +294,7 @@ class DartDoc {
277294 _onCheckProgress.add (fullPath);
278295 }
279296
280- if (! foundIndex ) {
297+ if (! foundIndexJson ) {
281298 _warn (package, PackageWarning .brokenLink, indexJson, normalOrigin);
282299 _onCheckProgress.add (indexJson);
283300 }
@@ -305,6 +322,42 @@ class DartDoc {
305322 return new Tuple2 (stringLinks, baseHref);
306323 }
307324
325+ void _doSearchIndexCheck (
326+ Package package, String origin, Set <String > visited) {
327+ String fullPath = path.joinAll ([origin, 'index.json' ]);
328+ String indexPath = path.joinAll ([origin, 'index.html' ]);
329+ File file = new File ("$fullPath " );
330+ if (! file.existsSync ()) {
331+ return null ;
332+ }
333+ JsonDecoder decoder = new JsonDecoder ();
334+ List jsonData = decoder.convert (file.readAsStringSync ());
335+
336+ Set <String > found = new Set ();
337+ found.add (fullPath);
338+ // The package index isn't supposed to be in the search, so suppress the
339+ // warning.
340+ found.add (indexPath);
341+ for (Map <String , String > entry in jsonData) {
342+ if (entry.containsKey ('href' )) {
343+ String entryPath = path.joinAll ([origin, entry['href' ]]);
344+ if (! visited.contains (entryPath)) {
345+ _warn (package, PackageWarning .brokenLink, entryPath,
346+ path.normalize (origin),
347+ referredFrom: fullPath);
348+ }
349+ found.add (entryPath);
350+ }
351+ }
352+ // Missing from search index
353+ Set <String > missing_from_search = visited.difference (found);
354+ for (String s in missing_from_search) {
355+ _warn (package, PackageWarning .missingFromSearchIndex, s,
356+ path.normalize (origin),
357+ referredFrom: fullPath);
358+ }
359+ }
360+
308361 void _doCheck (
309362 Package package, String origin, Set <String > visited, String pathToCheck,
310363 [String source, String fullPath]) {
@@ -313,15 +366,15 @@ class DartDoc {
313366 fullPath = path.normalize (fullPath);
314367 }
315368
316- visited.add (fullPath);
317369 Tuple2 stringLinksAndHref = _getStringLinksAndHref (fullPath);
318370 if (stringLinksAndHref == null ) {
319371 _warn (package, PackageWarning .brokenLink, pathToCheck,
320372 path.normalize (origin),
321- source : source);
373+ referredFrom : source);
322374 _onCheckProgress.add (pathToCheck);
323375 return null ;
324376 }
377+ visited.add (fullPath);
325378 Iterable <String > stringLinks = stringLinksAndHref.item1;
326379 String baseHref = stringLinksAndHref.item2;
327380
@@ -355,10 +408,10 @@ class DartDoc {
355408
356409 final Set <String > visited = new Set ();
357410 final String start = 'index.html' ;
358- visited.add (start);
359411 stdout.write ('\n validating docs...' );
360412 _doCheck (package, origin, visited, start);
361413 _doOrphanCheck (package, origin, visited);
414+ _doSearchIndexCheck (package, origin, visited);
362415 }
363416
364417 List <LibraryElement > _parseLibraries (
0 commit comments