mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:37:53 +00:00
[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>
This commit is contained in:
parent
b8909a4878
commit
8b567447dc
|
@ -109,7 +109,7 @@ a:focus, a:hover {
|
|||
<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
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -80,11 +80,13 @@ class DartUnitSignatureComputer {
|
|||
|
||||
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);
|
||||
|
|
|
@ -1073,27 +1073,31 @@ lsp.SignatureHelp toSignatureHelp(List<lsp.MarkupKind> preferredFormats,
|
|||
/// 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(', ') + '}');
|
||||
|
|
|
@ -54,7 +54,7 @@ class AnalysisSignatureTest extends AbstractAnalysisTest {
|
|||
class MyClass {
|
||||
/// MyClass constructor doc
|
||||
MyClass(String name, {int length}) {}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
var a = new MyClass("Danny", /*^*/);
|
||||
}
|
||||
|
@ -63,10 +63,12 @@ main() {
|
|||
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 @@ class MyClass {
|
|||
factory MyClass(String name, {int length}) {
|
||||
return new MyClass._();
|
||||
}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
var a = new MyClass("Danny", /*^*/);
|
||||
}
|
||||
|
@ -88,10 +90,12 @@ main() {
|
|||
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 @@ main() {
|
|||
class MyClass {
|
||||
/// MyClass.foo constructor doc
|
||||
MyClass.foo(String name, {int length}) {}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
var a = new MyClass.foo("Danny", /*^*/);
|
||||
}
|
||||
|
@ -109,10 +113,12 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ main() {
|
|||
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 @@ class MyClass {
|
|||
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 @@ main() {
|
|||
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 @@ class MyClass {
|
|||
MyClass(String name, {int length}) {}
|
||||
/// MyClass static method
|
||||
static void myStaticMethod(String name, {int length}) {}
|
||||
}
|
||||
}
|
||||
main() {
|
||||
MyClass.myStaticMethod("Danny", /*^*/);
|
||||
}
|
||||
|
@ -460,9 +502,11 @@ main() {
|
|||
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')));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1206,12 +1206,17 @@ final Matcher isParameterInfo = LazyMatcher(() => MatchesJsonObject(
|
|||
/// 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
|
||||
///
|
||||
|
|
|
@ -49,6 +49,8 @@ abstract class AbstractLspAnalysisServerTest
|
|||
TestPluginManager pluginManager;
|
||||
LspAnalysisServer server;
|
||||
|
||||
AnalysisServerOptions get serverOptions => AnalysisServerOptions();
|
||||
|
||||
@override
|
||||
Stream<Message> get serverToClient => channel.serverToClient;
|
||||
|
||||
|
@ -121,7 +123,7 @@ abstract class AbstractLspAnalysisServerTest
|
|||
server = LspAnalysisServer(
|
||||
channel,
|
||||
resourceProvider,
|
||||
AnalysisServerOptions(),
|
||||
serverOptions,
|
||||
DartSdkManager(convertPath('/sdk')),
|
||||
CrashReportingAttachmentsBuilder.empty,
|
||||
InstrumentationService.NULL_SERVICE);
|
||||
|
|
|
@ -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 @@ import 'server_abstract.dart';
|
|||
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 @@ class SignatureHelpTest extends 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);
|
||||
@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'),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,18 +16,23 @@ package org.dartlang.analysis.server.protocol;
|
|||
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";
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -4358,27 +4358,34 @@ class ParameterInfo implements HasToJson {
|
|||
/// 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 @@ class ParameterKind implements Enum {
|
|||
|
||||
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');
|
||||
}
|
||||
|
|
|
@ -666,12 +666,17 @@ final Matcher isParameterInfo = LazyMatcher(() => MatchesJsonObject(
|
|||
/// 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
|
||||
///
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue