@@ -1300,7 +1300,7 @@ abstract class Documentable extends Nameable {
13001300abstract class Categorization implements ModelElement {
13011301 @override
13021302 String _buildDocumentationAddition (String rawDocs) =>
1303- _stripAndSetDartdocCategories (rawDocs);
1303+ _stripAndSetDartdocCategories (rawDocs ?? = '' );
13041304
13051305 /// Parse {@category ...} and related information in API comments, stripping
13061306 /// out that information from the given comments and returning the stripped
@@ -2263,7 +2263,7 @@ class Library extends ModelElement with Categorization, TopLevelContainer {
22632263 Set <String > get canonicalFor {
22642264 if (_canonicalFor == null ) {
22652265 // TODO(jcollins-g): restructure to avoid using side effects.
2266- documentation ;
2266+ _buildDocumentationAddition (documentationComment) ;
22672267 }
22682268 return _canonicalFor;
22692269 }
@@ -2273,14 +2273,14 @@ class Library extends ModelElement with Categorization, TopLevelContainer {
22732273 ///
22742274 /// Example:
22752275 /// {@canonicalFor libname.ClassName}
2276- String _setCanonicalFor ( String rawDocs) {
2277- if (_canonicalFor == null ) {
2278- _canonicalFor = new Set ( );
2279- }
2276+ @override
2277+ String _buildDocumentationAddition ( String rawDocs ) {
2278+ rawDocs = super . _buildDocumentationAddition (rawDocs );
2279+ Set < String > newCanonicalFor = new Set ();
22802280 Set <String > notFoundInAllModelElements = new Set ();
22812281 final canonicalRegExp = new RegExp (r'{@canonicalFor\s([^}]+)}' );
22822282 rawDocs = rawDocs.replaceAllMapped (canonicalRegExp, (Match match) {
2283- canonicalFor .add (match.group (1 ));
2283+ newCanonicalFor .add (match.group (1 ));
22842284 notFoundInAllModelElements.add (match.group (1 ));
22852285 return '' ;
22862286 });
@@ -2290,16 +2290,12 @@ class Library extends ModelElement with Categorization, TopLevelContainer {
22902290 for (String notFound in notFoundInAllModelElements) {
22912291 warn (PackageWarning .ignoredCanonicalFor, message: notFound);
22922292 }
2293- return rawDocs;
2294- }
2295-
2296- String _libraryDocs;
2297- @override
2298- String get documentation {
2299- if (_libraryDocs == null ) {
2300- _libraryDocs = _setCanonicalFor (super .documentation);
2293+ // TODO(jcollins-g): warn if a macro/tool _does_ generate an unexpected
2294+ // canonicalFor?
2295+ if (_canonicalFor == null ) {
2296+ _canonicalFor = newCanonicalFor;
23012297 }
2302- return _libraryDocs ;
2298+ return rawDocs ;
23032299 }
23042300
23052301 /// Libraries are not enclosed by anything.
@@ -3250,13 +3246,14 @@ abstract class ModelElement extends Canonicalization
32503246
32513247 /// Override this to add more features to the documentation builder in a
32523248 /// subclass.
3253- String _buildDocumentationAddition (String docs) => docs;
3249+ String _buildDocumentationAddition (String docs) => docs ?? = '' ;
32543250
32553251 /// Separate from _buildDocumentationLocal for overriding.
32563252 String _buildDocumentationBaseSync () {
3257- assert (_rawDocs == null );
3253+ assert (_rawDocs == null , 'reentrant calls to _buildDocumentation* not allowed' );
32583254 // Do not use the sync method if we need to evaluate tools or templates.
3259- assert (packageGraph._localDocumentationBuilt);
3255+ assert (! isCanonical ||
3256+ ! needsPrecacheRegExp.hasMatch (documentationComment ?? '' ));
32603257 if (config.dropTextFrom.contains (element.library.name)) {
32613258 _rawDocs = '' ;
32623259 } else {
@@ -3273,7 +3270,7 @@ abstract class ModelElement extends Canonicalization
32733270 /// Separate from _buildDocumentationLocal for overriding. Can only be
32743271 /// used as part of [PackageGraph.setUpPackageGraph] .
32753272 Future <String > _buildDocumentationBase () async {
3276- assert (_rawDocs == null );
3273+ assert (_rawDocs == null , 'reentrant calls to _buildDocumentation* not allowed' );
32773274 // Do not use the sync method if we need to evaluate tools or templates.
32783275 if (config.dropTextFrom.contains (element.library.name)) {
32793276 _rawDocs = '' ;
@@ -4037,6 +4034,8 @@ abstract class ModelElement extends Canonicalization
40374034 'LIBRARY_NAME' : library? .fullyQualifiedName,
40384035 'ELEMENT_NAME' : fullyQualifiedNameWithoutLibrary,
40394036 'INVOCATION_INDEX' : invocationIndex.toString (),
4037+ 'PACKAGE_INVOCATION_INDEX' :
4038+ (package.toolInvocationIndex++ ).toString (),
40404039 }..removeWhere ((key, value) => value == null ));
40414040 });
40424041 } else {
@@ -4688,6 +4687,11 @@ class PackageGraph {
46884687 /// Generate a list of futures for any docs that actually require precaching.
46894688 Iterable <Future > precacheLocalDocs () sync * {
46904689 for (ModelElement m in allModelElements) {
4690+ // Skip if there is a canonicalModelElement somewhere else we can run this
4691+ // for. Not the same as allCanonicalModelElements since we need to run
4692+ // for any ModelElement that might not have a canonical ModelElement,
4693+ // too.
4694+ if (m.canonicalModelElement != null && ! m.isCanonical) continue ;
46914695 if (m.documentationComment != null &&
46924696 needsPrecacheRegExp.hasMatch (m.documentationComment)) {
46934697 yield m._precacheLocalDocs ();
@@ -5800,6 +5804,9 @@ class Package extends LibraryContainer
58005804 @override
58015805 Library get canonicalLibrary => null ;
58025806
5807+ /// Number of times we have invoked a tool for this package.
5808+ int toolInvocationIndex = 0 ;
5809+
58035810 /// Pieces of the location split by [locationSplitter] (removing package: and
58045811 /// slashes).
58055812 @override
0 commit comments