Use LinterContext.resolveNameInScope() for avoid_types_as_parameter_names. (#2062) (#2064)

Co-authored-by: Konstantin Scheglov <scheglov@google.com>
diff --git a/lib/src/rules/avoid_types_as_parameter_names.dart b/lib/src/rules/avoid_types_as_parameter_names.dart
index 5ab51d0..b5ad339 100644
--- a/lib/src/rules/avoid_types_as_parameter_names.dart
+++ b/lib/src/rules/avoid_types_as_parameter_names.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
 
 import '../analyzer.dart';
 
@@ -36,7 +37,7 @@
   @override
   void registerNodeProcessors(
       NodeLintRegistry registry, LinterContext context) {
-    final visitor = _Visitor(this);
+    final visitor = _Visitor(this, context);
     registry.addFormalParameterList(this, visitor);
     registry.addCatchClause(this, visitor);
   }
@@ -44,21 +45,14 @@
 
 class _Visitor extends SimpleAstVisitor<void> {
   final LintRule rule;
+  final LinterContext context;
 
-  _Visitor(this.rule);
-
-  bool isTypeName(String name) =>
-      // TODO(a14n) test that parameter name matches a existing type. No api to do
-      // that for now.
-      // todo (pq): consider adding a lookup method to LinterContext.
-      name != null &&
-      (name.startsWith(RegExp('[A-Z]')) ||
-          ['num', 'int', 'double', 'bool', 'dynamic'].contains(name));
+  _Visitor(this.rule, this.context);
 
   @override
   void visitCatchClause(CatchClause node) {
     final parameter = node.exceptionParameter;
-    if (parameter != null && isTypeName(parameter.name)) {
+    if (parameter != null && _isTypeName(node, parameter)) {
       rule.reportLint(parameter);
     }
   }
@@ -69,9 +63,18 @@
 
     for (final parameter in node.parameters) {
       if (parameter.declaredElement.hasImplicitType &&
-          isTypeName(parameter.identifier.name)) {
+          _isTypeName(node, parameter.identifier)) {
         rule.reportLint(parameter.identifier);
       }
     }
   }
+
+  bool _isTypeName(AstNode scope, SimpleIdentifier node) {
+    final result = context.resolveNameInScope(node.name, false, scope);
+    if (result.isRequestedName) {
+      final element = result.element;
+      return element is ClassElement || element is FunctionTypeAliasElement;
+    }
+    return false;
+  }
 }
diff --git a/test/rules/avoid_types_as_parameter_names.dart b/test/rules/avoid_types_as_parameter_names.dart
index 9bb3af6..75c7f76 100644
--- a/test/rules/avoid_types_as_parameter_names.dart
+++ b/test/rules/avoid_types_as_parameter_names.dart
@@ -28,7 +28,7 @@
   bool, // LINT
 ]);
 typedef f6 = int Function(int); // OK
-typedef void f7(Undefined); // LINT
+typedef void f7(Undefined); // OK
 
 m1(f()) => null; // OK
 m2(f(int a)) => null; // OK
@@ -36,6 +36,9 @@
 m4(f(num a, {int})) => null; // LINT
 m5(f(double a, [bool])) => null; // LINT
 m6(int Function(int) f)=> null; // OK
-m7(f(Undefined)) => null; // LINT
+m7(f(Undefined)) => null; // OK
+m8(f6) => null; // LINT
+m9(f7) => null; // LINT
+m10(m1) => null; // OK
 
 final void Function(Object, [StackTrace]) onError = null; // OK