Do not allow tools to run in compare_output_test (#1853)

* Do not allow tools to run in compare_output_test

* Update dev docs
diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart
index 2d77708..328f9da 100644
--- a/lib/src/dartdoc_options.dart
+++ b/lib/src/dartdoc_options.dart
@@ -1286,6 +1286,7 @@
 
   // All values defined in createDartdocOptions should be exposed here.
   bool get addCrossdart => optionSet['addCrossdart'].valueAt(context);
+  bool get allowTools => optionSet['allowTools'].valueAt(context);
   double get ambiguousReexportScorerMinConfidence =>
       optionSet['ambiguousReexportScorerMinConfidence'].valueAt(context);
   bool get autoIncludeDependencies =>
@@ -1347,6 +1348,9 @@
     new DartdocOptionArgOnly<bool>('addCrossdart', false,
         help: 'Add Crossdart links to the source code pieces.',
         negatable: true),
+    new DartdocOptionArgOnly<bool>('allowTools', true,
+        help: 'Execute user-defined tools to fill in @tool directives.',
+        negatable: true),
     new DartdocOptionArgFile<double>(
         'ambiguousReexportScorerMinConfidence', 0.1,
         help: 'Minimum scorer confidence to suppress warning on ambiguous '
diff --git a/lib/src/model.dart b/lib/src/model.dart
index 1c92fc1..2816a51 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -3988,38 +3988,42 @@
   /// ## Content to send to tool.
   /// 2018-09-18T21:15+00:00
   Future<String> _evaluateTools(String rawDocs) async {
-    var runner = new ToolRunner(config.tools, (String message) async {
-      warn(PackageWarning.toolError, message: message);
-    });
-    int invocationIndex = 0;
-    return await _replaceAllMappedAsync(rawDocs, basicToolRegExp,
-        (basicMatch) async {
-      List<String> args = _splitUpQuotedArgs(basicMatch[1]).toList();
-      // Tool name must come first.
-      if (args.isEmpty) {
-        warn(PackageWarning.toolError,
-            message: 'Must specify a tool to execute for the @tool directive.');
-        return Future.value('');
-      }
-      // Count the number of invocations of tools in this dartdoc block,
-      // so that tools can differentiate different blocks from each other.
-      invocationIndex++;
-      return await runner.run(args,
-          content: basicMatch[2],
-          environment: {
-            'SOURCE_LINE': lineAndColumn?.item1?.toString(),
-            'SOURCE_COLUMN': lineAndColumn?.item2?.toString(),
-            'SOURCE_PATH': (sourceFileName == null ||
-                    package?.packagePath == null)
-                ? null
-                : pathLib.relative(sourceFileName, from: package.packagePath),
-            'PACKAGE_PATH': package?.packagePath,
-            'PACKAGE_NAME': package?.name,
-            'LIBRARY_NAME': library?.fullyQualifiedName,
-            'ELEMENT_NAME': fullyQualifiedNameWithoutLibrary,
-            'INVOCATION_INDEX': invocationIndex.toString(),
-          }..removeWhere((key, value) => value == null));
-    }).whenComplete(runner.dispose);
+    if (config.allowTools) {
+      var runner = new ToolRunner(config.tools, (String message) async {
+        warn(PackageWarning.toolError, message: message);
+      });
+      int invocationIndex = 0;
+      return await _replaceAllMappedAsync(rawDocs, basicToolRegExp,
+              (basicMatch) async {
+            List<String> args = _splitUpQuotedArgs(basicMatch[1]).toList();
+            // Tool name must come first.
+            if (args.isEmpty) {
+              warn(PackageWarning.toolError,
+                  message: 'Must specify a tool to execute for the @tool directive.');
+              return Future.value('');
+            }
+            // Count the number of invocations of tools in this dartdoc block,
+            // so that tools can differentiate different blocks from each other.
+            invocationIndex++;
+            return await runner.run(args,
+                content: basicMatch[2],
+                environment: {
+                  'SOURCE_LINE': lineAndColumn?.item1?.toString(),
+                  'SOURCE_COLUMN': lineAndColumn?.item2?.toString(),
+                  'SOURCE_PATH': (sourceFileName == null ||
+                      package?.packagePath == null)
+                      ? null
+                      : pathLib.relative(sourceFileName, from: package.packagePath),
+                  'PACKAGE_PATH': package?.packagePath,
+                  'PACKAGE_NAME': package?.name,
+                  'LIBRARY_NAME': library?.fullyQualifiedName,
+                  'ELEMENT_NAME': fullyQualifiedNameWithoutLibrary,
+                  'INVOCATION_INDEX': invocationIndex.toString(),
+                }..removeWhere((key, value) => value == null));
+          }).whenComplete(runner.dispose);
+    } else {
+      return rawDocs;
+    }
   }
 
   /// Replace &#123;@animation ...&#125; in API comments with some HTML to manage an
diff --git a/test/compare_output_test.dart b/test/compare_output_test.dart
index 82f93b3..bef2de7 100644
--- a/test/compare_output_test.dart
+++ b/test/compare_output_test.dart
@@ -89,6 +89,7 @@
       var args = <String>[
         '--enable-asserts',
         dartdocBin,
+        '--no-allow-tools',
         '--auto-include-dependencies',
         '--example-path-prefix',
         'examples',
diff --git a/testing/test_package_docs/ex/HtmlInjection/injectHtmlFromTool.html b/testing/test_package_docs/ex/HtmlInjection/injectHtmlFromTool.html
index 807259b..65315e0 100644
--- a/testing/test_package_docs/ex/HtmlInjection/injectHtmlFromTool.html
+++ b/testing/test_package_docs/ex/HtmlInjection/injectHtmlFromTool.html
@@ -73,18 +73,12 @@
     </section>
     <section class="desc markdown">
       <p>Invokes more than one tool in the same comment block, and injects HTML.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: HtmlInjection.injectHtmlFromTool, INVOCATION_INDEX: 1}
-Script location is in dartdoc tree.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --html</code></p>
-<h2 id="this-text-should-appear-in-the-output"><code>This text should appear in the output.</code></h2>
-<p>{@inject-html}</p><div class="title">Title</div>{@end-inject-html}<p></p>
-<p>This text should appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: HtmlInjection.injectHtmlFromTool, INVOCATION_INDEX: 2}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --html</code></p>
-<h2 id="this-text-should-also-appear-in-the-output"><code>This text should also appear in the output.</code></h2>
-<p>{@inject-html}</p><div class="title">Title</div>{@end-inject-html}<p></p>
-<p>This text should also appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file=$INPUT --html}
+This text should appear in the output.
+{@end-tool}
+{@tool drill --file=$INPUT --html}
+This text should also appear in the output.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs/ex/ToolUser/invokeTool.html b/testing/test_package_docs/ex/ToolUser/invokeTool.html
index fb1b3ff..ce98148 100644
--- a/testing/test_package_docs/ex/ToolUser/invokeTool.html
+++ b/testing/test_package_docs/ex/ToolUser/invokeTool.html
@@ -74,13 +74,10 @@
     </section>
     <section class="desc markdown">
       <p>Invokes a tool.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeTool, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --source=lib/example.dart_546_8, --package-path=&lt;PACKAGE_PATH&gt;, --package-name=test_package, --library-name=ex, --element-name=ToolUser.invokeTool, --special= |[</code>!@#"'$%^&amp;*()_+]</p>
-<h2 id="yes-it-is-a-dog"><code>Yes it is a [Dog]!</code></h2>
-<p>Yes it is a <a href="ex/Dog-class.html">Dog</a>! Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<h2 id="ok-fine-it-isnt"><code>Ok, fine it isn't.</code></h2>
-<p>Ok, fine it isn't. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file="$INPUT" --source="$(SOURCE_PATH)<em>$(SOURCE_LINE)</em>$SOURCE_COLUMN" --package-path=$PACKAGE_PATH --package-name=$PACKAGE_NAME --library-name=$LIBRARY_NAME --element-name=$(ELEMENT_NAME) --special=" |[]!@#"'$%^&amp;*()_+"}
+Yes it is a <a href="ex/Dog-class.html">Dog</a>!
+Ok, fine it isn't.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs/ex/ToolUser/invokeToolMultipleSections.html b/testing/test_package_docs/ex/ToolUser/invokeToolMultipleSections.html
index c120fef..d4db247 100644
--- a/testing/test_package_docs/ex/ToolUser/invokeToolMultipleSections.html
+++ b/testing/test_package_docs/ex/ToolUser/invokeToolMultipleSections.html
@@ -74,16 +74,12 @@
     </section>
     <section class="desc markdown">
       <p>Invokes more than one tool in the same comment block.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolMultipleSections, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;</code></p>
-<h2 id="this-text-should-appear-in-the-output"><code>This text should appear in the output.</code></h2>
-<p>This text should appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolMultipleSections, INVOCATION_INDEX: 2}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;</code></p>
-<h2 id="this-text-should-also-appear-in-the-output"><code>This text should also appear in the output.</code></h2>
-<p>This text should also appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file=$INPUT}
+This text should appear in the output.
+{@end-tool}
+{@tool drill --file=$INPUT}
+This text should also appear in the output.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs/ex/ToolUser/invokeToolNoInput.html b/testing/test_package_docs/ex/ToolUser/invokeToolNoInput.html
index a38f3e9..3943d67 100644
--- a/testing/test_package_docs/ex/ToolUser/invokeToolNoInput.html
+++ b/testing/test_package_docs/ex/ToolUser/invokeToolNoInput.html
@@ -74,9 +74,9 @@
     </section>
     <section class="desc markdown">
       <p>Invokes a tool without the $INPUT token or args.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolNoInput, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: []</p>
+<p>{@tool drill}
+This text should not appear in the output, even if it references <a href="ex/Dog-class.html">Dog</a>.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs_dev/ex/HtmlInjection/injectHtmlFromTool.html b/testing/test_package_docs_dev/ex/HtmlInjection/injectHtmlFromTool.html
index 807259b..65315e0 100644
--- a/testing/test_package_docs_dev/ex/HtmlInjection/injectHtmlFromTool.html
+++ b/testing/test_package_docs_dev/ex/HtmlInjection/injectHtmlFromTool.html
@@ -73,18 +73,12 @@
     </section>
     <section class="desc markdown">
       <p>Invokes more than one tool in the same comment block, and injects HTML.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: HtmlInjection.injectHtmlFromTool, INVOCATION_INDEX: 1}
-Script location is in dartdoc tree.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --html</code></p>
-<h2 id="this-text-should-appear-in-the-output"><code>This text should appear in the output.</code></h2>
-<p>{@inject-html}</p><div class="title">Title</div>{@end-inject-html}<p></p>
-<p>This text should appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: HtmlInjection.injectHtmlFromTool, INVOCATION_INDEX: 2}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --html</code></p>
-<h2 id="this-text-should-also-appear-in-the-output"><code>This text should also appear in the output.</code></h2>
-<p>{@inject-html}</p><div class="title">Title</div>{@end-inject-html}<p></p>
-<p>This text should also appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file=$INPUT --html}
+This text should appear in the output.
+{@end-tool}
+{@tool drill --file=$INPUT --html}
+This text should also appear in the output.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs_dev/ex/ToolUser/invokeTool.html b/testing/test_package_docs_dev/ex/ToolUser/invokeTool.html
index fb1b3ff..ce98148 100644
--- a/testing/test_package_docs_dev/ex/ToolUser/invokeTool.html
+++ b/testing/test_package_docs_dev/ex/ToolUser/invokeTool.html
@@ -74,13 +74,10 @@
     </section>
     <section class="desc markdown">
       <p>Invokes a tool.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeTool, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;, --source=lib/example.dart_546_8, --package-path=&lt;PACKAGE_PATH&gt;, --package-name=test_package, --library-name=ex, --element-name=ToolUser.invokeTool, --special= |[</code>!@#"'$%^&amp;*()_+]</p>
-<h2 id="yes-it-is-a-dog"><code>Yes it is a [Dog]!</code></h2>
-<p>Yes it is a <a href="ex/Dog-class.html">Dog</a>! Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<h2 id="ok-fine-it-isnt"><code>Ok, fine it isn't.</code></h2>
-<p>Ok, fine it isn't. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file="$INPUT" --source="$(SOURCE_PATH)<em>$(SOURCE_LINE)</em>$SOURCE_COLUMN" --package-path=$PACKAGE_PATH --package-name=$PACKAGE_NAME --library-name=$LIBRARY_NAME --element-name=$(ELEMENT_NAME) --special=" |[]!@#"'$%^&amp;*()_+"}
+Yes it is a <a href="ex/Dog-class.html">Dog</a>!
+Ok, fine it isn't.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs_dev/ex/ToolUser/invokeToolMultipleSections.html b/testing/test_package_docs_dev/ex/ToolUser/invokeToolMultipleSections.html
index c120fef..d4db247 100644
--- a/testing/test_package_docs_dev/ex/ToolUser/invokeToolMultipleSections.html
+++ b/testing/test_package_docs_dev/ex/ToolUser/invokeToolMultipleSections.html
@@ -74,16 +74,12 @@
     </section>
     <section class="desc markdown">
       <p>Invokes more than one tool in the same comment block.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolMultipleSections, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;</code></p>
-<h2 id="this-text-should-appear-in-the-output"><code>This text should appear in the output.</code></h2>
-<p>This text should appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolMultipleSections, INVOCATION_INDEX: 2}
-Script location is in snapshot cache.
-Args: <code>--file=&lt;INPUT_FILE&gt;</code></p>
-<h2 id="this-text-should-also-appear-in-the-output"><code>This text should also appear in the output.</code></h2>
-<p>This text should also appear in the output. Is not a <a href="ex/ToolUser-class.html">ToolUser</a>.</p>
+<p>{@tool drill --file=$INPUT}
+This text should appear in the output.
+{@end-tool}
+{@tool drill --file=$INPUT}
+This text should also appear in the output.
+{@end-tool}</p>
     </section>
     
     
diff --git a/testing/test_package_docs_dev/ex/ToolUser/invokeToolNoInput.html b/testing/test_package_docs_dev/ex/ToolUser/invokeToolNoInput.html
index a38f3e9..3943d67 100644
--- a/testing/test_package_docs_dev/ex/ToolUser/invokeToolNoInput.html
+++ b/testing/test_package_docs_dev/ex/ToolUser/invokeToolNoInput.html
@@ -74,9 +74,9 @@
     </section>
     <section class="desc markdown">
       <p>Invokes a tool without the $INPUT token or args.</p>
-<p>Env: {INPUT: &lt;INPUT_FILE&gt;, SOURCE_COLUMN: 8, SOURCE_PATH: lib/example.dart, PACKAGE_PATH: &lt;PACKAGE_PATH&gt;, PACKAGE_NAME: test_package, LIBRARY_NAME: ex, ELEMENT_NAME: ToolUser.invokeToolNoInput, INVOCATION_INDEX: 1}
-Script location is in snapshot cache.
-Args: []</p>
+<p>{@tool drill}
+This text should not appear in the output, even if it references <a href="ex/Dog-class.html">Dog</a>.
+{@end-tool}</p>
     </section>
     
     
diff --git a/tool/grind.dart b/tool/grind.dart
index e33c0f5..455eaae 100644
--- a/tool/grind.dart
+++ b/tool/grind.dart
@@ -968,6 +968,7 @@
       [
         '--enable-asserts',
         pathLib.join('..', '..', 'bin', 'dartdoc.dart'),
+        '--no-allow-tools',
         '--auto-include-dependencies',
         '--example-path-prefix',
         'examples',