Support documenting unversioned packages (#1697)

* Fix bug where --version didn't do anything

* Review comments

* Rebuild test package docs for retype deprecation in dev.55

* dartdoc_test as full integration test now

* Eliminate unused initializer and update pubspec

* allow unversioned

* Add test

* Add gitignore to test_package_minimum

* dartfmt

* Remove extra copy of contextFromArgvTemp introduced in merge resolution
diff --git a/lib/dartdoc.dart b/lib/dartdoc.dart
index df2e0ba..4966dff 100644
--- a/lib/dartdoc.dart
+++ b/lib/dartdoc.dart
@@ -66,8 +66,7 @@
   /// An asynchronous factory method that builds Dartdoc's file writers
   /// and returns a Dartdoc object with them.
   static withDefaultGenerators(DartdocGeneratorOptionContext config) async {
-    List<Generator> generators =
-        await initGenerators(config);
+    List<Generator> generators = await initGenerators(config);
     return new Dartdoc._(config, generators);
   }
 
diff --git a/lib/src/model.dart b/lib/src/model.dart
index ffb2aef..40edde8 100644
--- a/lib/src/model.dart
+++ b/lib/src/model.dart
@@ -4396,7 +4396,7 @@
     return _inheritThrough;
   }
 
-  String get version => packageMeta.version;
+  String get version => packageMeta.version ?? '0.0.0-unknown';
 
   /// Looks up some [Library] that is reexporting this [Element]; not
   /// necessarily the canonical [Library].
diff --git a/test/compare_output_test.dart b/test/compare_output_test.dart
index 4d0f5e3..a85d7e9 100644
--- a/test/compare_output_test.dart
+++ b/test/compare_output_test.dart
@@ -49,7 +49,8 @@
       var result = Process.runSync(Platform.resolvedExecutable, args,
           workingDirectory: _testPackagePath);
       PackageMeta dartdocMeta = new PackageMeta.fromFilename(dartdocBin);
-      expect(result.stdout, equals('dartdoc version: ${dartdocMeta.version}\n'));
+      expect(
+          result.stdout, equals('dartdoc version: ${dartdocMeta.version}\n'));
     });
 
     test("Validate html output of test_package", () async {
diff --git a/test/dartdoc_test.dart b/test/dartdoc_test.dart
index f03f0a6..7bf6b1b 100644
--- a/test/dartdoc_test.dart
+++ b/test/dartdoc_test.dart
@@ -28,13 +28,24 @@
       delete(tempDir);
     });
 
-    Future<DartdocGeneratorOptionContext> generatorContextFromArgvTemp(List<String> argv) async {
+    Future<DartdocGeneratorOptionContext> generatorContextFromArgvTemp(
+        List<String> argv) async {
       return await generatorContextFromArgv(argv..addAll(outputParam));
     }
 
+    test('package without version produces valid semver in docs', () async {
+      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageMinimumDir.path]));
+      DartdocResults results = await dartdoc.generateDocs();
+      PackageGraph p = results.packageGraph;
+      assert(p.version == '0.0.0-unknown');
+    });
+
     test('basic interlinking test', () async {
-      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(await generatorContextFromArgvTemp(
-          ['--input', testPackageDir.path, '--link-to-remote']));
+      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageDir.path, '--link-to-remote']));
       DartdocResults results = await dartdoc.generateDocs();
       PackageGraph p = results.packageGraph;
       Package tuple = p.publicPackages.firstWhere((p) => p.name == 'tuple');
@@ -60,7 +71,6 @@
           contains(stringLink));
     });
 
-
     test('generate docs for ${pathLib.basename(testPackageDir.path)} works',
         () async {
       Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
@@ -79,7 +89,8 @@
     test('generate docs for ${pathLib.basename(testPackageBadDir.path)} fails',
         () async {
       Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
-          await generatorContextFromArgvTemp(['--input', testPackageBadDir.path]));
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageBadDir.path]));
 
       try {
         await dartdoc.generateDocs();
@@ -91,7 +102,8 @@
 
     test('generate docs for a package that does not have a readme', () async {
       Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
-          await generatorContextFromArgvTemp(['--input', testPackageWithNoReadme.path]));
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageWithNoReadme.path]));
 
       DartdocResults results = await dartdoc.generateDocs();
       expect(results.packageGraph, isNotNull);
@@ -104,8 +116,9 @@
     });
 
     test('generate docs including a single library', () async {
-      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(await generatorContextFromArgvTemp(
-          ['--input', testPackageDir.path, '--include', 'fake']));
+      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageDir.path, '--include', 'fake']));
 
       DartdocResults results = await dartdoc.generateDocs();
       expect(results.packageGraph, isNotNull);
@@ -118,8 +131,9 @@
     });
 
     test('generate docs excluding a single library', () async {
-      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(await generatorContextFromArgvTemp(
-          ['--input', testPackageDir.path, '--exclude', 'fake']));
+      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageDir.path, '--exclude', 'fake']));
 
       DartdocResults results = await dartdoc.generateDocs();
       expect(results.packageGraph, isNotNull);
@@ -135,8 +149,9 @@
     test('generate docs for package with embedder yaml', () async {
       PackageMeta meta = new PackageMeta.fromDir(testPackageWithEmbedderYaml);
       if (meta.needsPubGet) meta.runPubGet();
-      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(await generatorContextFromArgvTemp(
-          ['--input', testPackageWithEmbedderYaml.path]));
+      Dartdoc dartdoc = await Dartdoc.withDefaultGenerators(
+          await generatorContextFromArgvTemp(
+              ['--input', testPackageWithEmbedderYaml.path]));
 
       DartdocResults results = await dartdoc.generateDocs();
       expect(results.packageGraph, isNotNull);
diff --git a/test/src/utils.dart b/test/src/utils.dart
index 993d0c0..9a650bd 100644
--- a/test/src/utils.dart
+++ b/test/src/utils.dart
@@ -21,22 +21,23 @@
 
 final Directory testPackageBadDir = new Directory('testing/test_package_bad');
 final Directory testPackageDir = new Directory('testing/test_package');
+final Directory testPackageMinimumDir =
+    new Directory('testing/test_package_minimum');
 final Directory testPackageWithEmbedderYaml =
     new Directory('testing/test_package_embedder_yaml');
 final Directory testPackageWithNoReadme =
     new Directory('testing/test_package_small');
 
-
 /// Convenience factory to build a [DartdocGeneratorOptionContext] and associate
 /// it with a [DartdocOptionSet] based on the current working directory.
-Future<DartdocGeneratorOptionContext> generatorContextFromArgv(List<String> argv) async {
-  DartdocOptionSet optionSet = await DartdocOptionSet
-      .fromOptionGenerators('dartdoc', [createDartdocOptions, createGeneratorOptions]);
+Future<DartdocGeneratorOptionContext> generatorContextFromArgv(
+    List<String> argv) async {
+  DartdocOptionSet optionSet = await DartdocOptionSet.fromOptionGenerators(
+      'dartdoc', [createDartdocOptions, createGeneratorOptions]);
   optionSet.parseArguments(argv);
   return new DartdocGeneratorOptionContext(optionSet, Directory.current);
 }
 
-
 /// Convenience factory to build a [DartdocOptionContext] and associate it with a
 /// [DartdocOptionSet] based on the current working directory.
 Future<DartdocOptionContext> contextFromArgv(List<String> argv) async {
diff --git a/testing/test_package_minimum/.gitignore b/testing/test_package_minimum/.gitignore
new file mode 100644
index 0000000..70e751d
--- /dev/null
+++ b/testing/test_package_minimum/.gitignore
@@ -0,0 +1,2 @@
+doc/api/
+pubspec.lock
diff --git a/testing/test_package_minimum/lib/main.dart b/testing/test_package_minimum/lib/main.dart
new file mode 100644
index 0000000..e14d752
--- /dev/null
+++ b/testing/test_package_minimum/lib/main.dart
@@ -0,0 +1 @@
+library small;
diff --git a/testing/test_package_minimum/pubspec.yaml b/testing/test_package_minimum/pubspec.yaml
new file mode 100644
index 0000000..062b6cc
--- /dev/null
+++ b/testing/test_package_minimum/pubspec.yaml
@@ -0,0 +1 @@
+name: test_package_minimal
diff --git a/tool/grind.dart b/tool/grind.dart
index 2d38b54..e700b4a 100644
--- a/tool/grind.dart
+++ b/tool/grind.dart
@@ -732,9 +732,8 @@
   List<String> parameters = ['--preview-dart-2', '--enable-asserts'];
 
   // sdk#32901 is really bad on Windows.
-  for (File dartFile in testFiles
-      .where((f) =>
-          !f.path.endsWith('html_generator_test.dart') && !Platform.isWindows)) {
+  for (File dartFile in testFiles.where((f) =>
+      !f.path.endsWith('html_generator_test.dart') && !Platform.isWindows)) {
     // absolute path to work around dart-lang/sdk#32901
     await testFutures.addFuture(new SubprocessLauncher(
             'dart2-${pathLib.basename(dartFile.absolute.path)}')