Add containsTypeParameter() helper.

Change-Id: Id1a7b22e0a0d5a1b5c3338ec0a216df49933af80
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/180241
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 56ef139..88848f7 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -296,6 +296,33 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    if (typeFormals.any((element) {
+      var elementImpl = element as TypeParameterElementImpl;
+      assert(!parameters.contains(elementImpl));
+
+      var bound = elementImpl.bound as TypeImpl;
+      if (bound != null && bound.referencesAny(parameters)) {
+        return true;
+      }
+
+      var defaultType = elementImpl.defaultType as TypeImpl;
+      return defaultType.referencesAny(parameters);
+    })) {
+      return true;
+    }
+
+    if (this.parameters.any((element) {
+      var type = element.type as TypeImpl;
+      return type.referencesAny(parameters);
+    })) {
+      return true;
+    }
+
+    return (returnType as TypeImpl).referencesAny(parameters);
+  }
+
+  @override
   TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
     return FunctionTypeImpl(
@@ -1312,6 +1339,14 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return typeArguments.any((argument) {
+      var argumentImpl = argument as TypeImpl;
+      return argumentImpl.referencesAny(parameters);
+    });
+  }
+
+  @override
   InterfaceTypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
     if (this.nullabilitySuffix == nullabilitySuffix) return this;
 
@@ -1712,6 +1747,11 @@
     return builder.toString();
   }
 
+  /// Returns true if this type references any of the [parameters].
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return false;
+  }
+
   @override
   DartType resolveToBound(DartType objectType) => this;
 
@@ -1853,6 +1893,11 @@
   }
 
   @override
+  bool referencesAny(Set<TypeParameterElement> parameters) {
+    return parameters.contains(element);
+  }
+
+  @override
   DartType resolveToBound(DartType objectType) {
     if (promotedBound != null) {
       return promotedBound;
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 6efd3dd..bac0ac6 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -25,6 +25,7 @@
 import 'type_bounded_test.dart' as type_bounded;
 import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer;
 import 'type_parameter_element_test.dart' as type_parameter_element;
+import 'type_references_any_test.dart' as type_references_any;
 import 'type_visitor_test.dart' as type_visitor;
 import 'upper_lower_bound_test.dart' as upper_bound;
 
@@ -52,6 +53,7 @@
     type_bounded.main();
     type_constraint_gatherer.main();
     type_parameter_element.main();
+    type_references_any.main();
     type_visitor.main();
     upper_bound.main();
   }, name: 'element');
diff --git a/pkg/analyzer/test/src/dart/element/type_references_any_test.dart b/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
new file mode 100644
index 0000000..60b8192
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
@@ -0,0 +1,73 @@
+// 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.
+
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TypeReferencesAnyTest);
+  });
+}
+
+@reflectiveTest
+class TypeReferencesAnyTest extends AbstractTypeSystemNullSafetyTest {
+  TypeParameterElement T;
+  TypeParameterType T_none;
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    T = typeParameter('T');
+    T_none = typeParameterTypeNone(T);
+  }
+
+  test_false() {
+    _checkFalse(dynamicNone);
+    _checkFalse(intNone);
+    _checkFalse(neverNone);
+    _checkFalse(voidNone);
+    _checkFalse(listNone(intNone));
+  }
+
+  test_true() {
+    _checkTrue(T_none);
+    _checkTrue(listNone(T_none));
+    _checkTrue(mapNone(T_none, intNone));
+    _checkTrue(mapNone(intNone, T_none));
+
+    _checkTrue(functionTypeNone(returnType: T_none));
+
+    _checkTrue(
+      functionTypeNone(returnType: voidNone, parameters: [
+        requiredParameter(type: T_none),
+      ]),
+    );
+
+    _checkTrue(
+      functionTypeNone(
+        typeFormals: [
+          typeParameter('U', bound: T_none),
+        ],
+        returnType: voidNone,
+      ),
+    );
+  }
+
+  void _checkFalse(DartType type) {
+    var actual = (type as TypeImpl).referencesAny({T});
+    expect(actual, isFalse);
+  }
+
+  void _checkTrue(DartType type) {
+    var actual = (type as TypeImpl).referencesAny({T});
+    expect(actual, isTrue);
+  }
+}