show discontinued in pub outdated (#3399)

diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index a291198..5c275e4 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -211,6 +211,11 @@
         latestIsOverridden = true;
       }
 
+      final packageStatus = await current?.source.status(current, cache);
+      final discontinued =
+          packageStatus == null ? false : packageStatus.isDiscontinued;
+      final discontinuedReplacedBy = packageStatus?.discontinuedReplacedBy;
+
       return _PackageDetails(
         name,
         await _describeVersion(
@@ -230,6 +235,8 @@
           latestIsOverridden,
         ),
         _kind(name, entrypoint, nonDevDependencies),
+        discontinued,
+        discontinuedReplacedBy,
       );
     }
 
@@ -401,6 +408,7 @@
           ...(rows..sort((a, b) => a.name.compareTo(b.name)))
               .map((packageDetails) => {
                     'package': packageDetails.name,
+                    'isDiscontinued': packageDetails.isDiscontinued,
                     'current': markedRows[packageDetails]![0].toJson(),
                     'upgradable': markedRows[packageDetails]![1].toJson(),
                     'resolvable': markedRows[packageDetails]![2].toJson(),
@@ -575,6 +583,17 @@
           'To update these dependencies, ${mode.upgradeConstrained}.');
     }
   }
+  if (rows.any((package) => package.isDiscontinued)) {
+    log.message('\n');
+    for (var package in rows.where((package) => package.isDiscontinued)) {
+      log.message(log.bold(package.name));
+      final replacedByText = package.discontinuedReplacedBy != null
+          ? ', replaced by ${package.discontinuedReplacedBy}.'
+          : '.';
+      log.message(
+          '    Package ${package.name} has been discontinued$replacedByText');
+    }
+  }
 }
 
 abstract class Mode {
@@ -633,12 +652,17 @@
       ]) {
         String Function(String)? color;
         String? prefix;
+        String? suffix;
         var asDesired = false;
         if (versionDetails != null) {
           final isLatest = versionDetails == packageDetails.latest;
           if (isLatest) {
             color = versionDetails == previous ? color = log.gray : null;
             asDesired = true;
+            if (packageDetails.isDiscontinued &&
+                identical(versionDetails, packageDetails.latest)) {
+              suffix = ' (discontinued)';
+            }
           } else {
             color = log.red;
           }
@@ -650,6 +674,7 @@
             asDesired: asDesired,
             format: color,
             prefix: prefix,
+            suffix: suffix,
           ),
         );
         previous = versionDetails;
@@ -736,9 +761,14 @@
           (versionDetails) {
             String Function(String)? color;
             String? prefix;
+            String? suffix;
             MapEntry<String, Object>? jsonExplanation;
             var asDesired = false;
             if (versionDetails != null) {
+              if (packageDetails.isDiscontinued &&
+                  identical(versionDetails, packageDetails.latest)) {
+                suffix = ' (discontinued)';
+              }
               if (nullSafetyMap[versionDetails._id]!) {
                 color = log.green;
                 prefix = _compliantEmoji;
@@ -755,6 +785,7 @@
               asDesired: asDesired,
               format: color,
               prefix: prefix,
+              suffix: suffix,
               jsonExplanation: jsonExplanation,
             );
           },
@@ -818,9 +849,11 @@
   final _VersionDetails? resolvable;
   final _VersionDetails? latest;
   final _DependencyKind kind;
+  final bool isDiscontinued;
+  final String? discontinuedReplacedBy;
 
   _PackageDetails(this.name, this.current, this.upgradable, this.resolvable,
-      this.latest, this.kind);
+      this.latest, this.kind, this.isDiscontinued, this.discontinuedReplacedBy);
 
   @override
   int compareTo(_PackageDetails other) {
@@ -837,6 +870,8 @@
       'upgradable': upgradable?.toJson(),
       'resolvable': resolvable?.toJson(),
       'latest': latest?.toJson(),
+      'isDiscontinued': isDiscontinued,
+      'discontinuedReplacedBy': discontinuedReplacedBy,
     };
   }
 }
@@ -880,6 +915,7 @@
   final _VersionDetails? _versionDetails;
   final String Function(String)? _format;
   final String? _prefix;
+  final String? _suffix;
 
   /// This should be true if the mode creating this consideres the version as
   /// "good".
@@ -893,15 +929,18 @@
     required this.asDesired,
     format,
     prefix = '',
+    suffix = '',
     jsonExplanation,
   })  : _format = format,
         _prefix = prefix,
+        _suffix = suffix,
         _jsonExplanation = jsonExplanation;
 
   _FormattedString toHuman() => _FormattedString(
         _versionDetails?.describe ?? '-',
         format: _format,
         prefix: _prefix,
+        suffix: _suffix,
       );
 
   Object? toJson() {
@@ -923,16 +962,22 @@
   /// A prefix for marking this string if colors are not used.
   final String _prefix;
 
-  _FormattedString(this.value, {String Function(String)? format, prefix})
+  final String _suffix;
+
+  _FormattedString(this.value,
+      {String Function(String)? format, prefix, suffix})
       : _format = format ?? _noFormat,
-        _prefix = prefix ?? '';
+        _prefix = prefix ?? '',
+        _suffix = suffix ?? '';
 
   String formatted({required bool useColors}) {
-    return useColors ? _format(_prefix + value) : _prefix + value;
+    return useColors
+        ? _format(_prefix + value + _suffix)
+        : _prefix + value + _suffix;
   }
 
   int computeLength({required bool? useColors}) {
-    return _prefix.length + value.length;
+    return _prefix.length + value.length + _suffix.length;
   }
 
   static String _noFormat(String x) => x;
diff --git a/test/outdated/outdated_test.dart b/test/outdated/outdated_test.dart
index 31113c7..5a90fae 100644
--- a/test/outdated/outdated_test.dart
+++ b/test/outdated/outdated_test.dart
@@ -109,6 +109,30 @@
     await ctx.runOutdatedTests();
   });
 
+  testWithGolden('show discontinued', (ctx) async {
+    final builder = await servePackages();
+    builder
+      ..serve('foo', '1.2.3', deps: {'transitive': '^1.0.0'})
+      ..serve('bar', '1.0.0')
+      ..serve('baz', '1.0.0')
+      ..serve('transitive', '1.2.3');
+
+    await d.dir(appPath, [
+      d.pubspec({
+        'name': 'app',
+        'dependencies': {
+          'foo': '^1.0.0',
+          'bar': '^1.0.0',
+          'baz': '^1.0.0',
+        },
+      })
+    ]).create();
+    await pubGet();
+    builder.discontinue('foo');
+    builder.discontinue('baz', replacementText: 'newbaz');
+    await ctx.runOutdatedTests();
+  });
+
   testWithGolden('circular dependency on root', (ctx) async {
     final server = await servePackages();
     server.serve('foo', '1.2.3', deps: {'app': '^1.0.0'});
diff --git a/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt b/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
index c9bc73f..5a9578a 100644
--- a/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/Handles SDK dependencies.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.1.0"
       },
@@ -189,6 +190,7 @@
   "packages": [
     {
       "package": "flutter_test",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -208,6 +210,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.1.0",
         "nullSafety": false
@@ -236,6 +239,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.1.0"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt b/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
index b9ab0a5..c01a007 100644
--- a/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
+++ b/test/testdata/goldens/outdated/outdated_test/circular dependency on root.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
@@ -168,6 +169,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3",
         "nullSafety": false
@@ -196,6 +198,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt b/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
index 12c2ee3..92a4ba1 100644
--- a/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
+++ b/test/testdata/goldens/outdated/outdated_test/latest version reported while locked on a prerelease can be a prerelease.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0-dev.1"
       },
@@ -21,6 +22,7 @@
     },
     {
       "package": "mop",
+      "isDiscontinued": false,
       "current": {
         "version": "0.10.0-dev"
       },
@@ -197,6 +199,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "0.9.0",
         "nullSafety": false
@@ -216,6 +219,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0-dev.1",
         "nullSafety": false
@@ -235,6 +239,7 @@
     },
     {
       "package": "mop",
+      "isDiscontinued": false,
       "current": {
         "version": "0.10.0-dev",
         "nullSafety": false
@@ -263,6 +268,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0-dev.1"
       },
@@ -278,6 +284,7 @@
     },
     {
       "package": "mop",
+      "isDiscontinued": false,
       "current": {
         "version": "0.10.0-dev"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt b/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
index 18baa88..c8d7e0b 100644
--- a/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
+++ b/test/testdata/goldens/outdated/outdated_test/mutually incompatible newer versions.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -21,6 +22,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -183,6 +185,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -202,6 +205,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -230,6 +234,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -245,6 +250,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/newer versions available.txt b/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
index d6c0ff9..3e71426 100644
--- a/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
+++ b/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "builder",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
@@ -21,6 +22,7 @@
     },
     {
       "package": "dev_trans",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -34,6 +36,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
@@ -49,6 +52,7 @@
     },
     {
       "package": "transitive",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
@@ -64,6 +68,7 @@
     },
     {
       "package": "transitive2",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": null,
       "resolvable": {
@@ -75,6 +80,7 @@
     },
     {
       "package": "transitive3",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": null,
       "resolvable": {
@@ -335,6 +341,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -354,6 +361,7 @@
     },
     {
       "package": "builder",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3",
         "nullSafety": false
@@ -373,6 +381,7 @@
     },
     {
       "package": "dev_trans",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -389,6 +398,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3",
         "nullSafety": false
@@ -408,6 +418,7 @@
     },
     {
       "package": "local_package",
+      "isDiscontinued": false,
       "current": {
         "version": "0.0.1",
         "nullSafety": false
@@ -427,6 +438,7 @@
     },
     {
       "package": "transitive",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3",
         "nullSafety": false
@@ -446,6 +458,7 @@
     },
     {
       "package": "transitive2",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": null,
       "resolvable": {
@@ -459,6 +472,7 @@
     },
     {
       "package": "transitive3",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": null,
       "resolvable": {
@@ -481,6 +495,7 @@
   "packages": [
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
@@ -496,6 +511,7 @@
     },
     {
       "package": "transitive",
+      "isDiscontinued": false,
       "current": {
         "version": "1.2.3"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/no lockfile.txt b/test/testdata/goldens/outdated/outdated_test/no lockfile.txt
index 7f670db..87a8997 100644
--- a/test/testdata/goldens/outdated/outdated_test/no lockfile.txt
+++ b/test/testdata/goldens/outdated/outdated_test/no lockfile.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3"
@@ -19,6 +20,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3"
@@ -215,6 +217,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3",
@@ -231,6 +234,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3",
@@ -256,6 +260,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3"
@@ -269,6 +274,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": null,
       "upgradable": {
         "version": "1.2.3"
diff --git a/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt b/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
index d345f55..507d194 100644
--- a/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null safety compliance.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -21,6 +22,7 @@
     },
     {
       "package": "fails_analysis",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -36,6 +38,7 @@
     },
     {
       "package": "fails_analysis_in_dependency",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -51,6 +54,7 @@
     },
     {
       "package": "file_in_dependency_opts_out",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -66,6 +70,7 @@
     },
     {
       "package": "file_opts_out",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -81,6 +86,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -276,6 +282,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -295,6 +302,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -323,6 +331,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -338,6 +347,7 @@
     },
     {
       "package": "fails_analysis",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -353,6 +363,7 @@
     },
     {
       "package": "fails_analysis_in_dependency",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -368,6 +379,7 @@
     },
     {
       "package": "file_in_dependency_opts_out",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -383,6 +395,7 @@
     },
     {
       "package": "file_opts_out",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
@@ -398,6 +411,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0"
       },
diff --git a/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt b/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
index 3d227ec..5d3cf9b 100644
--- a/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null-safety already migrated.txt
@@ -127,6 +127,7 @@
   "packages": [
     {
       "package": "devTransitive",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
diff --git a/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt b/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
index 1ab20ad..bc19cb6 100644
--- a/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
+++ b/test/testdata/goldens/outdated/outdated_test/null-safety no resolution.txt
@@ -125,6 +125,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
@@ -141,6 +142,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "nullSafety": false
diff --git a/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt b/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
index 909ee0a..521da52 100644
--- a/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
+++ b/test/testdata/goldens/outdated/outdated_test/overridden dependencies - no resolution.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true
@@ -24,6 +25,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true
@@ -188,6 +190,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true,
@@ -210,6 +213,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true,
@@ -241,6 +245,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true
@@ -259,6 +264,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.0",
         "overridden": true
diff --git a/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
index 49abe1b..a761ce0 100644
--- a/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
@@ -6,6 +6,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true
@@ -24,6 +25,7 @@
     },
     {
       "package": "baz",
+      "isDiscontinued": false,
       "current": {
         "version": "2.0.0",
         "overridden": true
@@ -42,6 +44,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true
@@ -220,6 +223,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true,
@@ -242,6 +246,7 @@
     },
     {
       "package": "baz",
+      "isDiscontinued": false,
       "current": {
         "version": "2.0.0",
         "overridden": true,
@@ -264,6 +269,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true,
@@ -295,6 +301,7 @@
   "packages": [
     {
       "package": "bar",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true
@@ -313,6 +320,7 @@
     },
     {
       "package": "baz",
+      "isDiscontinued": false,
       "current": {
         "version": "2.0.0",
         "overridden": true
@@ -331,6 +339,7 @@
     },
     {
       "package": "foo",
+      "isDiscontinued": false,
       "current": {
         "version": "1.0.1",
         "overridden": true
diff --git a/test/testdata/goldens/outdated/outdated_test/show discontinued.txt b/test/testdata/goldens/outdated/outdated_test/show discontinued.txt
new file mode 100644
index 0000000..97e2717
--- /dev/null
+++ b/test/testdata/goldens/outdated/outdated_test/show discontinued.txt
@@ -0,0 +1,243 @@
+# GENERATED BY: test/outdated/outdated_test.dart
+
+## Section 0
+$ pub outdated --json
+{
+  "packages": []
+}
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 1
+$ pub outdated --no-color
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Found no outdated packages
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 2
+$ pub outdated --no-color --no-transitive
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Found no outdated packages
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 3
+$ pub outdated --no-color --up-to-date
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Package Name  Current  Upgradable  Resolvable  Latest                
+
+direct dependencies:
+bar           1.0.0    1.0.0       1.0.0       1.0.0                 
+baz           1.0.0    1.0.0       1.0.0       1.0.0 (discontinued)  
+foo           1.2.3    1.2.3       1.2.3       1.2.3 (discontinued)  
+
+transitive dependencies:
+transitive    1.2.3    1.2.3       1.2.3       1.2.3                 
+You are already using the newest resolvable versions listed in the 'Resolvable' column.
+Newer versions, listed in 'Latest', may not be mutually compatible.
+
+baz
+    Package baz has been discontinued, replaced by newbaz.
+foo
+    Package foo has been discontinued.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 4
+$ pub outdated --no-color --prereleases
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Found no outdated packages
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 5
+$ pub outdated --no-color --no-dev-dependencies
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Found no outdated packages
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 6
+$ pub outdated --no-color --no-dependency-overrides
+Showing outdated packages.
+[*] indicates versions that are not the latest available.
+
+Found no outdated packages
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 7
+$ pub outdated --no-color --mode=null-safety
+Showing dependencies that are currently not opted in to null-safety.
+[✗] indicates versions without null safety support.
+[✓] indicates versions opting in to null safety.
+
+Package Name  Current  Upgradable  Resolvable  Latest                 
+
+direct dependencies:
+bar           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0                 
+baz           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0 (discontinued)  
+foo           ✗1.2.3   ✗1.2.3      ✗1.2.3      ✗1.2.3 (discontinued)  
+You are already using the newest resolvable versions listed in the 'Resolvable' column.
+Newer versions, listed in 'Latest', may not be mutually compatible.
+
+baz
+    Package baz has been discontinued, replaced by newbaz.
+foo
+    Package foo has been discontinued.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 8
+$ pub outdated --no-color --mode=null-safety --transitive
+Showing dependencies that are currently not opted in to null-safety.
+[✗] indicates versions without null safety support.
+[✓] indicates versions opting in to null safety.
+
+Package Name  Current  Upgradable  Resolvable  Latest                 
+
+direct dependencies:
+bar           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0                 
+baz           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0 (discontinued)  
+foo           ✗1.2.3   ✗1.2.3      ✗1.2.3      ✗1.2.3 (discontinued)  
+
+transitive dependencies:
+transitive    ✗1.2.3   ✗1.2.3      ✗1.2.3      ✗1.2.3                 
+You are already using the newest resolvable versions listed in the 'Resolvable' column.
+Newer versions, listed in 'Latest', may not be mutually compatible.
+
+baz
+    Package baz has been discontinued, replaced by newbaz.
+foo
+    Package foo has been discontinued.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 9
+$ pub outdated --no-color --mode=null-safety --no-prereleases
+Showing dependencies that are currently not opted in to null-safety.
+[✗] indicates versions without null safety support.
+[✓] indicates versions opting in to null safety.
+
+Package Name  Current  Upgradable  Resolvable  Latest                 
+
+direct dependencies:
+bar           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0                 
+baz           ✗1.0.0   ✗1.0.0      ✗1.0.0      ✗1.0.0 (discontinued)  
+foo           ✗1.2.3   ✗1.2.3      ✗1.2.3      ✗1.2.3 (discontinued)  
+You are already using the newest resolvable versions listed in the 'Resolvable' column.
+Newer versions, listed in 'Latest', may not be mutually compatible.
+
+baz
+    Package baz has been discontinued, replaced by newbaz.
+foo
+    Package foo has been discontinued.
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 10
+$ pub outdated --json --mode=null-safety
+{
+  "packages": [
+    {
+      "package": "bar",
+      "isDiscontinued": false,
+      "current": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "upgradable": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "resolvable": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "latest": {
+        "version": "1.0.0",
+        "nullSafety": false
+      }
+    },
+    {
+      "package": "baz",
+      "isDiscontinued": true,
+      "current": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "upgradable": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "resolvable": {
+        "version": "1.0.0",
+        "nullSafety": false
+      },
+      "latest": {
+        "version": "1.0.0",
+        "nullSafety": false
+      }
+    },
+    {
+      "package": "foo",
+      "isDiscontinued": true,
+      "current": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "upgradable": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "resolvable": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "latest": {
+        "version": "1.2.3",
+        "nullSafety": false
+      }
+    },
+    {
+      "package": "transitive",
+      "isDiscontinued": false,
+      "current": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "upgradable": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "resolvable": {
+        "version": "1.2.3",
+        "nullSafety": false
+      },
+      "latest": {
+        "version": "1.2.3",
+        "nullSafety": false
+      }
+    }
+  ]
+}
+
+-------------------------------- END OF OUTPUT ---------------------------------
+
+## Section 11
+$ pub outdated --json --no-dev-dependencies
+{
+  "packages": []
+}
+