From a7322c2f47f4804366e80f7f96098a2357a1776a Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Tue, 17 Aug 2021 09:57:18 -0700 Subject: [PATCH 1/8] Switch to using CompilationUnitElement.classes (#2743) --- lib/src/model/library.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/model/library.dart b/lib/src/model/library.dart index 0d473879b0..b79109b623 100644 --- a/lib/src/model/library.dart +++ b/lib/src/model/library.dart @@ -102,13 +102,13 @@ class Library extends ModelElement with Categorization, TopLevelContainer { CompilationUnitElement compilationUnit) { return quiver.concat([ compilationUnit.accessors, + compilationUnit.classes, compilationUnit.enums, compilationUnit.extensions, compilationUnit.functions, compilationUnit.mixins, compilationUnit.topLevelVariables, compilationUnit.typeAliases, - compilationUnit.types, ]); } From 1d9181151a27731c836de239cf898e19a2edba40 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Tue, 17 Aug 2021 15:21:44 -0700 Subject: [PATCH 2/8] Prepare dartdoc_options for migration (#2745) * more specific imports in options * do not allow autoinitialization * dartfmt * parameterize the valueWithContext type * Use alternative constructors instead of externalizing, didn't realize the autodetect was so widely used * more subclasses --- lib/options.dart | 16 +++- lib/src/dartdoc_options.dart | 110 +++++++++++----------- test/end2end/dartdoc_test.dart | 4 +- test/mustachio/renderers_output_test.dart | 4 +- test/src/utils.dart | 7 +- 5 files changed, 75 insertions(+), 66 deletions(-) diff --git a/lib/options.dart b/lib/options.dart index 537c83084f..9af65023ab 100644 --- a/lib/options.dart +++ b/lib/options.dart @@ -2,8 +2,11 @@ import 'dart:io' show stderr, exitCode; import 'package:analyzer/file_system/file_system.dart'; import 'package:args/args.dart'; -import 'package:dartdoc/dartdoc.dart'; +import 'package:dartdoc/dartdoc.dart' show dartdocVersion, programName; +import 'package:dartdoc/src/dartdoc_options.dart'; +import 'package:dartdoc/src/generator/generator.dart'; import 'package:dartdoc/src/logging.dart'; +import 'package:dartdoc/src/package_meta.dart'; /// Helper class that consolidates option contexts for instantiating generators. class DartdocGeneratorOptionContext extends DartdocOptionContext { @@ -11,6 +14,10 @@ class DartdocGeneratorOptionContext extends DartdocOptionContext { DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider) : super(optionSet, dir, resourceProvider); + DartdocGeneratorOptionContext.fromDefaultContextLocation( + DartdocOptionSet optionSet, ResourceProvider resourceProvider) + : super.fromDefaultContextLocation(optionSet, resourceProvider); + // TODO(migration): Make late final with initializer when Null Safe. String _header; @@ -57,6 +64,9 @@ class DartdocProgramOptionContext extends DartdocGeneratorOptionContext DartdocProgramOptionContext( DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider) : super(optionSet, dir, resourceProvider); + DartdocProgramOptionContext.fromDefaultContextLocation( + DartdocOptionSet optionSet, ResourceProvider resourceProvider) + : super.fromDefaultContextLocation(optionSet, resourceProvider); bool get generateDocs => optionSet['generateDocs'].valueAt(context); bool get help => optionSet['help'].valueAt(context); @@ -118,8 +128,8 @@ Future parseOptions( DartdocProgramOptionContext config; try { - config = DartdocProgramOptionContext( - optionSet, null, packageMetaProvider.resourceProvider); + config = DartdocProgramOptionContext.fromDefaultContextLocation( + optionSet, packageMetaProvider.resourceProvider); } on DartdocOptionError catch (e) { stderr.writeln(' fatal error: ${e.message}'); stderr.writeln(''); diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart index b8eba96f65..844012e232 100644 --- a/lib/src/dartdoc_options.dart +++ b/lib/src/dartdoc_options.dart @@ -396,10 +396,10 @@ abstract class DartdocOption { bool get _isDouble => _kDoubleVal is T; - DartdocOption _parent; + DartdocOption _parent; /// The parent of this DartdocOption, or null if this is the root. - DartdocOption get parent => _parent; + DartdocOption get parent => _parent; final Map __yamlAtCanonicalPathCache = {}; @@ -424,18 +424,18 @@ abstract class DartdocOption { /// Throw [DartdocFileMissing] with a detailed error message indicating where /// the error came from when a file or directory option is missing. void _onMissing( - _OptionValueWithContext valueWithContext, String missingFilename); + _OptionValueWithContext valueWithContext, String missingFilename); /// Call [_onMissing] for every path that does not exist. - void _validatePaths(_OptionValueWithContext valueWithContext) { + void _validatePaths(_OptionValueWithContext valueWithContext) { if (!mustExist) return; assert(isDir || isFile); List resolvedPaths; var value = valueWithContext.value; if (value is String) { - resolvedPaths = [valueWithContext.resolvedValue]; + resolvedPaths = [valueWithContext.resolvedValue as String]; } else if (value is List) { - resolvedPaths = valueWithContext.resolvedValue as List; + resolvedPaths = valueWithContext.resolvedValue as List; } else if (value is Map) { resolvedPaths = (valueWithContext.resolvedValue as Map).values.toList(); } else { @@ -456,7 +456,7 @@ abstract class DartdocOption { /// For a [List] or [String] value, if [isDir] or [isFile] is set, /// resolve paths in value relative to canonicalPath. - T _handlePathsInContext(_OptionValueWithContext valueWithContext) { + T _handlePathsInContext(_OptionValueWithContext valueWithContext) { if (valueWithContext?.value == null || !(isDir || isFile || isGlob)) { return valueWithContext?.value; } @@ -472,15 +472,15 @@ abstract class DartdocOption { ArgResults get _argResults => root.__argResults; /// Set the parent of this [DartdocOption]. Do not call more than once. - set parent(DartdocOption newParent) { + set parent(DartdocOption newParent) { assert(_parent == null); _parent = newParent; } /// The root [DartdocOption] containing this object, or [this] if the object /// has no parent. - DartdocOption get root { - DartdocOption p = this; + DartdocOption get root { + DartdocOption p = this; while (p.parent != null) { p = p.parent; } @@ -490,7 +490,7 @@ abstract class DartdocOption { /// All object names starting at the root. Iterable get keys { var keyList = []; - DartdocOption option = this; + DartdocOption option = this; while (option?.name != null) { keyList.add(option.name); option = option.parent; @@ -499,7 +499,7 @@ abstract class DartdocOption { } /// Direct children of this node, mapped by name. - final Map> _children = {}; + final Map _children = {}; /// Return the calculated value of this option, given the directory as /// context. @@ -531,7 +531,7 @@ abstract class DartdocOption { resourceProvider.pathContext.basename(element.source.fullName)))); /// Adds a DartdocOption to the children of this DartdocOption. - void add(DartdocOption option) { + void add(DartdocOption option) { if (_children.containsKey(option.name)) { throw DartdocOptionError( 'Tried to add two children with the same name: ${option.name}'); @@ -545,7 +545,7 @@ abstract class DartdocOption { void _onAdd() {} /// Adds a list of dartdoc options to the children of this DartdocOption. - void addAll(Iterable> options) => options.forEach(add); + void addAll(Iterable options) => options.forEach(add); /// Get the immediate child of this node named [name]. DartdocOption operator [](String name) { @@ -553,7 +553,7 @@ abstract class DartdocOption { } /// Apply the function [visit] to [this] and all children. - void traverse(void Function(DartdocOption option) visit) { + void traverse(void Function(DartdocOption option) visit) { visit(this); _children.values.forEach((d) => d.traverse(visit)); } @@ -590,7 +590,7 @@ class DartdocOptionFileSynth extends DartdocOption @override void _onMissing( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { if (valueWithContext.definingFile != null) { _onMissingFromFiles(valueWithContext, missingPath); } else { @@ -632,7 +632,7 @@ class DartdocOptionArgSynth extends DartdocOption @override void _onMissing( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { _onMissingFromArgs(valueWithContext, missingPath); } @@ -687,12 +687,12 @@ abstract class DartdocSyntheticOption implements DartdocOption { } @override - void _onMissing(_OptionValueWithContext valueWithContext, - String missingPath) => + void _onMissing( + _OptionValueWithContext valueWithContext, String missingPath) => _onMissingFromSynthetic(valueWithContext, missingPath); void _onMissingFromSynthetic( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { var description = 'Synthetic configuration option $name from '; throw DartdocFileMissing( '$description, computed as ${valueWithContext.value}, resolves to ' @@ -700,7 +700,7 @@ abstract class DartdocSyntheticOption implements DartdocOption { } } -typedef OptionGenerator = Future>> Function( +typedef OptionGenerator = Future> Function( PackageMetaProvider); /// A [DartdocOption] that only contains other [DartdocOption]s and is not an @@ -734,13 +734,13 @@ class DartdocOptionSet extends DartdocOption { /// Since we have no value, [_onMissing] does nothing. @override - void _onMissing(_OptionValueWithContext valueWithContext, - String missingFilename) {} + void _onMissing( + _OptionValueWithContext valueWithContext, String missingFilename) {} /// Traverse skips this node, because it doesn't represent a real /// configuration object. @override - void traverse(void Function(DartdocOption option) visitor) { + void traverse(void Function(DartdocOption option) visitor) { _children.values.forEach((d) => d.traverse(visitor)); } } @@ -815,7 +815,7 @@ class DartdocOptionArgFile extends DartdocOption @override void _onMissing( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { if (valueWithContext.definingFile != null) { _onMissingFromFiles(valueWithContext, missingPath); } else { @@ -887,12 +887,12 @@ abstract class _DartdocFileOption implements DartdocOption { String get fieldName => keys.join('.'); @override - void _onMissing(_OptionValueWithContext valueWithContext, - String missingPath) => + void _onMissing( + _OptionValueWithContext valueWithContext, String missingPath) => _onMissingFromFiles(valueWithContext, missingPath); void _onMissingFromFiles( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { var dartdocYaml = resourceProvider.pathContext.join( valueWithContext.canonicalDirectoryPath, valueWithContext.definingFile); throw DartdocFileMissing('Field $fieldName from $dartdocYaml, set to ' @@ -914,7 +914,7 @@ abstract class _DartdocFileOption implements DartdocOption { T _valueAtFromFiles(Folder dir) { var key = resourceProvider.pathContext.canonicalize(dir.path); if (!__valueAtFromFiles.containsKey(key)) { - _OptionValueWithContext valueWithContext; + _OptionValueWithContext valueWithContext; if (parentDirOverridesChild) { valueWithContext = _valueAtFromFilesLastFound(dir); } else { @@ -927,8 +927,8 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files through parent directories, starting at /// [dir], for the option and returns one once found. - _OptionValueWithContext _valueAtFromFilesFirstFound(Folder folder) { - _OptionValueWithContext value; + _OptionValueWithContext _valueAtFromFilesFirstFound(Folder folder) { + _OptionValueWithContext value; for (var dir in folder.withAncestors) { value = _valueAtFromFile(dir); if (value != null) break; @@ -939,8 +939,8 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files for the option, and returns the value /// in the top-most parent directory `dartdoc_options.yaml` file it is /// mentioned in. - _OptionValueWithContext _valueAtFromFilesLastFound(Folder folder) { - _OptionValueWithContext value; + _OptionValueWithContext _valueAtFromFilesLastFound(Folder folder) { + _OptionValueWithContext value; for (var dir in folder.withAncestors) { var tmpValue = _valueAtFromFile(dir); if (tmpValue != null) value = tmpValue; @@ -950,7 +950,7 @@ abstract class _DartdocFileOption implements DartdocOption { /// Returns null if not set in the YAML file in this directory (or its /// parents). - _OptionValueWithContext _valueAtFromFile(Folder dir) { + _OptionValueWithContext _valueAtFromFile(Folder dir) { var yamlFileData = _yamlAtDirectory(dir); var contextPath = yamlFileData.canonicalDirectoryPath; Object yamlData = yamlFileData.data ?? {}; @@ -1081,12 +1081,12 @@ abstract class _DartdocArgOption implements DartdocOption { } @override - void _onMissing(_OptionValueWithContext valueWithContext, - String missingPath) => + void _onMissing( + _OptionValueWithContext valueWithContext, String missingPath) => _onMissingFromArgs(valueWithContext, missingPath); void _onMissingFromArgs( - _OptionValueWithContext valueWithContext, String missingPath) { + _OptionValueWithContext valueWithContext, String missingPath) { throw DartdocFileMissing( 'Argument --$argName, set to ${valueWithContext.value}, resolves to ' 'missing path: "$missingPath"'); @@ -1096,7 +1096,7 @@ abstract class _DartdocArgOption implements DartdocOption { /// the [argParser] and the working directory from [_directoryCurrent]. /// /// Throws [UnsupportedError] if [T] is not a supported type. - _OptionValueWithContext _valueAtFromArgsWithContext() { + _OptionValueWithContext _valueAtFromArgsWithContext() { if (!_argResults.wasParsed(argName)) return null; T retval; @@ -1215,21 +1215,23 @@ class DartdocOptionContext extends DartdocOptionContextBase // TODO(jcollins-g): Allow passing in structured data to initialize a // [DartdocOptionContext]'s arguments instead of having to parse strings // via optionSet. - /// If [entity] is null, assume this is the initialization case and use - /// the inputDir flag to determine the context. - DartdocOptionContext( - this.optionSet, Resource resource, ResourceProvider resourceProvider) { - if (resource == null) { - var current = resourceProvider.pathContext.current; - String inputDir = - optionSet['inputDir'].valueAt(resourceProvider.getFolder(current)) ?? - current; - context = resourceProvider.getFolder(inputDir); - } else { - context = resourceProvider.getFolder(resourceProvider.pathContext - .canonicalize( - resource is File ? resource.parent2.path : resource.path)); - } + DartdocOptionContext(this.optionSet, Resource contextLocation, + ResourceProvider resourceProvider) { + assert(contextLocation != null); + context = resourceProvider.getFolder(resourceProvider.pathContext + .canonicalize(contextLocation is File + ? contextLocation.parent2.path + : contextLocation.path)); + } + + /// Build a DartdocOptionContext via the 'inputDir' command line option. + DartdocOptionContext.fromDefaultContextLocation( + this.optionSet, ResourceProvider resourceProvider) { + var current = resourceProvider.pathContext.current; + String inputDir = + optionSet['inputDir'].valueAt(resourceProvider.getFolder(current)) ?? + current; + context = resourceProvider.getFolder(inputDir); } /// Build a DartdocOptionContext from an analyzer element (using its source @@ -1366,7 +1368,7 @@ class DartdocOptionContext extends DartdocOptionContextBase /// Instantiate dartdoc's configuration file and options parser with the /// given command line arguments. -Future>> createDartdocOptions( +Future> createDartdocOptions( PackageMetaProvider packageMetaProvider, ) async { var resourceProvider = packageMetaProvider.resourceProvider; diff --git a/test/end2end/dartdoc_test.dart b/test/end2end/dartdoc_test.dart index 91ccfc83f1..2e90715203 100644 --- a/test/end2end/dartdoc_test.dart +++ b/test/end2end/dartdoc_test.dart @@ -55,8 +55,8 @@ Future _generatorContextFromArgv( ], pubPackageMetaProvider); optionSet.parseArguments(argv); - return DartdocGeneratorOptionContext( - optionSet, null, pubPackageMetaProvider.resourceProvider); + return DartdocGeneratorOptionContext.fromDefaultContextLocation( + optionSet, pubPackageMetaProvider.resourceProvider); } class DartdocLoggingOptionContext extends DartdocGeneratorOptionContext diff --git a/test/mustachio/renderers_output_test.dart b/test/mustachio/renderers_output_test.dart index b1c3ec4446..89bbc0ebea 100644 --- a/test/mustachio/renderers_output_test.dart +++ b/test/mustachio/renderers_output_test.dart @@ -27,8 +27,8 @@ Future _generatorContextFromArgv( ], pubPackageMetaProvider); optionSet.parseArguments(argv); - return DartdocGeneratorOptionContext( - optionSet, null, pubPackageMetaProvider.resourceProvider); + return DartdocGeneratorOptionContext.fromDefaultContextLocation( + optionSet, pubPackageMetaProvider.resourceProvider); } void main() { diff --git a/test/src/utils.dart b/test/src/utils.dart index 779fc77839..be6bd69529 100644 --- a/test/src/utils.dart +++ b/test/src/utils.dart @@ -34,14 +34,11 @@ final Folder testPackageToolError = _resourceProvider.getFolder(_pathContext /// [DartdocOptionSet] based on the current working directory. Future contextFromArgv( List argv, PackageMetaProvider packageMetaProvider) async { - var resourceProvider = packageMetaProvider.resourceProvider; var optionSet = await DartdocOptionSet.fromOptionGenerators( 'dartdoc', [createDartdocOptions], packageMetaProvider); optionSet.parseArguments(argv); - return DartdocOptionContext( - optionSet, - resourceProvider.getFolder(resourceProvider.pathContext.current), - pubPackageMetaProvider.resourceProvider); + return DartdocOptionContext.fromDefaultContextLocation( + optionSet, pubPackageMetaProvider.resourceProvider); } Future bootBasicPackage( From 038b59fab38e43f006c7ccea4b7f468bc2eb5a45 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Wed, 18 Aug 2021 16:15:09 -0700 Subject: [PATCH 3/8] flatten --- lib/options.dart | 26 +- lib/src/dartdoc_options.dart | 455 ++++++++---------- .../templates.runtime_renderers.dart | 2 +- lib/src/logging.dart | 2 +- lib/src/warnings.dart | 7 + test/dartdoc_options_test.dart | 16 +- test/documentation_comment_test.dart | 2 +- test/end2end/dartdoc_test.dart | 8 +- test/mustachio/renderers_output_test.dart | 2 +- test/package_test.dart | 2 +- test/src/utils.dart | 2 +- test/warnings_test.dart | 2 +- 12 files changed, 245 insertions(+), 281 deletions(-) diff --git a/lib/options.dart b/lib/options.dart index 85fdfa67e0..195510823e 100644 --- a/lib/options.dart +++ b/lib/options.dart @@ -10,8 +10,8 @@ import 'package:dartdoc/src/package_meta.dart'; /// Helper class that consolidates option contexts for instantiating generators. class DartdocGeneratorOptionContext extends DartdocOptionContext { - DartdocGeneratorOptionContext(DartdocOptionSet optionSet, Folder? dir, - ResourceProvider resourceProvider) + DartdocGeneratorOptionContext( + DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider) : super(optionSet, dir, resourceProvider); DartdocGeneratorOptionContext.fromDefaultContextLocation( DartdocOptionSet optionSet, ResourceProvider resourceProvider) @@ -51,8 +51,8 @@ class DartdocGeneratorOptionContext extends DartdocOptionContext { class DartdocProgramOptionContext extends DartdocGeneratorOptionContext with LoggingContext { - DartdocProgramOptionContext(DartdocOptionSet optionSet, Folder? dir, - ResourceProvider resourceProvider) + DartdocProgramOptionContext( + DartdocOptionSet optionSet, Folder dir, ResourceProvider resourceProvider) : super(optionSet, dir, resourceProvider); DartdocProgramOptionContext.fromDefaultContextLocation( DartdocOptionSet optionSet, ResourceProvider resourceProvider) @@ -84,7 +84,7 @@ Future parseOptions( List arguments, { OptionGenerator? additionalOptions, }) async { - var optionSet = await DartdocOptionSet.fromOptionGenerators( + var optionRoot = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [ createDartdocOptions, @@ -96,22 +96,22 @@ Future parseOptions( packageMetaProvider); try { - optionSet.parseArguments(arguments); + optionRoot.parseArguments(arguments); } on FormatException catch (e) { stderr.writeln(' fatal error: ${e.message}'); stderr.writeln(''); - _printUsage(optionSet.argParser); + _printUsage(optionRoot.argParser); // Do not use exit() as this bypasses --pause-isolates-on-exit exitCode = 64; return null; } - if (optionSet['help'].valueAtCurrent()) { - _printHelp(optionSet.argParser); + if (optionRoot['help'].valueAtCurrent()) { + _printHelp(optionRoot.argParser); exitCode = 0; return null; } - if (optionSet['version'].valueAtCurrent()) { - _printVersion(optionSet.argParser); + if (optionRoot['version'].valueAtCurrent()) { + _printVersion(optionRoot.argParser); exitCode = 0; return null; } @@ -119,12 +119,12 @@ Future parseOptions( DartdocProgramOptionContext config; try { config = DartdocProgramOptionContext.fromDefaultContextLocation( - optionSet, packageMetaProvider.resourceProvider); + optionRoot, packageMetaProvider.resourceProvider); } on DartdocOptionError catch (e) { stderr.writeln(' fatal error: ${e.message}'); stderr.writeln(''); await stderr.flush(); - _printUsage(optionSet.argParser); + _printUsage(optionRoot.argParser); exitCode = 64; return null; } diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart index a5ecfca71c..4ecf4b175f 100644 --- a/lib/src/dartdoc_options.dart +++ b/lib/src/dartdoc_options.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// @dart=2.9 - /// /// dartdoc's dartdoc_options.yaml configuration file follows similar loading /// semantics to that of analysis_options.yaml, @@ -43,7 +41,7 @@ const bool _kBoolVal = true; const String compileArgsTagName = 'compile_args'; -int get _usageLineLength => stdout.hasTerminal ? stdout.terminalColumns : null; +int get _usageLineLength => stdout.hasTerminal ? stdout.terminalColumns : 80; typedef ConvertYamlToType = T Function(YamlMap, String, ResourceProvider); @@ -63,11 +61,11 @@ class CategoryDefinition { final String name; /// Displayed name of the category in docs, or null if there is none. - final String _displayName; + final String? _displayName; /// Canonical path of the markdown file used to document this category /// (or null if undocumented). - final String documentationMarkdown; + final String? documentationMarkdown; CategoryDefinition(this.name, this._displayName, this.documentationMarkdown); @@ -92,12 +90,10 @@ class CategoryConfiguration { var newCategoryDefinitions = {}; for (var entry in yamlMap.entries) { var name = entry.key.toString(); - String displayName; - String documentationMarkdown; var categoryMap = entry.value; if (categoryMap is Map) { - displayName = categoryMap['displayName']?.toString(); - documentationMarkdown = categoryMap['markdown']?.toString(); + var displayName = categoryMap['displayName']?.toString(); + var documentationMarkdown = categoryMap['markdown']?.toString(); if (documentationMarkdown != null) { documentationMarkdown = resourceProvider.pathContext.canonicalize( resourceProvider.pathContext @@ -122,9 +118,7 @@ class ToolConfiguration { final ResourceProvider resourceProvider; - ToolRunner _runner; - - ToolRunner get runner => _runner ??= ToolRunner(this); + late ToolRunner runner = ToolRunner(this); ToolConfiguration._(this.tools, this.resourceProvider); @@ -140,14 +134,14 @@ class ToolConfiguration { for (var entry in yamlMap.entries) { var name = entry.key.toString(); var toolMap = entry.value; - List compileArgs; - String description; - List command; - List setupCommand; + String? description; + List? compileArgs; + List? command; + List? setupCommand; if (toolMap is Map) { - description = toolMap['description']?.toString(); - List findCommand([String prefix = '']) { - List command; + description = toolMap['description'].toString(); + List? findCommand([String prefix = '']) { + List? command; // If the command key is given, then it applies to all platforms. var commandFromKey = toolMap.containsKey('${prefix}command') ? '${prefix}command' @@ -183,8 +177,8 @@ class ToolConfiguration { command = findCommand(); setupCommand = findCommand('setup_'); - List findArgs() { - List args; + List? findArgs() { + List? args; if (toolMap.containsKey(compileArgsTagName)) { var compileArgs = toolMap[compileArgsTagName]; if (compileArgs is String) { @@ -289,7 +283,7 @@ class _OptionValueWithContext { String canonicalDirectoryPath; /// If non-null, the basename of the configuration file the value came from. - String definingFile; + String? definingFile; /// A [pathLib.Context] variable initialized with canonicalDirectoryPath. p.Context pathContext; @@ -298,10 +292,9 @@ class _OptionValueWithContext { /// /// [path] is the path where this value came from (not required to be /// canonical). - _OptionValueWithContext(this.value, String path, {this.definingFile}) { - canonicalDirectoryPath = p.canonicalize(path); - pathContext = p.Context(current: canonicalDirectoryPath); - } + _OptionValueWithContext(this.value, String path, {this.definingFile}) + : canonicalDirectoryPath = p.canonicalize(path), + pathContext = p.Context(current: p.canonicalize(path)); /// Assume value is a path, and attempt to resolve it. /// @@ -341,7 +334,7 @@ class _OptionValueWithContext { /// [DartdocOptionArgOnly], and [DartdocOptionFileOnly]. abstract class DartdocOption { /// This is the value returned if we couldn't find one otherwise. - final T defaultsTo; + final T? defaultsTo; /// Text string for help passed on in command line options. final String help; @@ -379,7 +372,7 @@ abstract class DartdocOption { } /// Closure to convert yaml data into some other structure. - ConvertYamlToType _convertYamlToType; + final ConvertYamlToType? _convertYamlToType; // The choice not to use reflection means there's some ugly type checking, // somewhat more ugly than we'd have to do anyway to automatically convert @@ -398,11 +391,6 @@ abstract class DartdocOption { bool get _isDouble => _kDoubleVal is T; - DartdocOption _parent; - - /// The parent of this DartdocOption, or null if this is the root. - DartdocOption get parent => _parent; - final Map __yamlAtCanonicalPathCache = {}; /// Implementation detail for [DartdocOptionFileOnly]. Make sure we use @@ -410,19 +398,6 @@ abstract class DartdocOption { Map get _yamlAtCanonicalPathCache => root.__yamlAtCanonicalPathCache; - final ArgParser __argParser = ArgParser(usageLineLength: _usageLineLength); - - ArgParser get argParser => root.__argParser; - - ArgResults __argResults; - - /// Parse these as string arguments (from argv) with the argument parser. - /// Call before calling [valueAt] for any [DartdocOptionArgOnly] or - /// [DartdocOptionArgFile] in this tree. - void _parseArguments(List arguments) { - __argResults = argParser.parse(arguments); - } - /// Throw [DartdocFileMissing] with a detailed error message indicating where /// the error came from when a file or directory option is missing. void _onMissing( @@ -432,14 +407,15 @@ abstract class DartdocOption { void _validatePaths(_OptionValueWithContext valueWithContext) { if (!mustExist) return; assert(isDir || isFile); - List resolvedPaths; + var resolvedPaths = []; var value = valueWithContext.value; if (value is String) { resolvedPaths = [valueWithContext.resolvedValue as String]; } else if (value is List) { resolvedPaths = valueWithContext.resolvedValue as List; } else if (value is Map) { - resolvedPaths = (valueWithContext.resolvedValue as Map).values.toList(); + resolvedPaths = (valueWithContext.resolvedValue as Map).values.toList() + as List; } else { assert( false, @@ -458,11 +434,11 @@ abstract class DartdocOption { /// For a [List] or [String] value, if [isDir] or [isFile] is set, /// resolve paths in value relative to canonicalPath. - T _handlePathsInContext(_OptionValueWithContext valueWithContext) { + T? _handlePathsInContext(_OptionValueWithContext? valueWithContext) { if (valueWithContext?.value == null || !(isDir || isFile || isGlob)) { return valueWithContext?.value; } - _validatePaths(valueWithContext); + _validatePaths(valueWithContext!); return valueWithContext.resolvedValue; } @@ -473,17 +449,14 @@ abstract class DartdocOption { ArgResults get _argResults => root.__argResults; - /// Set the parent of this [DartdocOption]. Do not call more than once. - set parent(DartdocOption newParent) { - assert(_parent == null); - _parent = newParent; - } + /// To avoid accessing early, call [add] on the option's parent before + /// looking up unless this is a [DartdocRootOption]. + late final DartdocOption parent; - /// The root [DartdocOption] containing this object, or [this] if the object - /// has no parent. - DartdocOption get root { + /// The [DartdocOptionRoot] containing this object. + DartdocOptionRoot get root { DartdocOption p = this; - while (p.parent != null) { + while (p is! DartdocOptionRoot) { p = p.parent; } return p; @@ -493,10 +466,11 @@ abstract class DartdocOption { Iterable get keys { var keyList = []; DartdocOption option = this; - while (option?.name != null) { + while (option is! DartdocOptionRoot) { keyList.add(option.name); option = option.parent; } + keyList.add(option.name); return keyList.reversed; } @@ -514,23 +488,15 @@ abstract class DartdocOption { /// type. If [mustExist] is true, will throw [DartdocFileMissing] for command /// line parameters and file paths in config files that don't point to /// corresponding files or directories. - T valueAt(Folder dir); + T? valueAt(Folder dir); /// Calls [valueAt] with the working directory at the start of the program. - T valueAtCurrent() => valueAt(_directoryCurrent); - - Folder __directoryCurrent; - Folder get _directoryCurrent => - __directoryCurrent ??= resourceProvider.getFolder(_directoryCurrentPath); - - String __directoryCurrentPath; - String get _directoryCurrentPath => - __directoryCurrentPath ??= resourceProvider.pathContext.current; + T? valueAtCurrent() => valueAt(_directoryCurrent); - /// Calls [valueAt] on the directory this element is defined in. - T valueAtElement(Element element) => - valueAt(resourceProvider.getFolder(resourceProvider.pathContext.normalize( - resourceProvider.pathContext.basename(element.source.fullName)))); + late final Folder _directoryCurrent = + resourceProvider.getFolder(_directoryCurrentPath); + late final String _directoryCurrentPath = + resourceProvider.pathContext.current; /// Adds a DartdocOption to the children of this DartdocOption. void add(DartdocOption option) { @@ -539,19 +505,20 @@ abstract class DartdocOption { 'Tried to add two children with the same name: ${option.name}'); } _children[option.name] = option; + // TODO(jcollins-g): Consider a stronger refactor that doesn't rely on + // post-construction setup for [parent]. option.parent = this; - option.traverse((option) => option._onAdd()); } - /// This method is guaranteed to be called when [this] or any parent is added. - void _onAdd() {} + /// This method is called when parsing options to set up the [ArgParser]. + void _addToArgParser(ArgParser argParser) {} /// Adds a list of dartdoc options to the children of this DartdocOption. void addAll(Iterable options) => options.forEach(add); /// Get the immediate child of this node named [name]. DartdocOption operator [](String name) { - return _children[name]; + return _children[name]!; } /// Apply the function [visit] to [this] and all children. @@ -565,7 +532,8 @@ abstract class DartdocOption { /// overridden by a file. class DartdocOptionFileSynth extends DartdocOption with DartdocSyntheticOption, _DartdocFileOption { - bool _parentDirOverridesChild; + @override + final bool parentDirOverridesChild; @override final T Function(DartdocSyntheticOption, Folder) _compute; @@ -574,15 +542,13 @@ class DartdocOptionFileSynth extends DartdocOption {bool mustExist = false, String help = '', OptionKind optionIs = OptionKind.other, - bool parentDirOverridesChild, - ConvertYamlToType convertYamlToType}) + this.parentDirOverridesChild = false, + ConvertYamlToType? convertYamlToType}) : super(name, null, help, optionIs, mustExist, convertYamlToType, - resourceProvider) { - _parentDirOverridesChild = parentDirOverridesChild; - } + resourceProvider); @override - T valueAt(Folder dir) { + T? valueAt(Folder dir) { var result = _valueAtFromFile(dir); if (result?.definingFile != null) { return _handlePathsInContext(result); @@ -599,37 +565,35 @@ class DartdocOptionFileSynth extends DartdocOption _onMissingFromSynthetic(valueWithContext, missingPath); } } - - @override - bool get parentDirOverridesChild => _parentDirOverridesChild; } /// A class that defaults to a value computed from a closure, but can /// be overridden on the command line. class DartdocOptionArgSynth extends DartdocOption with DartdocSyntheticOption, _DartdocArgOption { - String _abbr; - bool _hide; - bool _negatable; - bool _splitCommas; + @override + final String? abbr; + @override + final bool hide; + @override + final bool negatable; + @override + final bool splitCommas; @override final T Function(DartdocSyntheticOption, Folder) _compute; DartdocOptionArgSynth( String name, this._compute, ResourceProvider resourceProvider, - {String abbr, + {this.abbr, bool mustExist = false, String help = '', - bool hide = false, + this.hide = false, OptionKind optionIs = OptionKind.other, - bool negatable = false, - bool splitCommas}) + this.negatable = false, + this.splitCommas = false}) : super(name, null, help, optionIs, mustExist, null, resourceProvider) { - _hide = hide; - _negatable = negatable; - _splitCommas = splitCommas; - _abbr = abbr; + assert(T is! Iterable || splitCommas == true); } @override @@ -639,24 +603,12 @@ class DartdocOptionArgSynth extends DartdocOption } @override - T valueAt(Folder dir) { + T? valueAt(Folder dir) { if (_argResults.wasParsed(argName)) { return _valueAtFromArgs(); } return _valueAtFromSynthetic(dir); } - - @override - String get abbr => _abbr; - - @override - bool get hide => _hide; - - @override - bool get negatable => _negatable; - - @override - bool get splitCommas => _splitCommas; } /// A synthetic option takes a closure at construction time that computes @@ -681,9 +633,9 @@ abstract class DartdocSyntheticOption implements DartdocOption { T Function(DartdocSyntheticOption, Folder) get _compute; @override - T valueAt(Folder dir) => _valueAtFromSynthetic(dir); + T? valueAt(Folder dir) => _valueAtFromSynthetic(dir); - T _valueAtFromSynthetic(Folder dir) { + T? _valueAtFromSynthetic(Folder dir) { var context = _OptionValueWithContext(_compute(this, dir), dir.path); return _handlePathsInContext(context); } @@ -705,12 +657,13 @@ abstract class DartdocSyntheticOption implements DartdocOption { typedef OptionGenerator = Future> Function( PackageMetaProvider); -/// A [DartdocOption] that only contains other [DartdocOption]s and is not an -/// option itself. -class DartdocOptionSet extends DartdocOption { - DartdocOptionSet(String name, ResourceProvider resourceProvider) - : super( - name, null, null, OptionKind.other, false, null, resourceProvider); +/// This is a [DartdocOptionSet] used as a root node. +class DartdocOptionRoot extends DartdocOptionSet { + DartdocOptionRoot(String name, ResourceProvider resourceProvider) + : super(name, resourceProvider); + + late final ArgParser __argParser = + ArgParser(usageLineLength: _usageLineLength); /// Asynchronous factory that is the main entry point to initialize Dartdoc /// options for use. @@ -718,26 +671,37 @@ class DartdocOptionSet extends DartdocOption { /// [name] is the top level key for the option set. /// [optionGenerators] is a sequence of asynchronous functions that return /// [DartdocOption]s that will be added to the new option set. - static Future fromOptionGenerators( + static Future fromOptionGenerators( String name, Iterable optionGenerators, PackageMetaProvider packageMetaProvider) async { var optionSet = - DartdocOptionSet(name, packageMetaProvider.resourceProvider); + DartdocOptionRoot(name, packageMetaProvider.resourceProvider); for (var generator in optionGenerators) { optionSet.addAll(await generator(packageMetaProvider)); } return optionSet; } - /// [DartdocOptionSet] always has the null value. - @override - void valueAt(Folder dir) => null; + ArgParser get argParser => __argParser; - /// Since we have no value, [_onMissing] does nothing. - @override - void _onMissing( - _OptionValueWithContext valueWithContext, String missingFilename) {} + /// Initialized via [_parseArguments]. + late ArgResults __argResults; + + bool _argParserInitialized = false; + + /// Parse these as string arguments (from argv) with the argument parser. + /// Call before calling [valueAt] for any [DartdocOptionArgOnly] or + /// [DartdocOptionArgFile] in this tree. + void _parseArguments(List arguments) { + if (!_argParserInitialized) { + _argParserInitialized = true; + traverse((DartdocOption option) { + option._addToArgParser(argParser); + }); + } + __argResults = argParser.parse(arguments); + } /// Traverse skips this node, because it doesn't represent a real /// configuration object. @@ -745,75 +709,81 @@ class DartdocOptionSet extends DartdocOption { void traverse(void Function(DartdocOption option) visitor) { _children.values.forEach((d) => d.traverse(visitor)); } + + @override + DartdocOption get parent => + throw UnsupportedError('Root nodes have no parent'); +} + +/// A [DartdocOption] that only contains other [DartdocOption]s and is not an +/// option itself. +class DartdocOptionSet extends DartdocOption { + DartdocOptionSet(String name, ResourceProvider resourceProvider) + : super(name, null, '', OptionKind.other, false, null, resourceProvider); + + /// [DartdocOptionSet] always has the null value. + @override + void valueAt(Folder dir) => null; + + /// Since we have no value, [_onMissing] does nothing. + @override + void _onMissing( + _OptionValueWithContext valueWithContext, String missingFilename) {} } /// A [DartdocOption] that only exists as a command line argument. `--help` is a /// good example. class DartdocOptionArgOnly extends DartdocOption with _DartdocArgOption { - String _abbr; - bool _hide; - bool _negatable; - bool _splitCommas; + @override + final String? abbr; + @override + final bool hide; + @override + final bool negatable; + @override + final bool splitCommas; DartdocOptionArgOnly( String name, T defaultsTo, ResourceProvider resourceProvider, - {String abbr, + {this.abbr, bool mustExist = false, String help = '', - bool hide = false, + this.hide = false, OptionKind optionIs = OptionKind.other, - bool negatable = false, - bool splitCommas}) + this.negatable = false, + this.splitCommas = false}) : super(name, defaultsTo, help, optionIs, mustExist, null, - resourceProvider) { - _hide = hide; - _negatable = negatable; - _splitCommas = splitCommas; - _abbr = abbr; - } - - @override - String get abbr => _abbr; - - @override - bool get hide => _hide; - - @override - bool get negatable => _negatable; - - @override - bool get splitCommas => _splitCommas; + resourceProvider); } /// A [DartdocOption] that works with command line arguments and /// `dartdoc_options` files. class DartdocOptionArgFile extends DartdocOption with _DartdocArgOption, _DartdocFileOption { - String _abbr; - bool _hide; - bool _negatable; - bool _parentDirOverridesChild; - bool _splitCommas; + @override + final String? abbr; + @override + final bool hide; + @override + final bool negatable; + @override + final bool parentDirOverridesChild; + @override + final bool splitCommas; DartdocOptionArgFile( String name, T defaultsTo, ResourceProvider resourceProvider, - {String abbr, + {this.abbr, bool mustExist = false, String help = '', - bool hide = false, + this.hide = false, OptionKind optionIs = OptionKind.other, - bool negatable = false, - bool parentDirOverridesChild = false, - bool splitCommas}) + this.negatable = false, + this.parentDirOverridesChild = false, + this.splitCommas = false}) : super(name, defaultsTo, help, optionIs, mustExist, null, - resourceProvider) { - _abbr = abbr; - _hide = hide; - _negatable = negatable; - _parentDirOverridesChild = parentDirOverridesChild; - _splitCommas = splitCommas; - } + resourceProvider); @override void _onMissing( @@ -828,47 +798,28 @@ class DartdocOptionArgFile extends DartdocOption /// Try to find an explicit argument setting this value, but if not, fall back /// to files finally, the default. @override - T valueAt(Folder dir) { + T? valueAt(Folder dir) { var value = _valueAtFromArgs(); value ??= _valueAtFromFiles(dir); value ??= defaultsTo; return value; } - - @override - String get abbr => _abbr; - - @override - bool get hide => _hide; - - @override - bool get negatable => _negatable; - - @override - bool get parentDirOverridesChild => _parentDirOverridesChild; - - @override - bool get splitCommas => _splitCommas; } class DartdocOptionFileOnly extends DartdocOption with _DartdocFileOption { - bool _parentDirOverridesChild; + @override + final bool parentDirOverridesChild; DartdocOptionFileOnly( String name, T defaultsTo, ResourceProvider resourceProvider, {bool mustExist = false, String help = '', OptionKind optionIs = OptionKind.other, - bool parentDirOverridesChild = false, - ConvertYamlToType convertYamlToType}) + this.parentDirOverridesChild = false, + ConvertYamlToType? convertYamlToType}) : super(name, defaultsTo, help, optionIs, mustExist, convertYamlToType, - resourceProvider) { - _parentDirOverridesChild = parentDirOverridesChild; - } - - @override - bool get parentDirOverridesChild => _parentDirOverridesChild; + resourceProvider); } /// Implements checking for options contained in dartdoc.yaml. @@ -905,18 +856,18 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches for a value in configuration files relative to [dir], and if not /// found, returns [defaultsTo]. - T valueAt(Folder dir) { + T? valueAt(Folder dir) { return _valueAtFromFiles(dir) ?? defaultsTo; } - final Map __valueAtFromFiles = {}; + final Map __valueAtFromFiles = {}; // The value of this option from files will not change unless files are // modified during execution (not allowed in Dartdoc). - T _valueAtFromFiles(Folder dir) { + T? _valueAtFromFiles(Folder dir) { var key = resourceProvider.pathContext.canonicalize(dir.path); if (!__valueAtFromFiles.containsKey(key)) { - _OptionValueWithContext valueWithContext; + _OptionValueWithContext? valueWithContext; if (parentDirOverridesChild) { valueWithContext = _valueAtFromFilesLastFound(dir); } else { @@ -929,8 +880,8 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files through parent directories, starting at /// [dir], for the option and returns one once found. - _OptionValueWithContext _valueAtFromFilesFirstFound(Folder folder) { - _OptionValueWithContext value; + _OptionValueWithContext? _valueAtFromFilesFirstFound(Folder folder) { + _OptionValueWithContext? value; for (var dir in folder.withAncestors) { value = _valueAtFromFile(dir); if (value != null) break; @@ -941,8 +892,8 @@ abstract class _DartdocFileOption implements DartdocOption { /// Searches all dartdoc_options files for the option, and returns the value /// in the top-most parent directory `dartdoc_options.yaml` file it is /// mentioned in. - _OptionValueWithContext _valueAtFromFilesLastFound(Folder folder) { - _OptionValueWithContext value; + _OptionValueWithContext? _valueAtFromFilesLastFound(Folder folder) { + _OptionValueWithContext? value; for (var dir in folder.withAncestors) { var tmpValue = _valueAtFromFile(dir); if (tmpValue != null) value = tmpValue; @@ -952,16 +903,16 @@ abstract class _DartdocFileOption implements DartdocOption { /// Returns null if not set in the YAML file in this directory (or its /// parents). - _OptionValueWithContext _valueAtFromFile(Folder dir) { + _OptionValueWithContext? _valueAtFromFile(Folder dir) { var yamlFileData = _yamlAtDirectory(dir); var contextPath = yamlFileData.canonicalDirectoryPath; - Object yamlData = yamlFileData.data ?? {}; + Object yamlData = yamlFileData.data; for (var key in keys) { if (yamlData is Map && !yamlData.containsKey(key)) return null; yamlData = (yamlData as Map)[key] ?? {}; } - Object returnData; + Object? returnData; if (_isListString) { if (yamlData is YamlList) { returnData = [ @@ -969,6 +920,7 @@ abstract class _DartdocFileOption implements DartdocOption { ]; } } else if (yamlData is YamlMap) { + var convertYamlToType = _convertYamlToType; // TODO(jcollins-g): This special casing is unfortunate. Consider // a refactor to extract yaml data conversion into closures 100% of the // time or find a cleaner way to do this. @@ -976,8 +928,8 @@ abstract class _DartdocFileOption implements DartdocOption { // A refactor probably would integrate resolvedValue for // _OptionValueWithContext into the return data here, and would not have // that be separate. - if (_isMapString && _convertYamlToType == null) { - _convertYamlToType = (YamlMap yamlMap, String canonicalYamlPath, + if (_isMapString && convertYamlToType == null) { + convertYamlToType = (YamlMap yamlMap, String canonicalYamlPath, ResourceProvider resourceProvider) { var returnData = {}; for (var entry in yamlMap.entries) { @@ -986,15 +938,15 @@ abstract class _DartdocFileOption implements DartdocOption { return returnData as T; }; } - if (_convertYamlToType == null) { + if (convertYamlToType == null) { throw DartdocOptionError( 'Unable to convert yaml to type for option: $fieldName, method not ' 'defined'); } var canonicalDirectoryPath = resourceProvider.pathContext.canonicalize(contextPath); - returnData = _convertYamlToType( - yamlData, canonicalDirectoryPath, resourceProvider); + returnData = + convertYamlToType(yamlData, canonicalDirectoryPath, resourceProvider); } else if (_isDouble) { if (yamlData is num) { returnData = yamlData.toDouble(); @@ -1018,7 +970,7 @@ abstract class _DartdocFileOption implements DartdocOption { var canonicalPath = resourceProvider.pathContext.canonicalize(folder.path); if (_yamlAtCanonicalPathCache.containsKey(canonicalPath)) { - yamlData = _yamlAtCanonicalPathCache[canonicalPath]; + yamlData = _yamlAtCanonicalPathCache[canonicalPath]!; break; } canonicalPaths.add(canonicalPath); @@ -1054,12 +1006,12 @@ abstract class _DartdocArgOption implements DartdocOption { /// For [ArgParser], set to a single character to have a short version of the /// command line argument. - String get abbr; + String? get abbr; /// valueAt for arguments ignores the [dir] parameter and only uses command /// line arguments and the current working directory to resolve the result. @override - T valueAt(Folder dir) => _valueAtFromArgs() ?? defaultsTo; + T? valueAt(Folder dir) => _valueAtFromArgs() ?? defaultsTo; /// For passing in to [int.parse] and [double.parse] `onError'. void _throwErrorForTypes(String value) { @@ -1070,6 +1022,9 @@ abstract class _DartdocArgOption implements DartdocOption { example = '32'; } else if (_isDouble) { example = '0.76'; + } else { + throw UnimplementedError( + 'Type for $name is not implemented in $_throwErrorForTypes'); } throw DartdocOptionError( 'Invalid argument value: --$argName, set to "$value", must be a ' @@ -1077,7 +1032,7 @@ abstract class _DartdocArgOption implements DartdocOption { } /// Returns null if no argument was given on the command line. - T _valueAtFromArgs() { + T? _valueAtFromArgs() { var valueWithContext = _valueAtFromArgsWithContext(); return _handlePathsInContext(valueWithContext); } @@ -1098,7 +1053,7 @@ abstract class _DartdocArgOption implements DartdocOption { /// the [argParser] and the working directory from [_directoryCurrent]. /// /// Throws [UnsupportedError] if [T] is not a supported type. - _OptionValueWithContext _valueAtFromArgsWithContext() { + _OptionValueWithContext? _valueAtFromArgsWithContext() { if (!_argResults.wasParsed(argName)) return null; T retval; @@ -1145,7 +1100,8 @@ abstract class _DartdocArgOption implements DartdocOption { final camelCaseRegexp = RegExp(r'([a-z])([A-Z])(?=([a-z]))'); argName = argName.replaceAllMapped(camelCaseRegexp, (Match m) { var before = m.group(1); - var after = m.group(2).toLowerCase(); + // Group 2 is not optional. + var after = m.group(2)!.toLowerCase(); return '$before-$after'; }); return argName; @@ -1155,14 +1111,14 @@ abstract class _DartdocArgOption implements DartdocOption { /// [ArgParser.addFlag], [ArgParser.addOption], or [ArgParser.addMultiOption] /// as appropriate for [T]. @override - void _onAdd() { + void _addToArgParser(ArgParser argParser) { if (_isBool) { argParser.addFlag(argName, abbr: abbr, defaultsTo: defaultsTo as bool, help: help, hide: hide, - negatable: negatable ?? false); + negatable: negatable); } else if (_isInt || _isDouble || _isString) { argParser.addOption(argName, abbr: abbr, @@ -1212,29 +1168,25 @@ class DartdocOptionContext extends DartdocOptionContextBase @override final DartdocOptionSet optionSet; @override - Folder context; + final Folder context; // TODO(jcollins-g): Allow passing in structured data to initialize a // [DartdocOptionContext]'s arguments instead of having to parse strings // via optionSet. DartdocOptionContext(this.optionSet, Resource contextLocation, - ResourceProvider resourceProvider) { - assert(contextLocation != null); - context = resourceProvider.getFolder(resourceProvider.pathContext - .canonicalize(contextLocation is File - ? contextLocation.parent2.path - : contextLocation.path)); - } + ResourceProvider resourceProvider) + : context = resourceProvider.getFolder(resourceProvider.pathContext + .canonicalize(contextLocation is File + ? contextLocation.parent2.path + : contextLocation.path)); /// Build a DartdocOptionContext via the 'inputDir' command line option. DartdocOptionContext.fromDefaultContextLocation( - this.optionSet, ResourceProvider resourceProvider) { - var current = resourceProvider.pathContext.current; - String inputDir = - optionSet['inputDir'].valueAt(resourceProvider.getFolder(current)) ?? - current; - context = resourceProvider.getFolder(inputDir); - } + this.optionSet, ResourceProvider resourceProvider) + : context = resourceProvider.getFolder(optionSet['inputDir'].valueAt( + resourceProvider + .getFolder(resourceProvider.pathContext.current)) ?? + resourceProvider.pathContext.current); /// Build a DartdocOptionContext from an analyzer element (using its source /// location). @@ -1282,13 +1234,9 @@ class DartdocOptionContext extends DartdocOptionContextBase String get examplePathPrefix => optionSet['examplePathPrefix'].valueAt(context); - /// A memoized calculation of exclusions. // TODO(srawlins): This memoization saved a lot of time in unit testing, but // is the first value in this class to be memoized. Memoize others? - /*late final*/ List _exclude; - - List get exclude => - _exclude ??= optionSet['exclude'].valueAt(context); + late final List exclude = optionSet['exclude'].valueAt(context); List get excludePackages => optionSet['excludePackages'].valueAt(context); @@ -1388,6 +1336,7 @@ Future> createDartdocOptions( 'in the current package or "include-external"', negatable: true), DartdocOptionArgFile>('categoryOrder', [], resourceProvider, + splitCommas: true, help: 'A list of categories (not package names) to place first when ' "grouping symbols on dartdoc's sidebar. Unmentioned categories are " 'sorted after these.'), @@ -1421,7 +1370,7 @@ Future> createDartdocOptions( return []; }, resourceProvider, help: 'Remove text from libraries with the following names.'), - DartdocOptionArgFile('examplePathPrefix', null, resourceProvider, + DartdocOptionArgFile('examplePathPrefix', null, resourceProvider, optionIs: OptionKind.dir, help: 'Prefix for @example paths.\n(defaults to the project root)', mustExist: true), @@ -1456,8 +1405,7 @@ Future> createDartdocOptions( negatable: true), DartdocOptionArgFile>('include', [], resourceProvider, help: 'Library names to generate docs for.', splitCommas: true), - DartdocOptionArgFile>( - 'includeExternal', null, resourceProvider, + DartdocOptionArgFile>('includeExternal', [], resourceProvider, optionIs: OptionKind.file, help: 'Additional (external) dart files to include; use "dir/fileName", ' @@ -1507,14 +1455,18 @@ Future> createDartdocOptions( // Prefer SDK check first, then pub cache check. var inSdk = packageMeta .sdkType(option.parent.parent['flutterRoot'].valueAt(dir)); + // Analyzer may be confused because package_meta still needs + // migrating. It can definitely return null. + // ignore: unnecessary_null_comparison if (inSdk != null) { Map sdks = option.parent['sdks'].valueAt(dir); - if (sdks.containsKey(inSdk)) return sdks[inSdk]; + if (sdks.containsKey(inSdk)) return sdks[inSdk]!; } var hostedAt = packageMeta.hostedAt; + // ignore: unnecessary_null_comparison if (hostedAt != null) { Map hostMap = option.parent['hosted'].valueAt(dir); - if (hostMap.containsKey(hostedAt)) return hostMap[hostedAt]; + if (hostMap.containsKey(hostedAt)) return hostMap[hostedAt]!; } return ''; }, resourceProvider, help: 'Url to use for this particular package.'), @@ -1534,6 +1486,7 @@ Future> createDartdocOptions( 'packageMeta', (DartdocSyntheticOption option, Folder dir) { var packageMeta = packageMetaProvider.fromDir(dir); + // ignore: unnecessary_null_comparison if (packageMeta == null) { throw DartdocOptionError( 'Unable to determine package for directory: ${dir.path}'); @@ -1543,17 +1496,18 @@ Future> createDartdocOptions( resourceProvider, ), DartdocOptionArgOnly>('packageOrder', [], resourceProvider, + splitCommas: true, help: 'A list of package names to place first when grouping libraries in ' 'packages. Unmentioned packages are sorted after these.'), DartdocOptionArgOnly('sdkDocs', false, resourceProvider, help: 'Generate ONLY the docs for the Dart SDK.'), - DartdocOptionArgSynth('sdkDir', - (DartdocSyntheticOption option, Folder dir) { + DartdocOptionArgSynth('sdkDir', + (DartdocSyntheticOption option, Folder dir) { if (!(option.parent['sdkDocs'].valueAt(dir) as bool) && (option.root['topLevelPackageMeta'].valueAt(dir) as PackageMeta) .requiresFlutter) { - String flutterRoot = option.root['flutterRoot'].valueAt(dir); + String? flutterRoot = option.root['flutterRoot'].valueAt(dir); if (flutterRoot == null) { // For now, return null. An error is reported in // [PackageBuilder.buildPackageGraph]. @@ -1574,6 +1528,7 @@ Future> createDartdocOptions( (DartdocSyntheticOption option, Folder dir) { var packageMeta = packageMetaProvider.fromDir( resourceProvider.getFolder(option.parent['inputDir'].valueAt(dir))); + // ignore: unnecessary_null_comparison if (packageMeta == null) { throw DartdocOptionError( 'Unable to generate documentation: no package found'); diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 476d4695a1..578eaae7fc 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -14834,6 +14834,7 @@ const _invisibleGetters = { 'runtimeType', 'optionSet', 'context', + 'exclude', 'allowTools', 'ambiguousReexportScorerMinConfidence', 'autoIncludeDependencies', @@ -14841,7 +14842,6 @@ const _invisibleGetters = { 'categories', 'dropTextFrom', 'examplePathPrefix', - 'exclude', 'excludePackages', 'enhancedReferenceLookup', 'flutterRoot', diff --git a/lib/src/logging.dart b/lib/src/logging.dart index b56a8d39c1..6a673a0cd5 100644 --- a/lib/src/logging.dart +++ b/lib/src/logging.dart @@ -145,7 +145,7 @@ Future>> createLoggingOptions( negatable: true), DartdocOptionArgSynth('quiet', (DartdocSyntheticOption option, Folder dir) { - if (option.root['generateDocs']?.valueAt(dir) == false) { + if (option.parent['generateDocs'].valueAt(dir) == false) { return true; } return false; diff --git a/lib/src/warnings.dart b/lib/src/warnings.dart index f34b790e72..acd4aa272a 100644 --- a/lib/src/warnings.dart +++ b/lib/src/warnings.dart @@ -41,23 +41,28 @@ Future>> createPackageWarningOptions( // packages they don't control. DartdocOptionArgOnly>( 'allowWarningsInPackages', null, resourceProvider, + splitCommas: true, help: 'Package names to display warnings for (ignore all others if set).'), DartdocOptionArgOnly>( 'allowErrorsInPackages', null, resourceProvider, + splitCommas: true, help: 'Package names to display errors for (ignore all others if set)'), DartdocOptionArgOnly>( 'ignoreWarningsInPackages', null, resourceProvider, + splitCommas: true, help: 'Package names to ignore warnings for. Takes priority over ' 'allow-warnings-in-packages'), DartdocOptionArgOnly>( 'ignoreErrorsInPackages', null, resourceProvider, + splitCommas: true, help: 'Package names to ignore errors for. Takes priority over ' 'allow-errors-in-packages'), // Options for globally enabling/disabling warnings and errors across // packages. Loaded from dartdoc_options.yaml, but command line arguments // will override. DartdocOptionArgFile>('errors', null, resourceProvider, + splitCommas: true, help: 'Additional warning names to force as errors. Specify an empty ' 'list to force defaults (overriding dartdoc_options.yaml)\nDefaults:\n' + (packageWarningDefinitions.values @@ -68,6 +73,7 @@ Future>> createPackageWarningOptions( .map((d) => ' ${d.warningName}: ${d.shortHelp}') .join('\n')), DartdocOptionArgFile>('ignore', null, resourceProvider, + splitCommas: true, help: 'Additional warning names to ignore. Specify an empty list to ' 'force defaults (overriding dartdoc_options.yaml).\nDefaults:\n' + (packageWarningDefinitions.values @@ -78,6 +84,7 @@ Future>> createPackageWarningOptions( .map((d) => ' ${d.warningName}: ${d.shortHelp}') .join('\n')), DartdocOptionArgFile>('warnings', null, resourceProvider, + splitCommas: true, help: 'Additional warning names to show as warnings (instead of error or ' 'ignore, if not warning by default).\nDefaults:\n' + diff --git a/test/dartdoc_options_test.dart b/test/dartdoc_options_test.dart index 95f7d38bab..3f2a540962 100644 --- a/test/dartdoc_options_test.dart +++ b/test/dartdoc_options_test.dart @@ -43,10 +43,10 @@ class ConvertedOption { void main() { var resourceProvider = pubPackageMetaProvider.resourceProvider; - DartdocOptionSet dartdocOptionSetFiles; - DartdocOptionSet dartdocOptionSetArgs; - DartdocOptionSet dartdocOptionSetAll; - DartdocOptionSet dartdocOptionSetSynthetic; + DartdocOptionRoot dartdocOptionSetFiles; + DartdocOptionRoot dartdocOptionSetArgs; + DartdocOptionRoot dartdocOptionSetAll; + DartdocOptionRoot dartdocOptionSetSynthetic; Folder tempDir; Folder firstDir; Folder secondDir; @@ -59,7 +59,7 @@ void main() { File firstExisting; setUpAll(() { - dartdocOptionSetSynthetic = DartdocOptionSet('dartdoc', resourceProvider); + dartdocOptionSetSynthetic = DartdocOptionRoot('dartdoc', resourceProvider); dartdocOptionSetSynthetic.add( DartdocOptionArgFile('mySpecialInteger', 91, resourceProvider)); dartdocOptionSetSynthetic.add( @@ -86,7 +86,7 @@ void main() { return (option.root['vegetableLoader'].valueAt(dir) as List).first; }, resourceProvider, optionIs: OptionKind.file)); - dartdocOptionSetFiles = DartdocOptionSet('dartdoc', resourceProvider); + dartdocOptionSetFiles = DartdocOptionRoot('dartdoc', resourceProvider); dartdocOptionSetFiles.add(DartdocOptionFileOnly>( 'categoryOrder', [], resourceProvider)); dartdocOptionSetFiles @@ -122,7 +122,7 @@ void main() { convertYamlToType: ConvertedOption.fromYamlMap, )); - dartdocOptionSetArgs = DartdocOptionSet('dartdoc', resourceProvider); + dartdocOptionSetArgs = DartdocOptionRoot('dartdoc', resourceProvider); dartdocOptionSetArgs.add(DartdocOptionArgOnly( 'cauliflowerSystem', false, resourceProvider)); dartdocOptionSetArgs.add(DartdocOptionArgOnly( @@ -152,7 +152,7 @@ void main() { 'unimportantFile', 'whatever', resourceProvider, optionIs: OptionKind.file)); - dartdocOptionSetAll = DartdocOptionSet('dartdoc', resourceProvider); + dartdocOptionSetAll = DartdocOptionRoot('dartdoc', resourceProvider); dartdocOptionSetAll.add(DartdocOptionArgFile>( 'categoryOrder', [], resourceProvider)); dartdocOptionSetAll.add( diff --git a/test/documentation_comment_test.dart b/test/documentation_comment_test.dart index 1650f759d9..f297926ec7 100644 --- a/test/documentation_comment_test.dart +++ b/test/documentation_comment_test.dart @@ -53,7 +53,7 @@ void main() { sdkFolder, defaultSdk: mockSdk, ); - var optionSet = await DartdocOptionSet.fromOptionGenerators( + var optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [createDartdocOptions], packageMetaProvider); optionSet.parseArguments([]); packageConfigProvider = FakePackageConfigProvider(); diff --git a/test/end2end/dartdoc_test.dart b/test/end2end/dartdoc_test.dart index 62f961e1cc..047dc158d8 100644 --- a/test/end2end/dartdoc_test.dart +++ b/test/end2end/dartdoc_test.dart @@ -49,7 +49,7 @@ final Folder _testPackageExperiments = /// the '--input' flag. Future _generatorContextFromArgv( List argv) async { - var optionSet = await DartdocOptionSet.fromOptionGenerators( + var optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [ createDartdocOptions, @@ -73,8 +73,10 @@ void main() { Folder tempDir; setUpAll(() async { - var optionSet = await DartdocOptionSet.fromOptionGenerators( - 'dartdoc', [createLoggingOptions], pubPackageMetaProvider); + var optionSet = await DartdocOptionRoot.fromOptionGenerators( + 'dartdoc', + [createDartdocProgramOptions, createLoggingOptions], + pubPackageMetaProvider); optionSet.parseArguments([]); startLogging(DartdocLoggingOptionContext( optionSet, diff --git a/test/mustachio/renderers_output_test.dart b/test/mustachio/renderers_output_test.dart index 39c7dbf604..5f0071342f 100644 --- a/test/mustachio/renderers_output_test.dart +++ b/test/mustachio/renderers_output_test.dart @@ -21,7 +21,7 @@ import 'package:test/test.dart'; /// the '--input' flag. Future _generatorContextFromArgv( List argv) async { - var optionSet = await DartdocOptionSet.fromOptionGenerators( + var optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [ createDartdocOptions, diff --git a/test/package_test.dart b/test/package_test.dart index 4c44da5178..183e00bb35 100644 --- a/test/package_test.dart +++ b/test/package_test.dart @@ -40,7 +40,7 @@ void main() { resourceProvider = packageMetaProvider.resourceProvider; sdkFolder = packageMetaProvider.defaultSdkDir; - optionSet = await DartdocOptionSet.fromOptionGenerators( + optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [createDartdocOptions], packageMetaProvider); packageConfigProvider = utils.getTestPackageConfigProvider(sdkFolder.path); }); diff --git a/test/src/utils.dart b/test/src/utils.dart index 3636ddf3f3..46b0e60be7 100644 --- a/test/src/utils.dart +++ b/test/src/utils.dart @@ -36,7 +36,7 @@ final Folder testPackageToolError = _resourceProvider.getFolder(_pathContext /// [DartdocOptionSet] based on the current working directory. Future contextFromArgv( List argv, PackageMetaProvider packageMetaProvider) async { - var optionSet = await DartdocOptionSet.fromOptionGenerators( + var optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [createDartdocOptions], packageMetaProvider); optionSet.parseArguments(argv); return DartdocOptionContext.fromDefaultContextLocation( diff --git a/test/warnings_test.dart b/test/warnings_test.dart index 6f63e6b497..f4f571abf9 100644 --- a/test/warnings_test.dart +++ b/test/warnings_test.dart @@ -56,7 +56,7 @@ dartdoc: }); setUp(() async { - optionSet = await DartdocOptionSet.fromOptionGenerators( + optionSet = await DartdocOptionRoot.fromOptionGenerators( 'dartdoc', [createDartdocOptions], pubPackageMetaProvider); }); From 98b4c17040b9f08bdcdba37a9ddfa414b14bcb74 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Thu, 19 Aug 2021 11:59:43 -0700 Subject: [PATCH 4/8] Disable the unstable template checks and prepare for 2.14 stable. (#2752) * Disable one of the template checks? and add beta branch for testing * beta is the new stable * empty commit - force check reset --- .github/workflows/test.yaml | 6 +++--- tool/grind.dart | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index fdeaaaf0e0..f5ed341553 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [dev, stable] + sdk: [dev, beta] job: [main, flutter, sdk-analyzer, packages, sdk-docs] include: - os: macos-latest @@ -32,9 +32,9 @@ jobs: # Do not try to run flutter against the "stable" sdk, # it is unlikely to work and produces uninteresting # results. - - sdk: stable + - sdk: beta job: flutter - - sdk: stable + - sdk: beta job: sdk-analyzer steps: diff --git a/tool/grind.dart b/tool/grind.dart index db4701cbcc..365730ab22 100644 --- a/tool/grind.dart +++ b/tool/grind.dart @@ -1056,7 +1056,8 @@ final _generatedFilesList = [ 'src/generator/html_resources.g.dart', 'src/generator/templates.aot_renderers_for_html.dart', 'src/generator/templates.aot_renderers_for_md.dart', - 'src/generator/templates.runtime_renderers.dart', + // TODO(jcollins-g): https://github.com/dart-lang/dartdoc/issues/2751 + //'src/generator/templates.runtime_renderers.dart', 'src/version.dart', '../test/mustachio/foo.dart', ].map((s) => path.joinAll(path.posix.split(s))); From 2c393eb66643cfc626e318a198a7bc941c349594 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Mon, 23 Aug 2021 08:35:20 -0700 Subject: [PATCH 5/8] Add a blurb to the README about requiring analysis (#2753) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 01fb7d69d5..6c41da2dd2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ Run `pub global activate dartdoc` to install the latest version of dartdoc compa ## Generating docs -Run `dartdoc` from the root directory of a package. Here is an example of dartdoc documenting itself: +Run `dartdoc` from the root directory of a package. Your package must analyze without errors +with `dart analyze` or `flutter analyze` as appropriate. Here is an example of dartdoc documenting +itself: ``` $ dartdoc From 8460c9a0f2deea58e6e49ecad35967ee29a94e54 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Mon, 23 Aug 2021 18:17:49 +0200 Subject: [PATCH 6/8] Allow comment references on generic typedefs (#2756) Co-authored-by: Janice Collins --- lib/src/model/typedef.dart | 8 ++++++-- .../test_package/lib/features/generalized_typedefs.dart | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/src/model/typedef.dart b/lib/src/model/typedef.dart index 7c47548a50..93358152d6 100644 --- a/lib/src/model/typedef.dart +++ b/lib/src/model/typedef.dart @@ -71,8 +71,12 @@ class Typedef extends ModelElement Map get referenceChildren { if (_referenceChildren == null) { _referenceChildren = {}; - _referenceChildren - .addEntriesIfAbsent(parameters.explicitOnCollisionWith(this)); + + // Only consider parameters if this is a function typedef. + if (isCallable) { + _referenceChildren + .addEntriesIfAbsent(parameters.explicitOnCollisionWith(this)); + } _referenceChildren .addEntriesIfAbsent(typeParameters.explicitOnCollisionWith(this)); } diff --git a/testing/test_package/lib/features/generalized_typedefs.dart b/testing/test_package/lib/features/generalized_typedefs.dart index e43a9d721b..220be96e82 100644 --- a/testing/test_package/lib/features/generalized_typedefs.dart +++ b/testing/test_package/lib/features/generalized_typedefs.dart @@ -10,6 +10,8 @@ library generalized_typedefs; typedef T0 = void; typedef T1 = Function; + +/// [List], [String] typedef T2 = List; typedef T3 = Map; typedef T4 = void Function(); From a4ca86f9bf732d7adc4506f7373e0ed63251b646 Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Mon, 23 Aug 2021 10:11:53 -0700 Subject: [PATCH 7/8] Prepare for dartdoc 2.0.0 (#2754) * Prepare for dartdoc 2.0.0 * Update changelog for additional bugfix --- CHANGELOG.md | 9 +++++++++ dartdoc_options.yaml | 2 +- lib/src/version.dart | 2 +- pubspec.yaml | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9a32e1a3c..e47033a8da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.0.0 +* BREAKING CHANGE: changes to dartdoc options API + to prepare for NNBD migration (#2745, #2744). +* Fix unbound type reference in extension method comment + reference creating a null dereference (#2741, #2740) +* Update to analyzer 2.0. (#2734) +* Fix comment references on generic typedefs in new + lookup code. (#2755, #2756) + ## 1.0.2 * Fix where extensions header in library sidebar linked to the diff --git a/dartdoc_options.yaml b/dartdoc_options.yaml index 1f6e65ac2c..242689dbfc 100644 --- a/dartdoc_options.yaml +++ b/dartdoc_options.yaml @@ -1,4 +1,4 @@ dartdoc: linkToSource: root: '.' - uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v1.0.2/%f%#L%l%' + uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v2.0.0/%f%#L%l%' diff --git a/lib/src/version.dart b/lib/src/version.dart index b0e99a53ed..0e58df3934 100644 --- a/lib/src/version.dart +++ b/lib/src/version.dart @@ -1,2 +1,2 @@ // Generated code. Do not modify. -const packageVersion = '1.0.2'; +const packageVersion = '2.0.0'; diff --git a/pubspec.yaml b/pubspec.yaml index d9d6e1e6b6..7610241635 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: dartdoc # Run `grind build` after updating. -version: 1.0.2 +version: 2.0.0 description: A non-interactive HTML documentation generator for Dart source code. homepage: https://github.com/dart-lang/dartdoc environment: From f6a5ec7e576d3fcca53d47b1bf0cd89c51af41af Mon Sep 17 00:00:00 2001 From: Janice Collins Date: Mon, 23 Aug 2021 11:49:08 -0700 Subject: [PATCH 8/8] review comments --- lib/src/dartdoc_options.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/src/dartdoc_options.dart b/lib/src/dartdoc_options.dart index 4ecf4b175f..544e32dcdf 100644 --- a/lib/src/dartdoc_options.dart +++ b/lib/src/dartdoc_options.dart @@ -414,8 +414,7 @@ abstract class DartdocOption { } else if (value is List) { resolvedPaths = valueWithContext.resolvedValue as List; } else if (value is Map) { - resolvedPaths = (valueWithContext.resolvedValue as Map).values.toList() - as List; + resolvedPaths = [...(valueWithContext.resolvedValue as Map).values]; } else { assert( false, @@ -662,7 +661,7 @@ class DartdocOptionRoot extends DartdocOptionSet { DartdocOptionRoot(String name, ResourceProvider resourceProvider) : super(name, resourceProvider); - late final ArgParser __argParser = + late final ArgParser _argParser = ArgParser(usageLineLength: _usageLineLength); /// Asynchronous factory that is the main entry point to initialize Dartdoc @@ -683,7 +682,7 @@ class DartdocOptionRoot extends DartdocOptionSet { return optionSet; } - ArgParser get argParser => __argParser; + ArgParser get argParser => _argParser; /// Initialized via [_parseArguments]. late ArgResults __argResults;