Don't warn against discontinued transitive dependencies (#3195)

diff --git a/lib/src/solver/report.dart b/lib/src/solver/report.dart
index 04d6fa4..251c290 100644
--- a/lib/src/solver/report.dart
+++ b/lib/src/solver/report.dart
@@ -151,7 +151,11 @@
       if (id.source == null) continue;
       final status =
           await _cache.source(id.source).status(id, maxAge: Duration(days: 3));
-      if (status.isDiscontinued) numDiscontinued++;
+      if (status.isDiscontinued &&
+          (_root.dependencyType(id.name) == DependencyType.direct ||
+              _root.dependencyType(id.name) == DependencyType.dev)) {
+        numDiscontinued++;
+      }
     }
     if (numDiscontinued > 0) {
       if (numDiscontinued == 1) {
@@ -268,7 +272,9 @@
         } else {
           message = '(retracted)';
         }
-      } else if (status.isDiscontinued) {
+      } else if (status.isDiscontinued &&
+          (_root.dependencyType(name) == DependencyType.direct ||
+              _root.dependencyType(name) == DependencyType.dev)) {
         if (status.discontinuedReplacedBy == null) {
           message = '(discontinued)';
         } else {
diff --git a/test/get/hosted/warn_about_discontinued_test.dart b/test/get/hosted/warn_about_discontinued_test.dart
index 3913b2c..76558a0 100644
--- a/test/get/hosted/warn_about_discontinued_test.dart
+++ b/test/get/hosted/warn_about_discontinued_test.dart
@@ -15,7 +15,7 @@
 import '../../test_pub.dart';
 
 void main() {
-  test('Warns about discontinued packages', () async {
+  test('Warns about discontinued dependencies', () async {
     await servePackages((builder) => builder
       ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
       ..serve('transitive', '1.0.0'));
@@ -40,7 +40,6 @@
     await pubGet(output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued)
-  transitive 1.0.0 (discontinued)
 Got dependencies!
 ''');
     expect(fileExists(fooVersionsCache), isTrue);
@@ -54,7 +53,6 @@
     await pubGet(output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
-  transitive 1.0.0 (discontinued)
 Got dependencies!''');
     final c2 = json.decode(readTextFile(fooVersionsCache));
     // Make a bad cached value to test that responses are actually from cache.
@@ -62,14 +60,12 @@
     writeTextFile(fooVersionsCache, json.encode(c2));
     await pubGet(output: '''
 Resolving dependencies...
-  transitive 1.0.0 (discontinued)
 Got dependencies!''');
     // Repairing the cache should reset the package listing caches.
     await runPub(args: ['cache', 'repair']);
     await pubGet(output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
-  transitive 1.0.0 (discontinued)
 Got dependencies!''');
     // Test that --offline won't try to access the server for retrieving the
     // status.
@@ -77,7 +73,6 @@
     await pubGet(args: ['--offline'], output: '''
 Resolving dependencies...
   foo 1.2.3 (discontinued replaced by bar)
-  transitive 1.0.0 (discontinued)
 Got dependencies!''');
     deleteEntry(fooVersionsCache);
     deleteEntry(transitiveVersionsCache);
@@ -87,6 +82,79 @@
 ''');
   });
 
+  test('Warns about discontinued dev dependencies', () async {
+    await servePackages((builder) => builder
+      ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+      ..serve('transitive', '1.0.0'));
+
+    await d.dir(appPath, [
+      d.file('pubspec.yaml', '''
+name: myapp
+dependencies:
+
+dev_dependencies:
+  foo: 1.2.3
+environment:
+  sdk: '>=0.1.2 <1.0.0'
+''')
+    ]).create();
+    await pubGet();
+
+    globalPackageServer.add((builder) => builder
+      ..discontinue('foo')
+      ..discontinue('transitive'));
+    // A pub get straight away will not trigger the warning, as we cache
+    // responses for a while.
+    await pubGet();
+    final fooVersionsCache =
+        p.join(globalPackageServer.cachingPath, '.cache', 'foo-versions.json');
+    expect(fileExists(fooVersionsCache), isTrue);
+    deleteEntry(fooVersionsCache);
+    // We warn only about the direct dependency here:
+    await pubGet(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued)
+Got dependencies!
+''');
+    expect(fileExists(fooVersionsCache), isTrue);
+    final c = json.decode(readTextFile(fooVersionsCache));
+    // Make the cache artificially old.
+    c['_fetchedAt'] =
+        DateTime.now().subtract(Duration(days: 5)).toIso8601String();
+    writeTextFile(fooVersionsCache, json.encode(c));
+    globalPackageServer
+        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    await pubGet(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+    final c2 = json.decode(readTextFile(fooVersionsCache));
+    // Make a bad cached value to test that responses are actually from cache.
+    c2['isDiscontinued'] = false;
+    writeTextFile(fooVersionsCache, json.encode(c2));
+    await pubGet(output: '''
+Resolving dependencies...
+Got dependencies!''');
+    // Repairing the cache should reset the package listing caches.
+    await runPub(args: ['cache', 'repair']);
+    await pubGet(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+    // Test that --offline won't try to access the server for retrieving the
+    // status.
+    await serveErrors();
+    await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued replaced by bar)
+Got dependencies!''');
+    deleteEntry(fooVersionsCache);
+    await pubGet(args: ['--offline'], output: '''
+Resolving dependencies...
+Got dependencies!
+''');
+  });
+
   test('get does not fail when status listing fails', () async {
     await servePackages((builder) => builder..serve('foo', '1.2.3'));
     await d.appDir({'foo': '1.2.3'}).create();
diff --git a/test/upgrade/hosted/warn_about_discontinued_test.dart b/test/upgrade/hosted/warn_about_discontinued_test.dart
new file mode 100644
index 0000000..426e14d
--- /dev/null
+++ b/test/upgrade/hosted/warn_about_discontinued_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// 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.10
+import 'package:test/test.dart';
+
+import '../../descriptor.dart' as d;
+import '../../test_pub.dart';
+
+void main() {
+  test('Warns about discontinued dependencies', () async {
+    await servePackages((builder) => builder
+      ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+      ..serve('transitive', '1.0.0'));
+    await d.appDir({'foo': '1.2.3'}).create();
+    await pubGet();
+
+    globalPackageServer.add((builder) => builder
+      ..discontinue('foo')
+      ..discontinue('transitive'));
+    // We warn only about the direct dependency here:
+    await pubUpgrade(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued)
+  transitive 1.0.0
+  No dependencies changed.
+  1 package is discontinued.
+''');
+    globalPackageServer
+        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    // We warn only about the direct dependency here:
+    await pubUpgrade(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued replaced by bar)
+  transitive 1.0.0
+  No dependencies changed.
+  1 package is discontinued.
+''');
+  });
+
+  test('Warns about discontinued dev_dependencies', () async {
+    await servePackages((builder) => builder
+      ..serve('foo', '1.2.3', deps: {'transitive': 'any'})
+      ..serve('transitive', '1.0.0'));
+
+    await d.dir(appPath, [
+      d.file('pubspec.yaml', '''
+name: myapp
+dependencies:
+
+dev_dependencies:
+  foo: 1.2.3
+environment:
+  sdk: '>=0.1.2 <1.0.0'
+''')
+    ]).create();
+    await pubGet();
+
+    globalPackageServer.add((builder) => builder
+      ..discontinue('foo')
+      ..discontinue('transitive'));
+
+    // We warn only about the direct dependency here:
+    await pubUpgrade(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued)
+    transitive 1.0.0
+  No dependencies changed.
+  1 package is discontinued.
+''');
+    globalPackageServer
+        .add((builder) => builder.discontinue('foo', replacementText: 'bar'));
+    // We warn only about the direct dependency here:
+    await pubUpgrade(output: '''
+Resolving dependencies...
+  foo 1.2.3 (discontinued replaced by bar)
+  transitive 1.0.0
+  No dependencies changed.
+  1 package is discontinued.
+''');
+  });
+}