[Analyzer] Use new NAMED_REQUIRED ParameterKind for signature help

Change-Id: Ia4d23cb51f4e3729e8d40fa5a38dd8b2a8771c03
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162006
Commit-Queue: Danny Tuppeny <danny@tuppeny.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 7514dc1..37b095d9 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.29.1
+  1.30.0
 </h1>
 <p>
   This document contains a specification of the API provided by the
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 76c886f..25f5a64 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.29.1';
+const String PROTOCOL_VERSION = '1.30.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index 6c2f036..8da528f 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.dart
@@ -80,11 +80,13 @@
 
   ParameterInfo _convertParam(ParameterElement param) {
     return ParameterInfo(
-        param.isOptionalPositional
-            ? ParameterKind.OPTIONAL
-            : param.isPositional
-                ? ParameterKind.REQUIRED
-                : ParameterKind.NAMED,
+        param.isOptionalNamed
+            ? ParameterKind.OPTIONAL_NAMED
+            : param.isOptionalPositional
+                ? ParameterKind.OPTIONAL_POSITIONAL
+                : param.isRequiredNamed
+                    ? ParameterKind.REQUIRED_NAMED
+                    : ParameterKind.REQUIRED_POSITIONAL,
         param.displayName,
         param.type.getDisplayString(withNullability: false),
         defaultValue: param.defaultValueCode);
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 0f44750..f710272 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -1073,27 +1073,31 @@
   ///     String s = 'foo'
   String getParamLabel(server.ParameterInfo p) {
     final def = p.defaultValue != null ? ' = ${p.defaultValue}' : '';
-    return '${p.type} ${p.name}$def';
+    final prefix =
+        p.kind == server.ParameterKind.REQUIRED_NAMED ? 'required ' : '';
+    return '$prefix${p.type} ${p.name}$def';
   }
 
   /// Gets the full signature label in the form
   ///     foo(String s, int i, bool a = true)
   String getSignatureLabel(server.AnalysisGetSignatureResult resp) {
-    final req = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.REQUIRED)
+    final positionalRequired = signature.parameters
+        .where((p) => p.kind == server.ParameterKind.REQUIRED_POSITIONAL)
         .toList();
-    final opt = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.OPTIONAL)
+    final positionalOptional = signature.parameters
+        .where((p) => p.kind == server.ParameterKind.OPTIONAL_POSITIONAL)
         .toList();
     final named = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.NAMED)
+        .where((p) =>
+            p.kind == server.ParameterKind.OPTIONAL_NAMED ||
+            p.kind == server.ParameterKind.REQUIRED_NAMED)
         .toList();
     final params = [];
-    if (req.isNotEmpty) {
-      params.add(req.map(getParamLabel).join(', '));
+    if (positionalRequired.isNotEmpty) {
+      params.add(positionalRequired.map(getParamLabel).join(', '));
     }
-    if (opt.isNotEmpty) {
-      params.add('[' + opt.map(getParamLabel).join(', ') + ']');
+    if (positionalOptional.isNotEmpty) {
+      params.add('[' + positionalOptional.map(getParamLabel).join(', ') + ']');
     }
     if (named.isNotEmpty) {
       params.add('{' + named.map(getParamLabel).join(', ') + '}');
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index 0579563..da09214 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -54,7 +54,7 @@
 class MyClass {
   /// MyClass constructor doc
   MyClass(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass("Danny", /*^*/);
 }
@@ -63,10 +63,12 @@
     expect(result.name, equals('MyClass'));
     expect(result.dartdoc, equals('MyClass constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_constructor_factory() async {
@@ -79,7 +81,7 @@
   factory MyClass(String name, {int length}) {
     return new MyClass._();
   }
-} 
+}
 main() {
   var a = new MyClass("Danny", /*^*/);
 }
@@ -88,10 +90,12 @@
     expect(result.name, equals('MyClass'));
     expect(result.dartdoc, equals('MyClass factory constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_constructor_named() async {
@@ -100,7 +104,7 @@
 class MyClass {
   /// MyClass.foo constructor doc
   MyClass.foo(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass.foo("Danny", /*^*/);
 }
@@ -109,10 +113,12 @@
     expect(result.name, equals('MyClass.foo'));
     expect(result.dartdoc, equals('MyClass.foo constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_does_not_walk_up_over_closure() async {
@@ -170,8 +176,10 @@
     expect(result.name, equals('f'));
     expect(result.dartdoc, equals('f doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 's', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 's', 'String')));
   }
 
   Future<void> test_function_from_other_file() async {
@@ -192,10 +200,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_irrelevant_parens() async {
@@ -210,10 +222,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_named() async {
@@ -228,10 +244,12 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_function_named_with_default_int() async {
@@ -246,11 +264,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int',
             defaultValue: '1')));
   }
 
@@ -266,11 +286,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'email', 'String',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'email', 'String',
             defaultValue: '"a@b.c"')));
   }
 
@@ -289,8 +311,10 @@
     expect(result.name, equals('two'));
     expect(result.dartdoc, equals('two doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'two', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'two', 'String')));
   }
 
   Future<void> test_function_nested_call_outer() async {
@@ -308,8 +332,10 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'one', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'one', 'String')));
   }
 
   Future<void> test_function_no_dart_doc() async {
@@ -323,10 +349,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, isNull);
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_optional() async {
@@ -341,10 +371,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.OPTIONAL, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.OPTIONAL_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_optional_with_default() async {
@@ -359,11 +393,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.OPTIONAL, 'length', 'int',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_POSITIONAL, 'length', 'int',
             defaultValue: '11')));
   }
 
@@ -379,10 +415,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_zero_arguments() async {
@@ -427,7 +467,7 @@
   MyClass(String name, {int length}) {}
   /// MyClass instance method
   myMethod(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass("Danny");
   a.myMethod("Danny", /*^*/);
@@ -437,10 +477,12 @@
     expect(result.name, equals('myMethod'));
     expect(result.dartdoc, equals('MyClass instance method'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_method_static() async {
@@ -451,7 +493,7 @@
   MyClass(String name, {int length}) {}
   /// MyClass static method
   static void myStaticMethod(String name, {int length}) {}
-} 
+}
 main() {
   MyClass.myStaticMethod("Danny", /*^*/);
 }
@@ -460,9 +502,11 @@
     expect(result.name, equals('myStaticMethod'));
     expect(result.dartdoc, equals('MyClass static method'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 }
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 354c2aa..534a918 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1206,12 +1206,17 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
-final Matcher isParameterKind =
-    MatchesEnum('ParameterKind', ['NAMED', 'OPTIONAL', 'REQUIRED']);
+final Matcher isParameterKind = MatchesEnum('ParameterKind', [
+  'OPTIONAL_NAMED',
+  'OPTIONAL_POSITIONAL',
+  'REQUIRED_NAMED',
+  'REQUIRED_POSITIONAL'
+]);
 
 /// Position
 ///
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 271c2c6..2468725 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -49,6 +49,8 @@
   TestPluginManager pluginManager;
   LspAnalysisServer server;
 
+  AnalysisServerOptions get serverOptions => AnalysisServerOptions();
+
   @override
   Stream<Message> get serverToClient => channel.serverToClient;
 
@@ -121,7 +123,7 @@
     server = LspAnalysisServer(
         channel,
         resourceProvider,
-        AnalysisServerOptions(),
+        serverOptions,
         DartSdkManager(convertPath('/sdk')),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE);
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart
index 889f9e8..fbac555 100644
--- a/pkg/analysis_server/test/lsp/signature_help_test.dart
+++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/analysis_server.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,11 +12,48 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SignatureHelpTest);
+    defineReflectiveTests(SignatureHelpWithNullSafetyTest);
   });
 }
 
+mixin SignatureHelpMixin on AbstractLspAnalysisServerTest {
+  Future<void> testSignature(
+    String fileContent,
+    String expectedLabel,
+    String expectedDoc,
+    List<ParameterInformation> expectedParams, {
+    MarkupKind expectedFormat = MarkupKind.Markdown,
+    SignatureHelpContext context,
+  }) async {
+    final res = await getSignatureHelp(
+        mainFileUri, positionFromMarker(fileContent), context);
+
+    // TODO(dantup): Update this when there is clarification on how to handle
+    // no valid selected parameter.
+    expect(res.activeParameter, -1);
+    expect(res.activeSignature, equals(0));
+    expect(res.signatures, hasLength(1));
+    final sig = res.signatures.first;
+    expect(sig.label, equals(expectedLabel));
+    expect(sig.parameters, equals(expectedParams));
+
+    // Test the format matches the tests expectation.
+    // For clients that don't support MarkupContent it'll be a plain string,
+    // but otherwise it'll be a MarkupContent of type PlainText or Markdown.
+    final doc = sig.documentation;
+    if (expectedFormat == null) {
+      // Plain string.
+      expect(doc.valueEquals(expectedDoc), isTrue);
+    } else {
+      final expected = MarkupContent(kind: expectedFormat, value: expectedDoc);
+      expect(doc.valueEquals(expected), isTrue);
+    }
+  }
+}
+
 @reflectiveTest
-class SignatureHelpTest extends AbstractLspAnalysisServerTest {
+class SignatureHelpTest extends AbstractLspAnalysisServerTest
+    with SignatureHelpMixin {
   Future<void> test_dartDocMacro() async {
     final content = '''
     /// {@template template_name}
@@ -405,37 +443,40 @@
       ],
     );
   }
+}
 
-  Future<void> testSignature(
-    String fileContent,
-    String expectedLabel,
-    String expectedDoc,
-    List<ParameterInformation> expectedParams, {
-    MarkupKind expectedFormat = MarkupKind.Markdown,
-    SignatureHelpContext context,
-  }) async {
-    final res = await getSignatureHelp(
-        mainFileUri, positionFromMarker(fileContent), context);
+@reflectiveTest
+class SignatureHelpWithNullSafetyTest extends AbstractLspAnalysisServerTest
+    with SignatureHelpMixin {
+  @override
+  AnalysisServerOptions get serverOptions =>
+      AnalysisServerOptions()..enabledExperiments = ['non-nullable'];
 
-    // TODO(dantup): Update this when there is clarification on how to handle
-    // no valid selected parameter.
-    expect(res.activeParameter, -1);
-    expect(res.activeSignature, equals(0));
-    expect(res.signatures, hasLength(1));
-    final sig = res.signatures.first;
-    expect(sig.label, equals(expectedLabel));
-    expect(sig.parameters, equals(expectedParams));
-
-    // Test the format matches the tests expectation.
-    // For clients that don't support MarkupContent it'll be a plain string,
-    // but otherwise it'll be a MarkupContent of type PlainText or Markdown.
-    final doc = sig.documentation;
-    if (expectedFormat == null) {
-      // Plain string.
-      expect(doc.valueEquals(expectedDoc), isTrue);
-    } else {
-      final expected = MarkupContent(kind: expectedFormat, value: expectedDoc);
-      expect(doc.valueEquals(expected), isTrue);
+  Future<void> test_params_requiredNamed() async {
+    // This test requires support for the "required" keyword.
+    final content = '''
+    /// Does foo.
+    foo(String s, {bool b = true, required bool a}) {
+      foo(^);
     }
+    ''';
+
+    final expectedLabel = 'foo(String s, {bool b = true, required bool a})';
+    final expectedDoc = 'Does foo.';
+
+    await initialize(
+        textDocumentCapabilities: withSignatureHelpContentFormat(
+            emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
+    await openFile(mainFileUri, withoutMarkers(content));
+    await testSignature(
+      content,
+      expectedLabel,
+      expectedDoc,
+      [
+        ParameterInformation(label: 'String s'),
+        ParameterInformation(label: 'bool b = true'),
+        ParameterInformation(label: 'required bool a'),
+      ],
+    );
   }
 }
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
index 43f3e4d..f29aafb 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
@@ -16,18 +16,23 @@
 public class ParameterKind {
 
   /**
-   * A named parameter.
+   * An optional named parameter.
    */
-  public static final String NAMED = "NAMED";
+  public static final String OPTIONAL_NAMED = "OPTIONAL_NAMED";
 
   /**
-   * An optional parameter.
+   * An optional positional parameter.
    */
-  public static final String OPTIONAL = "OPTIONAL";
+  public static final String OPTIONAL_POSITIONAL = "OPTIONAL_POSITIONAL";
 
   /**
-   * A required parameter.
+   * A required named parameter.
    */
-  public static final String REQUIRED = "REQUIRED";
+  public static final String REQUIRED_NAMED = "REQUIRED_NAMED";
+
+  /**
+   * A required positional parameter.
+   */
+  public static final String REQUIRED_POSITIONAL = "REQUIRED_POSITIONAL";
 
 }
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 6bcf904..eb8cf23 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.29.1</version>
+  <version>1.30.0</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 76c886f..25f5a64 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.29.1';
+const String PROTOCOL_VERSION = '1.30.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 7e2bab3..6e2aeae 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -4358,27 +4358,34 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
 class ParameterKind implements Enum {
-  /// A named parameter.
-  static const ParameterKind NAMED = ParameterKind._('NAMED');
+  /// An optional named parameter.
+  static const ParameterKind OPTIONAL_NAMED = ParameterKind._('OPTIONAL_NAMED');
 
-  /// An optional parameter.
-  static const ParameterKind OPTIONAL = ParameterKind._('OPTIONAL');
+  /// An optional positional parameter.
+  static const ParameterKind OPTIONAL_POSITIONAL =
+      ParameterKind._('OPTIONAL_POSITIONAL');
 
-  /// A required parameter.
-  static const ParameterKind REQUIRED = ParameterKind._('REQUIRED');
+  /// A required named parameter.
+  static const ParameterKind REQUIRED_NAMED = ParameterKind._('REQUIRED_NAMED');
+
+  /// A required positional parameter.
+  static const ParameterKind REQUIRED_POSITIONAL =
+      ParameterKind._('REQUIRED_POSITIONAL');
 
   /// A list containing all of the enum values that are defined.
   static const List<ParameterKind> VALUES = <ParameterKind>[
-    NAMED,
-    OPTIONAL,
-    REQUIRED
+    OPTIONAL_NAMED,
+    OPTIONAL_POSITIONAL,
+    REQUIRED_NAMED,
+    REQUIRED_POSITIONAL
   ];
 
   @override
@@ -4388,12 +4395,14 @@
 
   factory ParameterKind(String name) {
     switch (name) {
-      case 'NAMED':
-        return NAMED;
-      case 'OPTIONAL':
-        return OPTIONAL;
-      case 'REQUIRED':
-        return REQUIRED;
+      case 'OPTIONAL_NAMED':
+        return OPTIONAL_NAMED;
+      case 'OPTIONAL_POSITIONAL':
+        return OPTIONAL_POSITIONAL;
+      case 'REQUIRED_NAMED':
+        return REQUIRED_NAMED;
+      case 'REQUIRED_POSITIONAL':
+        return REQUIRED_POSITIONAL;
     }
     throw Exception('Illegal enum value: $name');
   }
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 53cebf0..092d411 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -666,12 +666,17 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
-final Matcher isParameterKind =
-    MatchesEnum('ParameterKind', ['NAMED', 'OPTIONAL', 'REQUIRED']);
+final Matcher isParameterKind = MatchesEnum('ParameterKind', [
+  'OPTIONAL_NAMED',
+  'OPTIONAL_POSITIONAL',
+  'REQUIRED_NAMED',
+  'REQUIRED_POSITIONAL'
+]);
 
 /// Position
 ///
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 0144da8..f4acea4 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -6,7 +6,7 @@
 </head>
 <body>
 <h1>Common Types</h1>
-<version>1.2.1</version>
+<version>1.3.0</version>
 <p>
   This document contains a specification of the types that are common between
   the analysis server wire protocol and the analysis server plugin wire
@@ -1253,21 +1253,27 @@
     </p>
     <enum>
       <value>
-        <code>NAMED</code>
+        <code>OPTIONAL_NAMED</code>
         <p>
-          A named parameter.
+          An optional named parameter.
         </p>
       </value>
       <value>
-        <code>OPTIONAL</code>
+        <code>OPTIONAL_POSITIONAL</code>
         <p>
-          An optional parameter.
+          An optional positional parameter.
         </p>
       </value>
       <value>
-        <code>REQUIRED</code>
+        <code>REQUIRED_NAMED</code>
         <p>
-          A required parameter.
+          A required named parameter.
+        </p>
+      </value>
+      <value>
+        <code>REQUIRED_POSITIONAL</code>
+        <p>
+          A required positional parameter.
         </p>
       </value>
     </enum>