Use the lockfile when computing upgradable, resolvable in outdated (#3887)

diff --git a/lib/src/command/outdated.dart b/lib/src/command/outdated.dart
index 18ebf30..c9e45df 100644
--- a/lib/src/command/outdated.dart
+++ b/lib/src/command/outdated.dart
@@ -13,6 +13,7 @@
 import '../command_runner.dart';
 import '../entrypoint.dart';
 import '../io.dart';
+import '../lock_file.dart';
 import '../log.dart' as log;
 import '../package.dart';
 import '../package_name.dart';
@@ -142,13 +143,19 @@
     await log.spinner(
       'Resolving',
       () async {
-        final upgradablePackagesResult =
-            await _tryResolve(upgradablePubspec, cache);
+        final upgradablePackagesResult = await _tryResolve(
+          upgradablePubspec,
+          cache,
+          lockFile: entrypoint.lockFile,
+        );
         hasUpgradableResolution = upgradablePackagesResult != null;
         upgradablePackages = upgradablePackagesResult ?? [];
 
-        final resolvablePackagesResult =
-            await _tryResolve(resolvablePubspec, cache);
+        final resolvablePackagesResult = await _tryResolve(
+          resolvablePubspec,
+          cache,
+          lockFile: entrypoint.lockFile,
+        );
         hasResolvableResolution = resolvablePackagesResult != null;
         resolvablePackages = resolvablePackagesResult ?? [];
       },
@@ -386,11 +393,16 @@
 
 /// Try to solve [pubspec] return [PackageId]s in the resolution or `null` if no
 /// resolution was found.
-Future<List<PackageId>?> _tryResolve(Pubspec pubspec, SystemCache cache) async {
+Future<List<PackageId>?> _tryResolve(
+  Pubspec pubspec,
+  SystemCache cache, {
+  LockFile? lockFile,
+}) async {
   final solveResult = await tryResolveVersions(
     SolveType.upgrade,
     cache,
     Package.inMemory(pubspec),
+    lockFile: lockFile,
   );
 
   return solveResult?.packages;
@@ -546,31 +558,35 @@
     log.message(b.toString());
   }
 
-  var upgradable = rows
-      .where(
-        (row) =>
-            row.current != null &&
-            row.upgradable != null &&
-            row.current != row.upgradable &&
-            // Include transitive only, if we show them
-            (showTransitiveDependencies ||
-                hasKind(_DependencyKind.direct)(row) ||
-                hasKind(_DependencyKind.dev)(row)),
-      )
-      .length;
+  var upgradable = rows.where(
+    (row) {
+      final current = row.current;
+      final upgradable = row.upgradable;
+      return current != null &&
+          upgradable != null &&
+          current < upgradable &&
+          // Include transitive only, if we show them
+          (showTransitiveDependencies ||
+              hasKind(_DependencyKind.direct)(row) ||
+              hasKind(_DependencyKind.dev)(row));
+    },
+  ).length;
 
-  var notAtResolvable = rows
-      .where(
-        (row) =>
-            (row.current != null || !lockFileExists) &&
-            row.resolvable != null &&
-            row.upgradable != row.resolvable &&
-            // Include transitive only, if we show them
-            (showTransitiveDependencies ||
-                hasKind(_DependencyKind.direct)(row) ||
-                hasKind(_DependencyKind.dev)(row)),
-      )
-      .length;
+  var notAtResolvable = rows.where(
+    (row) {
+      final current = row.current;
+      final upgradable = row.upgradable;
+      final resolvable = row.resolvable;
+      return (current != null || !lockFileExists) &&
+          resolvable != null &&
+          upgradable != null &&
+          upgradable < resolvable &&
+          // Include transitive only, if we show them
+          (showTransitiveDependencies ||
+              hasKind(_DependencyKind.direct)(row) ||
+              hasKind(_DependencyKind.dev)(row));
+    },
+  ).length;
 
   if (!hasUpgradableResolution || !hasResolvableResolution) {
     log.message(mode.noResolutionText);
@@ -763,6 +779,11 @@
           _id.source == other._id.source &&
           _pubspec.version == other._pubspec.version;
 
+  bool operator <(_VersionDetails other) =>
+      _overridden == other._overridden &&
+      _id.source == other._id.source &&
+      _pubspec.version < other._pubspec.version;
+
   @override
   int get hashCode => Object.hash(_pubspec.version, _id.source, _overridden);
 }
diff --git a/test/outdated/outdated_test.dart b/test/outdated/outdated_test.dart
index 0ef5756..0757d0a 100644
--- a/test/outdated/outdated_test.dart
+++ b/test/outdated/outdated_test.dart
@@ -70,7 +70,9 @@
         },
       )
       ..serve('transitive', '1.2.3')
-      ..serve('dev_trans', '1.0.0');
+      ..serve('dev_trans', '1.0.0')
+      ..serve('retracted', '1.0.0')
+      ..serve('retracted', '1.0.1');
 
     await d.dir('local_package', [
       d.libDir('local_package'),
@@ -83,7 +85,8 @@
         'dependencies': {
           'foo': '^1.0.0',
           'bar': '^1.0.0',
-          'local_package': {'path': '../local_package'}
+          'local_package': {'path': '../local_package'},
+          'retracted': '^1.0.0',
         },
         'dev_dependencies': {'builder': '^1.0.0'},
       })
@@ -112,7 +115,10 @@
       ..serve('transitive', '2.0.0')
       ..serve('transitive2', '1.0.0')
       ..serve('transitive3', '1.0.0')
-      ..serve('dev_trans', '2.0.0');
+      ..serve('dev_trans', '2.0.0')
+      // Even though the current (and latest) version is retracted, it should be
+      // the one shown in the upgradable and resolvable columns.
+      ..retractPackageVersion('retracted', '1.0.1');
     await ctx.runOutdatedTests();
   });
 
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 7d91029..4a31e13 100644
--- a/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
+++ b/test/testdata/goldens/outdated/outdated_test/newer versions available.txt
@@ -54,6 +54,23 @@
       }
     },
     {
+      "package": "retracted",
+      "kind": "direct",
+      "isDiscontinued": false,
+      "current": {
+        "version": "1.0.1"
+      },
+      "upgradable": {
+        "version": "1.0.1"
+      },
+      "resolvable": {
+        "version": "1.0.1"
+      },
+      "latest": {
+        "version": "1.0.0"
+      }
+    },
+    {
       "package": "transitive",
       "kind": "transitive",
       "isDiscontinued": false,
@@ -110,6 +127,7 @@
 
 direct dependencies:
 foo           *1.2.3   *1.3.0      *2.0.0      3.0.0   
+retracted     *1.0.1   *1.0.1      *1.0.1      1.0.0   
 
 dev_dependencies:
 builder       *1.2.3   *1.3.0      2.0.0       2.0.0   
@@ -131,6 +149,7 @@
 
 direct dependencies:
 foo           *1.2.3   *1.3.0      *2.0.0      3.0.0   
+retracted     *1.0.1   *1.0.1      *1.0.1      1.0.0   
 
 dev_dependencies:
 builder       *1.2.3   *1.3.0      2.0.0       2.0.0   
@@ -154,6 +173,7 @@
 bar            1.0.0         1.0.0         1.0.0         1.0.0         
 foo            *1.2.3        *1.3.0        *2.0.0        3.0.0         
 local_package  0.0.1 (path)  0.0.1 (path)  0.0.1 (path)  0.0.1 (path)  
+retracted      *1.0.1        *1.0.1        *1.0.1        1.0.0         
 
 dev_dependencies:
 builder        *1.2.3        *1.3.0        2.0.0         2.0.0         
@@ -175,6 +195,7 @@
 
 direct dependencies:
 foo           *1.2.3   *1.3.0      *2.0.0      3.0.0        
+retracted     *1.0.1   *1.0.1      *1.0.1      1.0.0        
 
 dev_dependencies:
 builder       *1.2.3   *1.3.0      *2.0.0      3.0.0-alpha  
@@ -196,6 +217,7 @@
 
 direct dependencies:
 foo           *1.2.3   *1.3.0      3.0.0       3.0.0   
+retracted     *1.0.1   *1.0.1      *1.0.1      1.0.0   
 
 1 upgradable dependency is locked (in pubspec.lock) to an older version.
 To update it, use `dart pub upgrade`.
@@ -214,6 +236,7 @@
 
 direct dependencies:
 foo           *1.2.3   *1.3.0      *2.0.0      3.0.0   
+retracted     *1.0.1   *1.0.1      *1.0.1      1.0.0   
 
 dev_dependencies:
 builder       *1.2.3   *1.3.0      2.0.0       2.0.0   
@@ -248,6 +271,23 @@
       }
     },
     {
+      "package": "retracted",
+      "kind": "direct",
+      "isDiscontinued": false,
+      "current": {
+        "version": "1.0.1"
+      },
+      "upgradable": {
+        "version": "1.0.1"
+      },
+      "resolvable": {
+        "version": "1.0.1"
+      },
+      "latest": {
+        "version": "1.0.0"
+      }
+    },
+    {
       "package": "transitive",
       "kind": "transitive",
       "isDiscontinued": false,
diff --git a/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
index 54bf561..3dd9640 100644
--- a/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
+++ b/test/testdata/goldens/outdated/outdated_test/overridden dependencies.txt
@@ -161,9 +161,6 @@
 baz           *2.0.0 (overridden)  *1.0.0      2.0.0       2.0.0   
 foo           *1.0.1 (overridden)  *1.0.0      *1.0.0      2.0.0   
 
-3 upgradable dependencies are locked (in pubspec.lock) to older versions.
-To update these dependencies, use `dart pub upgrade`.
-
 1 dependency is constrained to a version that is older than a resolvable version.
 To update it, edit pubspec.yaml, or run `dart pub upgrade --major-versions`.