@@ -120,6 +120,18 @@ class DartDoc {
120
120
121
121
Stream <String > get onCheckProgress => _onCheckProgress.stream;
122
122
123
+ bool isExcluded (String name) => excludes.any ((pattern) => name == pattern);
124
+
125
+ Iterable <LibraryElement > filterExcludesFrom (Iterable <LibraryElement > libraries) sync * {
126
+ for (LibraryElement l in libraries) {
127
+ if (isExcluded (l.source.uri.toString ()) ||
128
+ config.excludePackages.contains (Library .getPackageMeta (l)? .name)) {
129
+ continue ;
130
+ }
131
+ yield l;
132
+ }
133
+ }
134
+
123
135
/// Generate DartDoc documentation.
124
136
///
125
137
/// [DartDocResults] is returned if dartdoc succeeds. [DartDocFailure] is
@@ -129,52 +141,63 @@ class DartDoc {
129
141
Future <DartDocResults > generateDocs () async {
130
142
_stopwatch = new Stopwatch ()..start ();
131
143
132
- List <String > files = packageMeta.isSdk
133
- ? const []
134
- : findFilesToDocumentInPackage (rootDir.path).toList ();
135
-
136
- // TODO(jcollins-g): seems like most of this belongs in the Package constructor
137
- List <LibraryElement > libraries = _parseLibraries (files, includeExternals);
138
-
139
- if (includes != null && includes.isNotEmpty) {
140
- Iterable knownLibraryNames = libraries.map ((l) => l.name);
141
- Set notFound =
142
- new Set .from (includes).difference (new Set .from (knownLibraryNames));
143
- if (notFound.isNotEmpty) {
144
- throw 'Did not find: [${notFound .join (', ' )}] in '
145
- 'known libraries: [${knownLibraryNames .join (', ' )}]' ;
146
- }
147
- libraries.removeWhere ((lib) => ! includes.contains (lib.name));
148
- } else {
149
- // remove excluded libraries
150
- excludes.forEach ((pattern) {
151
- libraries.removeWhere ((lib) {
152
- return lib.name.startsWith (pattern) || lib.name == pattern;
153
- });
154
- });
155
- }
156
-
157
144
PackageWarningOptions warningOptions = new PackageWarningOptions ();
158
145
// TODO(jcollins-g): explode this into detailed command line options.
159
146
if (config != null && config.showWarnings) {
160
147
for (PackageWarning kind in PackageWarning .values) {
161
148
warningOptions.warn (kind);
162
149
}
163
150
}
151
+
164
152
Package package;
165
- if (config != null && config.autoIncludeDependencies) {
166
- package = Package .withAutoIncludedDependencies (
167
- libraries, packageMeta, warningOptions);
168
- libraries = package.libraries.map ((l) => l.element).toList ();
169
- // remove excluded libraries again, in case they are picked up through
170
- // dependencies.
171
- excludes.forEach ((pattern) {
172
- libraries.removeWhere ((lib) {
173
- return lib.name.startsWith (pattern) || lib.name == pattern;
174
- });
175
- });
153
+ // TODO(jcollins-g): seems like most of this belongs in the Package constructor
154
+ Set <String > rootDirsPrev = new Set ();
155
+ Set <String > rootDirs = new Set ()..add (rootDir.path);
156
+ Set <LibraryElement > libraries = new Set ();
157
+ Set <String > files = new Set ();
158
+ Set <String > filesPrev = new Set ();
159
+ while (! rootDirsPrev.containsAll (rootDirs)) {
160
+ for (String rootDirPath in rootDirs.difference (rootDirsPrev)) {
161
+ files.addAll (packageMeta.isSdk
162
+ ? new Set ()
163
+ : findFilesToDocumentInPackage (rootDirPath));
164
+ }
165
+
166
+ libraries.addAll (_parseLibraries (files.difference (filesPrev), includeExternals, rootDirsPrev.isEmpty));
167
+
168
+ if (includes != null && includes.isNotEmpty) {
169
+ Iterable knownLibraryNames = libraries.map ((l) => l.name);
170
+ Set notFound =
171
+ new Set .from (includes).difference (new Set .from (knownLibraryNames));
172
+ if (notFound.isNotEmpty) {
173
+ throw 'Did not find: [${notFound .join (', ' )}] in '
174
+ 'known libraries: [${knownLibraryNames .join (', ' )}]' ;
175
+ }
176
+ libraries.removeWhere ((lib) => ! includes.contains (lib.name));
177
+ } else {
178
+ libraries = filterExcludesFrom (libraries).toSet ();
179
+ }
180
+ /*
181
+ if (config != null && config.autoIncludeDependencies) {
182
+ package = Package.withAutoIncludedDependencies(
183
+ libraries, packageMeta, warningOptions);
184
+ // remove excluded libraries again, in case they are picked up through
185
+ // dependencies.
186
+ libraries = filterExcludesFrom(package.publicLibraries.map((l) => l.element as LibraryElement)).toSet();
187
+ }
188
+ rootDirsPrev = rootDirs.toSet();
189
+ for (Library lib in package.publicLibraries) {
190
+ if (libraries.contains(lib.element)) {
191
+ PackageMeta meta = lib.packageMeta;
192
+ if (meta != null) rootDirs.add(meta.dir.path);
193
+ }
194
+ }
195
+ filesPrev = files.toSet();
196
+ */
197
+ rootDirsPrev = rootDirs.toSet ();
198
+ filesPrev = files.toSet ();
176
199
}
177
- package = new Package (libraries, packageMeta, warningOptions);
200
+ package = new Package (libraries, packageMeta, warningOptions, context );
178
201
179
202
// Go through docs of every model element in package to prebuild the macros index
180
203
// TODO(jcollins-g): move index building into a cached-on-demand generation
@@ -201,10 +224,10 @@ class DartDoc {
201
224
202
225
double seconds = _stopwatch.elapsedMilliseconds / 1000.0 ;
203
226
logInfo (
204
- "Documented ${package .libraries .length } librar${package .libraries .length == 1 ? 'y' : 'ies' } "
227
+ "Documented ${package .publicLibraries .length } librar${package .publicLibraries .length == 1 ? 'y' : 'ies' } "
205
228
"in ${seconds .toStringAsFixed (1 )} seconds" );
206
229
207
- if (package.libraries .isEmpty) {
230
+ if (package.publicLibraries .isEmpty) {
208
231
throw new DartDocFailure (
209
232
"dartdoc could not find any libraries to document. Run `pub get` and try again." );
210
233
}
@@ -412,6 +435,7 @@ class DartDoc {
412
435
}
413
436
414
437
Map <String , Set <ModelElement >> _hrefs;
438
+ AnalysisContext context;
415
439
416
440
/// Don't call this method more than once, and only after you've
417
441
/// generated all docs for the Package.
@@ -428,7 +452,7 @@ class DartDoc {
428
452
}
429
453
430
454
List <LibraryElement > _parseLibraries (
431
- List <String > files, List <String > includeExternals) {
455
+ Iterable <String > files, List <String > includeExternals, [ bool parseEmbedders = true ] ) {
432
456
Set <LibraryElement > libraries = new Set ();
433
457
DartSdk sdk = new FolderBasedDartSdk (PhysicalResourceProvider .INSTANCE ,
434
458
PhysicalResourceProvider .INSTANCE .getFolder (sdkDir.path));
@@ -470,13 +494,18 @@ class DartDoc {
470
494
471
495
AnalysisEngine .instance.processRequiredPlugins ();
472
496
473
- AnalysisContext context = AnalysisEngine .instance.createAnalysisContext ()
497
+ context = AnalysisEngine .instance.createAnalysisContext ()
474
498
..analysisOptions = options
475
499
..sourceFactory = sourceFactory;
476
500
477
501
if (packageMeta.isSdk) {
478
502
libraries
479
503
.addAll (new Set ()..addAll (getSdkLibrariesToDocument (sdk, context)));
504
+ } else if (embedderSdk == null || embedderSdk.urlMappings.isEmpty) {
505
+ // TODO(jcollins-g): make this work for embedders?
506
+ // Make sure that Interceptor gets found so that the Package can collect
507
+ // it later and cloak that class completely.
508
+ libraries.addAll (getSdkLibrariesToDocument (sdk, context).where ((l) => l.name == '_interceptors' ));
480
509
}
481
510
482
511
List <Source > sources = [];
@@ -512,7 +541,7 @@ class DartDoc {
512
541
513
542
files.forEach (processLibrary);
514
543
515
- if ((embedderSdk != null ) && (embedderSdk.urlMappings.length > 0 )) {
544
+ if (parseEmbedders && (embedderSdk != null ) && (embedderSdk.urlMappings.length > 0 )) {
516
545
embedderSdk.urlMappings.keys.forEach ((String dartUri) {
517
546
Source source = embedderSdk.mapDartUri (dartUri);
518
547
processLibrary (source.fullName);
@@ -531,42 +560,38 @@ class DartDoc {
531
560
String libraryName = Library .getLibraryName (library);
532
561
var fullPath = source.fullName;
533
562
563
+ if (libraryName.contains ('analyzer' )) {
564
+ 1 + 1 ;
565
+ }
534
566
if (includeExternals.any ((string) => fullPath.endsWith (string))) {
535
567
if (libraries.map (Library .getLibraryName).contains (libraryName)) {
536
568
continue ;
537
569
}
538
570
libraries.add (library);
539
- } else if (config != null &&
540
- config.autoIncludeDependencies &&
541
- libraryName != '' ) {
542
- File searchFile = new File (fullPath);
543
- searchFile =
544
- new File (path.join (searchFile.parent.path, 'pubspec.yaml' ));
545
- bool foundLibSrc = false ;
546
- while (! foundLibSrc && searchFile.parent != null ) {
547
- if (searchFile.existsSync ()) break ;
548
- List <String > pathParts = path.split (searchFile.parent.path);
549
- // This is a pretty intensely hardcoded convention, but there seems to
550
- // to be no other way to identify what might be a "top level" library
551
- // here. If lib/src is in the path between the file and the pubspec,
552
- // assume that this is supposed to be private.
553
- if (pathParts.length < 2 ) break ;
554
- pathParts = pathParts.sublist (pathParts.length - 2 , pathParts.length);
555
- foundLibSrc =
556
- path.join (pathParts[0 ], pathParts[1 ]) == path.join ('lib' , 'src' );
557
- searchFile = new File (
558
- path.join (searchFile.parent.parent.path, 'pubspec.yaml' ));
559
- }
560
- if (foundLibSrc) continue ;
561
- libraries.add (library);
562
571
}
563
572
}
564
573
574
+ libraries = filterExcludesFrom (libraries).toSet ();
565
575
List <AnalysisErrorInfo > errorInfos = [];
566
576
577
+ // TODO(jcollins-g): figure out why sources can't contain includeExternals
578
+ // or embedded SDK components without having spurious(?) analysis errors.
579
+ // That seems wrong.
567
580
for (Source source in sources) {
568
581
context.computeErrors (source);
569
- errorInfos.add (context.getErrors (source));
582
+ AnalysisErrorInfo info = context.getErrors (source);
583
+ errorInfos.add (info);
584
+ List <_Error > errors = [info].expand ((AnalysisErrorInfo info) {
585
+ return info.errors.map ((error) =>
586
+ new _Error (error, info.lineInfo, packageMeta.dir.path));
587
+ })
588
+ .where ((_Error error) => error.isError)
589
+ .toList ()
590
+ ..sort ();
591
+ if (errors.isNotEmpty) {
592
+ logWarning ('analysis errors from source: ${source .uri .toString ()} (${source .toString ()}' );
593
+ errors.forEach (logWarning);
594
+ }
570
595
}
571
596
572
597
List <_Error > errors = errorInfos
@@ -584,7 +609,6 @@ class DartDoc {
584
609
_stopwatch.reset ();
585
610
586
611
if (errors.isNotEmpty) {
587
- errors.forEach (logWarning);
588
612
int len = errors.length;
589
613
throw new DartDocFailure (
590
614
"encountered ${len } analysis error${len == 1 ? '' : 's' }" );
0 commit comments