Rewrite parameter handling and add required named parameters for nnbd (#2075)

* Rewrite parameter handling and add required named parameters for nnbd

* Reduce indentation from named/optional parameters
diff --git a/lib/resources/styles.css b/lib/resources/styles.css
index 4af690d..711fde7 100644
--- a/lib/resources/styles.css
+++ b/lib/resources/styles.css
@@ -381,6 +381,12 @@
   display: unset;
 }
 
+.parameter-list {
+  display: table-cell;
+  margin-left: 10px;
+  list-style-type: none;
+}
+
 .signature {
   color: #727272;
 }
diff --git a/lib/src/model/model_element.dart b/lib/src/model/model_element.dart
index 671a1bd..29e54b5 100644
--- a/lib/src/model/model_element.dart
+++ b/lib/src/model/model_element.dart
@@ -930,7 +930,8 @@
 
   String get linkedParams => utils.linkedParams(parameters);
 
-  String get linkedParamsLines => utils.linkedParams(parameters).trim();
+  String get linkedParamsLines =>
+      utils.linkedParams(parameters, asList: true).trim();
 
   String get linkedParamsNoMetadata =>
       utils.linkedParams(parameters, showMetadata: false);
diff --git a/lib/src/model/parameter.dart b/lib/src/model/parameter.dart
index a1a0286..19c88d7 100644
--- a/lib/src/model/parameter.dart
+++ b/lib/src/model/parameter.dart
@@ -62,12 +62,15 @@
 
   bool get isCovariant => _parameter.isCovariant;
 
-  bool get isOptional => _parameter.isOptional;
+  bool get isRequiredPositional => _parameter.isRequiredPositional;
 
-  bool get isOptionalNamed => _parameter.isNamed;
+  bool get isNamed => _parameter.isNamed;
 
   bool get isOptionalPositional => _parameter.isOptionalPositional;
 
+  /// Only true if this is a required named parameter.
+  bool get isRequiredNamed => _parameter.isRequiredNamed;
+
   @override
   String get kind => 'parameter';
 
diff --git a/lib/src/model_utils.dart b/lib/src/model_utils.dart
index 35c1d1d..22d9afe 100644
--- a/lib/src/model_utils.dart
+++ b/lib/src/model_utils.dart
@@ -16,130 +16,184 @@
 
 final Map<String, String> _fileContents = <String, String>{};
 
-String linkedParams(List<Parameter> parameters,
-    {bool showMetadata = true,
-    bool showNames = true,
-    String separator = ', '}) {
-  List<Parameter> requiredParams =
-      parameters.where((Parameter p) => !p.isOptional).toList();
-  List<Parameter> positionalParams =
-      parameters.where((Parameter p) => p.isOptionalPositional).toList();
-  List<Parameter> namedParams =
-      parameters.where((Parameter p) => p.isOptionalNamed).toList();
-
-  StringBuffer builder = StringBuffer();
-
-  // prefix
-  if (requiredParams.isEmpty && positionalParams.isNotEmpty) {
-    builder.write('[');
-  } else if (requiredParams.isEmpty && namedParams.isNotEmpty) {
-    builder.write('{');
-  }
-
-  // index over params
-  for (Parameter param in requiredParams) {
-    bool isLast = param == requiredParams.last;
-    String ext;
-    if (isLast && positionalParams.isNotEmpty) {
-      ext = ', [';
-    } else if (isLast && namedParams.isNotEmpty) {
-      ext = ', {';
-    } else {
-      ext = isLast ? '' : ', ';
-    }
-    builder.write(renderParam(param, ext, showMetadata, showNames));
-    builder.write(' ');
-  }
-  for (Parameter param in positionalParams) {
-    bool isLast = param == positionalParams.last;
-    builder
-        .write(renderParam(param, isLast ? '' : ', ', showMetadata, showNames));
-    builder.write(' ');
-  }
-  for (Parameter param in namedParams) {
-    bool isLast = param == namedParams.last;
-    builder
-        .write(renderParam(param, isLast ? '' : ', ', showMetadata, showNames));
-    builder.write(' ');
-  }
-
-  // suffix
-  if (namedParams.isNotEmpty) {
-    builder.write('}');
-  } else if (positionalParams.isNotEmpty) {
-    builder.write(']');
-  }
-
-  return builder.toString().trim();
+/// Render HTML in an extended vertical format using <ol> tag.
+class ParameterRendererHtmlList extends ParameterRendererHtml {
+  ParameterRendererHtmlList({bool showMetadata = true, bool showNames = true})
+      : super(showMetadata: showMetadata, showNames: showNames);
+  @override
+  String listItem(String listItem) => '<li>$listItem</li>\n';
+  @override
+  // TODO(jcollins-g): consider comma separated lists and more advanced css.
+  String orderedList(String listItems) =>
+      '<ol class="parameter-list">$listItems</ol>\n';
 }
 
-String renderParam(
-    Parameter param, String suffix, bool showMetadata, bool showNames) {
-  StringBuffer buf = StringBuffer();
-  ElementType paramModelType = param.modelType;
+/// Render HTML suitable for a single, wrapped line.
+class ParameterRendererHtml extends ParameterRenderer {
+  @override
+  final bool showMetadata;
+  @override
+  final bool showNames;
+  ParameterRendererHtml({this.showMetadata = true, this.showNames = true});
 
-  buf.write('<span class="parameter" id="${param.htmlId}">');
-  if (showMetadata && param.hasAnnotations) {
-    param.annotations.forEach((String annotation) {
-      buf.write('<span>$annotation</span> ');
+  @override
+  String listItem(String listItem) => '${listItem}<wbr>';
+  @override
+  String orderedList(String listItems) => listItems;
+  @override
+  String annotation(String annotation) => '<span>$annotation</span>';
+  @override
+  String covariant(String covariant) => '<span>$covariant</span>';
+  @override
+  String defaultValue(String defaultValue) =>
+      '<span class="default-value">$defaultValue</span>';
+  @override
+  String parameter(String parameter, String htmlId) =>
+      '<span class="parameter" id="${htmlId}">$parameter</span>';
+  @override
+  String parameterName(String parameterName) =>
+      '<span class="parameter-name">$parameterName</span>';
+  @override
+  String typeName(String typeName) =>
+      '<span class="type-annotation">$typeName</span>';
+  @override
+  String required(String required) => '<span>$required</span>';
+}
+
+abstract class ParameterRenderer {
+  bool get showMetadata;
+  bool get showNames;
+
+  String listItem(String item);
+  String orderedList(String listItems);
+  String annotation(String annotation);
+  String covariant(String covariant);
+  String defaultValue(String defaultValue);
+  String parameter(String parameter, String id);
+  String parameterName(String parameterName);
+  String typeName(String typeName);
+  String required(String required);
+
+  String _linkedParameterSublist(List<Parameter> parameters, bool trailingComma,
+      {String thisOpenBracket = '', String thisCloseBracket = ''}) {
+    StringBuffer builder = StringBuffer();
+    parameters.forEach((p) {
+      String prefix = '';
+      String suffix = '';
+      if (identical(p, parameters.first)) {
+        prefix = thisOpenBracket;
+      }
+      if (identical(p, parameters.last)) {
+        suffix += thisCloseBracket;
+        if (trailingComma) suffix += ', ';
+      } else {
+        suffix += ', ';
+      }
+      builder.write(
+          listItem(parameter(prefix + renderParam(p) + suffix, p.htmlId)));
     });
-  }
-  if (param.isCovariant) {
-    buf.write('<span>covariant</span> ');
-  }
-  if (paramModelType is CallableElementTypeMixin ||
-      paramModelType.type is FunctionType) {
-    String returnTypeName;
-    if (paramModelType.isTypedef) {
-      returnTypeName = paramModelType.linkedName;
-    } else {
-      returnTypeName = paramModelType.createLinkedReturnTypeName();
-    }
-    buf.write('<span class="type-annotation">${returnTypeName}</span>');
-    if (showNames) {
-      buf.write(' <span class="parameter-name">${param.name}</span>');
-    } else if (paramModelType.isTypedef ||
-        paramModelType is CallableAnonymousElementType ||
-        paramModelType.type is FunctionType) {
-      buf.write(' <span class="parameter-name">${paramModelType.name}</span>');
-    }
-    if (!paramModelType.isTypedef && paramModelType is DefinedElementType) {
-      buf.write('(');
-      buf.write(linkedParams(paramModelType.element.parameters,
-          showNames: showNames, showMetadata: showMetadata));
-      buf.write(')');
-    }
-    if (!paramModelType.isTypedef && paramModelType.type is FunctionType) {
-      buf.write('(');
-      buf.write(linkedParams(
-          (paramModelType as UndefinedElementType).parameters,
-          showNames: showNames,
-          showMetadata: showMetadata));
-      buf.write(')');
-    }
-  } else if (param.modelType != null) {
-    String typeName = paramModelType.linkedName;
-    if (typeName.isNotEmpty) {
-      buf.write('<span class="type-annotation">$typeName</span>');
-    }
-    if (typeName.isNotEmpty && showNames && param.name.isNotEmpty) {
-      buf.write(' ');
-    }
-    if (showNames && param.name.isNotEmpty) {
-      buf.write('<span class="parameter-name">${param.name}</span>');
-    }
+    return builder.toString();
   }
 
-  if (param.hasDefaultValue) {
-    if (param.isOptionalNamed) {
-      buf.write(': ');
-    } else {
-      buf.write(' = ');
+  String linkedParams(List<Parameter> parameters) {
+    List<Parameter> positionalParams =
+        parameters.where((Parameter p) => p.isRequiredPositional).toList();
+    List<Parameter> optionalPositionalParams =
+        parameters.where((Parameter p) => p.isOptionalPositional).toList();
+    List<Parameter> namedParams =
+        parameters.where((Parameter p) => p.isNamed).toList();
+
+    String positional = '', optional = '', named = '';
+    if (positionalParams.isNotEmpty) {
+      positional = _linkedParameterSublist(positionalParams,
+          optionalPositionalParams.isNotEmpty || namedParams.isNotEmpty);
     }
-    buf.write('<span class="default-value">${param.defaultValue}</span>');
+    if (optionalPositionalParams.isNotEmpty) {
+      optional = _linkedParameterSublist(
+          optionalPositionalParams, namedParams.isNotEmpty,
+          thisOpenBracket: '[', thisCloseBracket: ']');
+    }
+    if (namedParams.isNotEmpty) {
+      named = _linkedParameterSublist(namedParams, false,
+          thisOpenBracket: '{', thisCloseBracket: '}');
+    }
+    return (orderedList(positional + optional + named));
   }
-  buf.write('${suffix}</span>');
-  return buf.toString();
+
+  String renderParam(Parameter param) {
+    StringBuffer buf = StringBuffer();
+    ElementType paramModelType = param.modelType;
+
+    if (showMetadata && param.hasAnnotations) {
+      buf.write(param.annotations.map(annotation).join(' ') + ' ');
+    }
+    if (param.isRequiredNamed) {
+      buf.write(required('required') + ' ');
+    }
+    if (param.isCovariant) {
+      buf.write(covariant('covariant') + ' ');
+    }
+    if (paramModelType is CallableElementTypeMixin ||
+        paramModelType.type is FunctionType) {
+      String returnTypeName;
+      if (paramModelType.isTypedef) {
+        returnTypeName = paramModelType.linkedName;
+      } else {
+        returnTypeName = paramModelType.createLinkedReturnTypeName();
+      }
+      buf.write(typeName(returnTypeName));
+      if (showNames) {
+        buf.write(' ${parameterName(param.name)}');
+      } else if (paramModelType.isTypedef ||
+          paramModelType is CallableAnonymousElementType ||
+          paramModelType.type is FunctionType) {
+        buf.write(' ${parameterName(paramModelType.name)}');
+      }
+      if (!paramModelType.isTypedef && paramModelType is DefinedElementType) {
+        buf.write('(');
+        buf.write(linkedParams(paramModelType.element.parameters));
+        buf.write(')');
+      }
+      if (!paramModelType.isTypedef && paramModelType.type is FunctionType) {
+        buf.write('(');
+        buf.write(
+            linkedParams((paramModelType as UndefinedElementType).parameters));
+        buf.write(')');
+      }
+    } else if (param.modelType != null) {
+      String linkedTypeName = paramModelType.linkedName;
+      if (linkedTypeName.isNotEmpty) {
+        buf.write(typeName(linkedTypeName));
+        if (showNames && param.name.isNotEmpty) {
+          buf.write(' ');
+        }
+      }
+      if (showNames && param.name.isNotEmpty) {
+        buf.write(parameterName(param.name));
+      }
+    }
+
+    if (param.hasDefaultValue) {
+      if (param.isNamed) {
+        buf.write(': ');
+      } else {
+        buf.write(' = ');
+      }
+      buf.write(defaultValue(param.defaultValue));
+    }
+    return buf.toString();
+  }
+}
+
+String linkedParams(List<Parameter> parameters,
+    {showMetadata = true, showNames = true, asList = false}) {
+  if (asList) {
+    return ParameterRendererHtmlList(
+            showMetadata: showMetadata, showNames: showNames)
+        .linkedParams(parameters);
+  }
+  return ParameterRendererHtml(showMetadata: showMetadata, showNames: showNames)
+      .linkedParams(parameters);
 }
 
 /// Returns the [AstNode] for a given [Element].
diff --git a/test/model_special_cases_test.dart b/test/model_special_cases_test.dart
index fdcd827..255f095 100644
--- a/test/model_special_cases_test.dart
+++ b/test/model_special_cases_test.dart
@@ -29,11 +29,61 @@
   // Experimental features not yet enabled by default.  Move tests out of this block
   // when the feature is enabled by default.
   group('Experiments', () {
-    Library lateFinalWithoutInitializer;
+    Library lateFinalWithoutInitializer, nnbdClassMemberDeclarations;
+    Class b;
     setUpAll(() async {
       lateFinalWithoutInitializer = (await utils.testPackageGraphExperiments)
           .libraries
           .firstWhere((lib) => lib.name == 'late_final_without_initializer');
+      nnbdClassMemberDeclarations = (await utils.testPackageGraphExperiments)
+          .libraries
+          .firstWhere((lib) => lib.name == 'nnbd_class_member_declarations');
+      b = nnbdClassMemberDeclarations.allClasses
+          .firstWhere((c) => c.name == 'B');
+    });
+
+    test('method parameters with required', () {
+      Method m1 = b.allInstanceMethods.firstWhere((m) => m.name == 'm1');
+      Parameter p1 = m1.allParameters.firstWhere((p) => p.name == 'p1');
+      Parameter p2 = m1.allParameters.firstWhere((p) => p.name == 'p2');
+      expect(p1.isRequiredNamed, isTrue);
+      expect(p2.isRequiredNamed, isFalse);
+      expect(p2.isNamed, isTrue);
+
+      expect(
+          m1.linkedParamsLines,
+          equals(
+              '<ol class="parameter-list"><li><span class="parameter" id="m1-param-some"><span class="type-annotation">int</span> <span class="parameter-name">some</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-regular"><span class="type-annotation">dynamic</span> <span class="parameter-name">regular</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-parameters"><span>covariant</span> <span class="type-annotation">dynamic</span> <span class="parameter-name">parameters</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-p1">{<span>required</span> <span class="type-annotation">dynamic</span> <span class="parameter-name">p1</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-p2"><span class="type-annotation">int</span> <span class="parameter-name">p2</span>: <span class="default-value">3</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-p3"><span>required</span> <span>covariant</span> <span class="type-annotation">dynamic</span> <span class="parameter-name">p3</span>, </span></li>\n'
+              '<li><span class="parameter" id="m1-param-p4"><span>required</span> <span>covariant</span> <span class="type-annotation">int</span> <span class="parameter-name">p4</span>}</span></li>\n'
+              '</ol>'));
+    });
+
+    test('verify no regression on ordinary optionals', () {
+      Method m2 = b.allInstanceMethods.firstWhere((m) => m.name == 'm2');
+      Parameter sometimes =
+          m2.allParameters.firstWhere((p) => p.name == 'sometimes');
+      Parameter optionals =
+          m2.allParameters.firstWhere((p) => p.name == 'optionals');
+      expect(sometimes.isRequiredNamed, isFalse);
+      expect(sometimes.isRequiredPositional, isTrue);
+      expect(sometimes.isOptionalPositional, isFalse);
+      expect(optionals.isRequiredNamed, isFalse);
+      expect(optionals.isRequiredPositional, isFalse);
+      expect(optionals.isOptionalPositional, isTrue);
+
+      expect(
+          m2.linkedParamsLines,
+          equals(
+              '<ol class="parameter-list"><li><span class="parameter" id="m2-param-sometimes"><span class="type-annotation">int</span> <span class="parameter-name">sometimes</span>, </span></li>\n'
+              '<li><span class="parameter" id="m2-param-we"><span class="type-annotation">dynamic</span> <span class="parameter-name">we</span>, </span></li>\n'
+              '<li><span class="parameter" id="m2-param-have">[<span class="type-annotation">String</span> <span class="parameter-name">have</span>, </span></li>\n'
+              '<li><span class="parameter" id="m2-param-optionals"><span class="type-annotation">double</span> <span class="parameter-name">optionals</span>]</span></li>\n'
+              '</ol>'));
     });
 
     test('Late final class member test', () {
diff --git a/test/model_test.dart b/test/model_test.dart
index c67bf45..953beba 100644
--- a/test/model_test.dart
+++ b/test/model_test.dart
@@ -2108,7 +2108,7 @@
       expect(
           linkedParams(paramOfFutureOrNull.parameters),
           equals(
-              '<span class="parameter" id="paramOfFutureOrNull-param-future"><span class="type-annotation">FutureOr<span class="signature">&lt;<wbr><span class="type-parameter">Null</span>&gt;</span></span> <span class="parameter-name">future</span></span>'));
+              '<span class="parameter" id="paramOfFutureOrNull-param-future"><span class="type-annotation">FutureOr<span class="signature">&lt;<wbr><span class="type-parameter">Null</span>&gt;</span></span> <span class="parameter-name">future</span></span><wbr>'));
     });
 
     test('function with a bound type to FutureOr', () {
@@ -2139,7 +2139,7 @@
           params,
           '<span class="parameter" id="addCallback-param-callback">'
           '<span class="type-annotation"><a href="fake/VoidCallback.html">VoidCallback</a></span> '
-          '<span class="parameter-name">callback</span></span>');
+          '<span class="parameter-name">callback</span></span><wbr>');
 
       function =
           fakeLibrary.functions.firstWhere((f) => f.name == 'addCallback2');
@@ -2148,7 +2148,7 @@
           params,
           '<span class="parameter" id="addCallback2-param-callback">'
           '<span class="type-annotation"><a href="fake/Callback2.html">Callback2</a></span> '
-          '<span class="parameter-name">callback</span></span>');
+          '<span class="parameter-name">callback</span></span><wbr>');
     });
 
     test('supports generic methods', () {
@@ -2159,7 +2159,7 @@
     test('can resolve functions as parameters', () {
       String params = linkedParams(doAComplicatedThing.parameters);
       expect(params,
-          '<span class="parameter" id="doAComplicatedThing-param-x"><span class="type-annotation">int</span> <span class="parameter-name">x</span>, {</span> <span class="parameter" id="doAComplicatedThing-param-doSomething"><span class="type-annotation">void</span> <span class="parameter-name">doSomething</span>(<span class="parameter" id="param-aThingParameter"><span class="type-annotation">int</span> <span class="parameter-name">aThingParameter</span>, </span> <span class="parameter" id="param-anotherThing"><span class="type-annotation">String</span> <span class="parameter-name">anotherThing</span></span>), </span> <span class="parameter" id="doAComplicatedThing-param-doSomethingElse"><span class="type-annotation">void</span> <span class="parameter-name">doSomethingElse</span>(<span class="parameter" id="param-aThingParameter"><span class="type-annotation">int</span> <span class="parameter-name">aThingParameter</span>, </span> <span class="parameter" id="param-somethingElse"><span class="type-annotation">double</span> <span class="parameter-name">somethingElse</span></span>)</span> }');
+          '<span class="parameter" id="doAComplicatedThing-param-x"><span class="type-annotation">int</span> <span class="parameter-name">x</span>, </span><wbr><span class="parameter" id="doAComplicatedThing-param-doSomething">{<span class="type-annotation">void</span> <span class="parameter-name">doSomething</span>(<span class="parameter" id="param-aThingParameter"><span class="type-annotation">int</span> <span class="parameter-name">aThingParameter</span>, </span><wbr><span class="parameter" id="param-anotherThing"><span class="type-annotation">String</span> <span class="parameter-name">anotherThing</span></span><wbr>), </span><wbr><span class="parameter" id="doAComplicatedThing-param-doSomethingElse"><span class="type-annotation">void</span> <span class="parameter-name">doSomethingElse</span>(<span class="parameter" id="param-aThingParameter"><span class="type-annotation">int</span> <span class="parameter-name">aThingParameter</span>, </span><wbr><span class="parameter" id="param-somethingElse"><span class="type-annotation">double</span> <span class="parameter-name">somethingElse</span></span><wbr>)}</span><wbr>');
     });
   });
 
@@ -2179,7 +2179,7 @@
       // TODO(jcollins-g): really, these shouldn't be called "parameters" in
       // the span class.
       expect(explicitSetter.linkedReturnType,
-          '<span class="parameter" id="explicitSetter=-param-f"><span class="type-annotation">dynamic</span> <span class="parameter-name">Function</span>(<span class="parameter" id="param-bar"><span class="type-annotation">int</span>, </span> <span class="parameter" id="param-baz"><span class="type-annotation"><a href="fake/Cool-class.html">Cool</a></span>, </span> <span class="parameter" id="param-macTruck"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span></span>)</span>');
+          '<span class="parameter" id="explicitSetter=-param-f"><span class="type-annotation">dynamic</span> <span class="parameter-name">Function</span>(<span class="parameter" id="param-bar"><span class="type-annotation">int</span>, </span><wbr><span class="parameter" id="param-baz"><span class="type-annotation"><a href="fake/Cool-class.html">Cool</a></span>, </span><wbr><span class="parameter" id="param-macTruck"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span></span><wbr>)</span><wbr>');
     });
 
     test('parameterized type from field is correctly displayed', () {
@@ -2227,7 +2227,7 @@
       // TODO(jcollins-g): really, these shouldn't be called "parameters" in
       // the span class.
       expect(aInheritedSetter.enclosingCombo.linkedReturnType,
-          '<span class="parameter" id="aInheritedSetter=-param-thingToSet"><span class="type-annotation"><a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature">&lt;<wbr><span class="type-parameter">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span>&gt;</span></span></span>');
+          '<span class="parameter" id="aInheritedSetter=-param-thingToSet"><span class="type-annotation"><a href="ex/AnotherParameterizedClass-class.html">AnotherParameterizedClass</a><span class="signature">&lt;<wbr><span class="type-parameter">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span>&gt;</span></span></span><wbr>');
     });
 
     test(
@@ -2276,7 +2276,7 @@
       expect(aInheritedAdditionOperator.linkedReturnType,
           '<a href="ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature">&lt;<wbr><span class="type-parameter">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span>&gt;</span>');
       expect(linkedParams(aInheritedAdditionOperator.parameters),
-          '<span class="parameter" id="+-param-other"><span class="type-annotation"><a href="ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature">&lt;<wbr><span class="type-parameter">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span>&gt;</span></span> <span class="parameter-name">other</span></span>');
+          '<span class="parameter" id="+-param-other"><span class="type-annotation"><a href="ex/ParameterizedClass-class.html">ParameterizedClass</a><span class="signature">&lt;<wbr><span class="type-parameter">List<span class="signature">&lt;<wbr><span class="type-parameter">int</span>&gt;</span></span>&gt;</span></span> <span class="parameter-name">other</span></span><wbr>');
     });
 
     test('', () {});
@@ -2339,7 +2339,7 @@
       expect(
           getAFunctionReturningVoid.linkedReturnType,
           equals(
-              'void Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">T1</span>, </span> <span class="parameter" id="param-"><span class="type-annotation">T2</span></span>)</span>'));
+              'void Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">T1</span>, </span><wbr><span class="parameter" id="param-"><span class="type-annotation">T2</span></span><wbr>)</span>'));
     });
 
     test(
@@ -2348,7 +2348,7 @@
       expect(
           getAFunctionReturningBool.linkedReturnType,
           equals(
-              'bool Function&lt;<wbr><span class="type-parameter">T4</span>&gt;<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">String</span>, </span> <span class="parameter" id="param-"><span class="type-annotation">T1</span>, </span> <span class="parameter" id="param-"><span class="type-annotation">T4</span></span>)</span>'));
+              'bool Function&lt;<wbr><span class="type-parameter">T4</span>&gt;<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">String</span>, </span><wbr><span class="parameter" id="param-"><span class="type-annotation">T1</span>, </span><wbr><span class="parameter" id="param-"><span class="type-annotation">T4</span></span><wbr>)</span>'));
     });
 
     test('has a fully qualified name', () {
@@ -2946,11 +2946,11 @@
       expect(
           typeArguments.last.linkedName,
           equals(
-              'dynamic Function<span class="signature">(<span class="parameter" id="param-a"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">num</span>&gt;</span></span> <span class="parameter-name">a</span></span>)</span>'));
+              'dynamic Function<span class="signature">(<span class="parameter" id="param-a"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">num</span>&gt;</span></span> <span class="parameter-name">a</span></span><wbr>)</span>'));
       expect(
           importantComputations.linkedReturnType,
           equals(
-              'Map<span class="signature">&lt;<wbr><span class="type-parameter">int</span>, <span class="type-parameter">dynamic Function<span class="signature">(<span class="parameter" id="param-a"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">num</span>&gt;</span></span> <span class="parameter-name">a</span></span>)</span></span>&gt;</span>'));
+              'Map<span class="signature">&lt;<wbr><span class="type-parameter">int</span>, <span class="type-parameter">dynamic Function<span class="signature">(<span class="parameter" id="param-a"><span class="type-annotation">List<span class="signature">&lt;<wbr><span class="type-parameter">num</span>&gt;</span></span> <span class="parameter-name">a</span></span><wbr>)</span></span>&gt;</span>'));
     });
 
     test(
@@ -2959,7 +2959,7 @@
       expect(
           complicatedReturn.linkedReturnType,
           equals(
-              '<a href="fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature">&lt;<wbr><span class="type-parameter">String Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">int</span></span>)</span></span>&gt;</span>'));
+              '<a href="fake/ATypeTakingClass-class.html">ATypeTakingClass</a><span class="signature">&lt;<wbr><span class="type-parameter">String Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">int</span></span><wbr>)</span></span>&gt;</span>'));
     });
 
     test('@nodoc on simple property works', () {
@@ -3244,7 +3244,7 @@
           linkedParams(aVoidParameter.parameters,
               showMetadata: true, showNames: true),
           equals(
-              '<span class="parameter" id="aVoidParameter-param-p1"><span class="type-annotation">Future<span class="signature">&lt;<wbr><span class="type-parameter">void</span>&gt;</span></span> <span class="parameter-name">p1</span></span>'));
+              '<span class="parameter" id="aVoidParameter-param-p1"><span class="type-annotation">Future<span class="signature">&lt;<wbr><span class="type-parameter">void</span>&gt;</span></span> <span class="parameter-name">p1</span></span><wbr>'));
     });
 
     test('a class that extends Future<void>', () {
@@ -3326,7 +3326,7 @@
       expect(
           linkedParams(theConstructor.parameters),
           equals(
-              '<span class="parameter" id="-param-x"><span class="type-annotation"><a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature">&lt;<wbr><span class="type-parameter">double</span>&gt;</span></span> <span class="parameter-name">x</span></span>'));
+              '<span class="parameter" id="-param-x"><span class="type-annotation"><a href="ex/ParameterizedTypedef.html">ParameterizedTypedef</a><span class="signature">&lt;<wbr><span class="type-parameter">double</span>&gt;</span></span> <span class="parameter-name">x</span></span><wbr>'));
     });
 
     test('anonymous nested functions inside typedefs are handled', () {
@@ -3343,11 +3343,13 @@
       expect(
           aComplexTypedef.linkedReturnType,
           equals(
-              'void Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">A1</span>, </span> <span class="parameter" id="param-"><span class="type-annotation">A2</span>, </span> <span class="parameter" id="param-"><span class="type-annotation">A3</span></span>)</span>'));
+              'void Function<span class="signature">(<span class="parameter" id="param-"><span class="type-annotation">A1</span>, </span><wbr><span class="parameter" id="param-"><span class="type-annotation">A2</span>, </span><wbr><span class="parameter" id="param-"><span class="type-annotation">A3</span></span><wbr>)</span>'));
       expect(
           aComplexTypedef.linkedParamsLines,
           equals(
-              '<span class="parameter" id="aComplexTypedef-param-"><span class="type-annotation">A3</span>, </span> <span class="parameter" id="aComplexTypedef-param-"><span class="type-annotation">String</span></span>'));
+              '<ol class="parameter-list"><li><span class="parameter" id="aComplexTypedef-param-"><span class="type-annotation">A3</span>, </span></li>\n'
+              '<li><span class="parameter" id="aComplexTypedef-param-"><span class="type-annotation">String</span></span></li>\n'
+              '</ol>'));
     });
 
     test('has a fully qualified name', () {
@@ -3446,8 +3448,10 @@
     });
 
     test('is optional', () {
-      expect(intCheckOptional.isOptional, isTrue);
-      expect(intNumber.isOptional, isFalse);
+      expect(intCheckOptional.isNamed, isTrue);
+      expect(intCheckOptional.isRequiredNamed, isFalse);
+      expect(intNumber.isNamed, isFalse);
+      expect(intNumber.isRequiredPositional, isTrue);
     });
 
     test('default value', () {
@@ -3455,7 +3459,7 @@
     });
 
     test('is named', () {
-      expect(intCheckOptional.isOptionalNamed, isTrue);
+      expect(intCheckOptional.isNamed, isTrue);
     });
 
     test('linkedName', () {
@@ -3496,7 +3500,7 @@
       expect(
           params,
           equals(
-              '<span class="parameter" id="methodWithTypedefParam-param-p"><span class="type-annotation"><a href="ex/processMessage.html">processMessage</a></span> <span class="parameter-name">p</span></span>'));
+              '<span class="parameter" id="methodWithTypedefParam-param-p"><span class="type-annotation"><a href="ex/processMessage.html">processMessage</a></span> <span class="parameter-name">p</span></span><wbr>'));
     });
   });
 
diff --git a/testing/test_package_experiments/lib/nnbd_class_member_declarations.dart b/testing/test_package_experiments/lib/nnbd_class_member_declarations.dart
new file mode 100644
index 0000000..6250e5b
--- /dev/null
+++ b/testing/test_package_experiments/lib/nnbd_class_member_declarations.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+library nnbd_class_member_declarations;
+
+/// Test required and covariant parameters
+abstract class B {
+  m1(int some, regular, covariant parameters, {
+      required p1,
+      int p2 = 3,
+      required covariant p3,
+      required covariant int p4,
+  });
+  m2(int sometimes, we, [String have, double optionals]);
+}
+