allow inferred types in final field assignments (#2089)

* allow inferred types in final variable assignments

* whoops — test code

* null checks

* over-cautious
diff --git a/lib/src/rules/type_annotate_public_apis.dart b/lib/src/rules/type_annotate_public_apis.dart
index 052ad5a..c910e88 100644
--- a/lib/src/rules/type_annotate_public_apis.dart
+++ b/lib/src/rules/type_annotate_public_apis.dart
@@ -130,6 +130,13 @@
 
   _VisitorHelper(this.rule);
 
+  bool hasInferredType(VariableDeclaration node) {
+    var staticType = node.initializer?.staticType;
+    return staticType != null &&
+        !staticType.isDynamic &&
+        !staticType.isDartCoreNull;
+  }
+
   @override
   void visitSimpleFormalParameter(SimpleFormalParameter param) {
     if (param.type == null && !isJustUnderscores(param.identifier.name)) {
@@ -139,7 +146,9 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
-    if (!isPrivate(node.name) && !node.isConst) {
+    if (!isPrivate(node.name) &&
+        !node.isConst &&
+        !(node.isFinal && hasInferredType(node))) {
       rule.reportLint(node.name);
     }
   }
diff --git a/test/rules/type_annotate_public_apis.dart b/test/rules/type_annotate_public_apis.dart
index 90b6cd9..e15d1bc 100644
--- a/test/rules/type_annotate_public_apis.dart
+++ b/test/rules/type_annotate_public_apis.dart
@@ -4,6 +4,19 @@
 
 // test w/ `pub run test -N type_annotate_public_apis`
 
+class AA {
+  final a = AA(); //OK
+  static final aa = AA(); //OK
+  final i = 0; //OK
+  static final ii = 0; //OK
+  final d = dyn(); //LINT
+  static final dd = dyn(); //LINT
+  final n = null; //LINT
+  static final nn = null; //LINT
+}
+
+dynamic dyn() => null;
+
 const X = ''; //OK
 
 f() {} //LINT
@@ -32,9 +45,8 @@
 
 class A {
   var x; // LINT
-  final xx = 1; //LINT
   static const y = ''; //OK
-  static final z = 3; //LINT
+  static final z = 3; //OK
 
   int get xxx => 42; //OK: #151