Support for parameters of constructors and methods.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I836978414ce765269a8482f1649c400b2d4c960c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107193
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index d2a5827..da6af12 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -327,16 +327,12 @@
         _FunctionBodyAccess(node),
       );
 
-      var function = node.parent;
-      if (function is FunctionExpression) {
-        var parameters = function.parameters;
-        if (parameters != null) {
-          for (var parameter in parameters?.parameters) {
-            flow.add(parameter.declaredElement, assigned: true);
-          }
+      var parameters = _enclosingExecutableParameters(node);
+      if (parameters != null) {
+        for (var parameter in parameters.parameters) {
+          flow.add(parameter.declaredElement, assigned: true);
         }
       }
-      // TODO(scheglov) Methods and constructors.
 
       super.visitBlockFunctionBody(node);
 
@@ -703,6 +699,20 @@
     unreachableNodes.add(node);
   }
 
+  FormalParameterList _enclosingExecutableParameters(FunctionBody node) {
+    var parent = node.parent;
+    if (parent is ConstructorDeclaration) {
+      return parent.parameters;
+    }
+    if (parent is FunctionExpression) {
+      return parent.parameters;
+    }
+    if (parent is MethodDeclaration) {
+      return parent.parameters;
+    }
+    return null;
+  }
+
   /// Return the target of the `break` or `continue` statement with the
   /// [element] label. The [element] might be `null` (when the statement does
   /// not specify a label), so the default enclosing target is returned.
diff --git a/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart b/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
index 77ad390..f9cb0c4 100644
--- a/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
@@ -1489,6 +1489,38 @@
     assertNonNullable('x; // 2');
   }
 
+  test_method_if_then_else() async {
+    await trackCode(r'''
+class C {
+  void f(int x) {
+    if (x == null) {
+      x; // 1
+    } else {
+      x; // 2
+    }
+  }
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable('x; // 2');
+  }
+
+  test_constructor_if_then_else() async {
+    await trackCode(r'''
+class C {
+  C(int x) {
+    if (x == null) {
+      x; // 1
+    } else {
+      x; // 2
+    }
+  }
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable('x; // 2');
+  }
+
   test_potentiallyMutatedInClosure() async {
     await trackCode(r'''
 f(int a, int b) {