Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit a2c9cae

Browse files
author
Dart CI
committed
Version 2.10.0-104.0.dev
Merge commit '4237fda6a52cb51b93a8968f3b5b4f2599564233' into 'dev'
2 parents 33b6c95 + 4237fda commit a2c9cae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1828
-310
lines changed

DEPS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ vars = {
4444
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
4545
# hashes. It requires access to the dart-build-access group, which EngProd
4646
# has.
47-
"co19_rev": "c99bc4280fe5ea323c4c937fd073c5e2d17fd975",
47+
"co19_rev": "d21ed3a1dd64107916db68afdce21709df65e85f",
4848
"co19_2_rev": "e48b3090826cf40b8037648f19d211e8eab1b4b6",
4949

5050
# The internal benchmarks to use. See go/dart-benchmarks-internal
@@ -112,7 +112,7 @@ vars = {
112112
"idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
113113
"intl_tag": "0.16.1",
114114
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
115-
"json_rpc_2_rev": "995611cf006c927d51cc53cb28f1aa4356d5414f",
115+
"json_rpc_2_rev": "8f189db8f0c299187a0e8fa959dba7e9b0254be5",
116116
"linter_tag": "0.1.118",
117117
"logging_rev": "9561ba016ae607747ae69b846c0e10958ca58ed4",
118118
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
library _fe_analyzer_shared.parser.parser;
66

7+
import 'package:_fe_analyzer_shared/src/parser/type_info_impl.dart';
8+
79
import '../messages/codes.dart' as codes;
810

911
import '../scanner/scanner.dart' show ErrorToken, Token;
@@ -1130,8 +1132,59 @@ class Parser {
11301132
}
11311133
if (optional('=', next)) {
11321134
equals = next;
1133-
token = computeType(equals, /* required = */ true)
1134-
.ensureTypeOrVoid(equals, this);
1135+
TypeInfo type = computeType(equals, /* required = */ true);
1136+
if (!type.isFunctionType) {
1137+
// Recovery: In certain cases insert missing 'Function' and missing
1138+
// parens.
1139+
Token skippedType = type.skipType(equals);
1140+
if (optional('(', skippedType.next) &&
1141+
skippedType.next.endGroup != null &&
1142+
optional(';', skippedType.next.endGroup.next)) {
1143+
// Turn "<return type>? '(' <whatever> ')';"
1144+
// into "<return type>? Function '(' <whatever> ')';".
1145+
// Assume the type is meant as the return type.
1146+
Token functionToken =
1147+
rewriter.insertSyntheticKeyword(skippedType, Keyword.FUNCTION);
1148+
reportRecoverableError(functionToken,
1149+
codes.templateExpectedButGot.withArguments('Function'));
1150+
type = computeType(equals, /* required = */ true);
1151+
} else if (type is NoType &&
1152+
optional('<', skippedType.next) &&
1153+
skippedType.next.endGroup != null) {
1154+
// Recover these two:
1155+
// "<whatever>;" => "Function<whatever>();"
1156+
// "<whatever>(<whatever>);" => "Function<whatever>(<whatever>);"
1157+
Token endGroup = skippedType.next.endGroup;
1158+
bool recover = false;
1159+
if (optional(';', endGroup.next)) {
1160+
// Missing parenthesis. Insert them.
1161+
// Turn "<whatever>;" in to "<whatever>();"
1162+
// Insert missing 'Function' below.
1163+
reportRecoverableError(endGroup,
1164+
missingParameterMessage(MemberKind.FunctionTypeAlias));
1165+
rewriter.insertParens(endGroup, /*includeIdentifier =*/ false);
1166+
recover = true;
1167+
} else if (optional('(', endGroup.next) &&
1168+
endGroup.next.endGroup != null &&
1169+
optional(';', endGroup.next.endGroup.next)) {
1170+
// "<whatever>(<whatever>);". Insert missing 'Function' below.
1171+
recover = true;
1172+
}
1173+
1174+
if (recover) {
1175+
// Assume the '<' indicates type arguments to the function.
1176+
// Insert 'Function' before them.
1177+
Token functionToken =
1178+
rewriter.insertSyntheticKeyword(equals, Keyword.FUNCTION);
1179+
reportRecoverableError(functionToken,
1180+
codes.templateExpectedButGot.withArguments('Function'));
1181+
type = computeType(equals, /* required = */ true);
1182+
}
1183+
} else {
1184+
// E.g. "typedef j = foo;" -- don't attempt any recovery.
1185+
}
1186+
}
1187+
token = type.ensureTypeOrVoid(equals, this);
11351188
} else {
11361189
// A rewrite caused the = to disappear
11371190
token = parseFormalParametersRequiredOpt(

pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ abstract class TypeInfo {
3030
/// Return true if the receiver has a trailing `?`.
3131
bool get isNullable;
3232

33+
/// Returns true if the type represents a function type, i.e. something like
34+
/// void Function foo(int x);
35+
bool get isFunctionType;
36+
3337
/// Call this function when the token after [token] must be a type (not void).
3438
/// This function will call the appropriate event methods on the [Parser]'s
3539
/// listener to handle the type, inserting a synthetic type reference if

pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class NoType implements TypeInfo {
101101
@override
102102
bool get isNullable => false;
103103

104+
@override
105+
bool get isFunctionType => false;
106+
104107
@override
105108
Token ensureTypeNotVoid(Token token, Parser parser) {
106109
parser.reportRecoverableErrorWithToken(
@@ -142,6 +145,9 @@ class PrefixedType implements TypeInfo {
142145
@override
143146
bool get isNullable => false;
144147

148+
@override
149+
bool get isFunctionType => false;
150+
145151
@override
146152
Token ensureTypeNotVoid(Token token, Parser parser) =>
147153
parseType(token, parser);
@@ -191,6 +197,9 @@ class SimpleNullableTypeWith1Argument extends SimpleTypeWith1Argument {
191197
@override
192198
bool get isNullable => true;
193199

200+
@override
201+
bool get isFunctionType => false;
202+
194203
@override
195204
Token parseTypeRest(Token start, Token token, Parser parser) {
196205
token = token.next;
@@ -222,6 +231,9 @@ class SimpleTypeWith1Argument implements TypeInfo {
222231
@override
223232
bool get isNullable => false;
224233

234+
@override
235+
bool get isFunctionType => false;
236+
225237
@override
226238
Token ensureTypeNotVoid(Token token, Parser parser) =>
227239
parseType(token, parser);
@@ -266,6 +278,9 @@ class SimpleNullableType extends SimpleType {
266278
@override
267279
bool get isNullable => true;
268280

281+
@override
282+
bool get isFunctionType => false;
283+
269284
@override
270285
Token parseTypeRest(Token start, Parser parser) {
271286
Token token = start.next;
@@ -293,6 +308,9 @@ class SimpleType implements TypeInfo {
293308
@override
294309
bool get isNullable => false;
295310

311+
@override
312+
bool get isFunctionType => false;
313+
296314
@override
297315
Token ensureTypeNotVoid(Token token, Parser parser) =>
298316
parseType(token, parser);
@@ -338,6 +356,9 @@ class VoidType implements TypeInfo {
338356
@override
339357
bool get isNullable => false;
340358

359+
@override
360+
bool get isFunctionType => false;
361+
341362
@override
342363
Token ensureTypeNotVoid(Token token, Parser parser) {
343364
// Report an error, then parse `void` as if it were a type name.
@@ -462,6 +483,9 @@ class ComplexTypeInfo implements TypeInfo {
462483
@override
463484
bool get isNullable => beforeQuestionMark != null;
464485

486+
@override
487+
bool get isFunctionType => gftHasReturnType != null;
488+
465489
@override
466490
Token ensureTypeNotVoid(Token token, Parser parser) =>
467491
parseType(token, parser);

pkg/analysis_server/lib/src/computer/computer_signature.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
1717
class DartUnitSignatureComputer {
1818
final DartdocDirectiveInfo _dartdocInfo;
1919
final AstNode _node;
20+
ArgumentList _argumentList;
2021
DartUnitSignatureComputer(
2122
this._dartdocInfo, CompilationUnit _unit, int _offset)
2223
: _node = NodeLocator(_offset).searchWithin(_unit);
2324

25+
/// The [ArgumentList] node located by [compute].
26+
ArgumentList get argumentList => _argumentList;
27+
2428
bool get offsetIsValid => _node != null;
2529

2630
/// Returns the computed signature information, maybe `null`.
@@ -64,6 +68,8 @@ class DartUnitSignatureComputer {
6468
return null;
6569
}
6670

71+
_argumentList = args;
72+
6773
final parameters =
6874
execElement.parameters.map((p) => _convertParam(p)).toList();
6975

@@ -76,7 +82,9 @@ class DartUnitSignatureComputer {
7682
return ParameterInfo(
7783
param.isOptionalPositional
7884
? ParameterKind.OPTIONAL
79-
: param.isPositional ? ParameterKind.REQUIRED : ParameterKind.NAMED,
85+
: param.isPositional
86+
? ParameterKind.REQUIRED
87+
: ParameterKind.NAMED,
8088
param.displayName,
8189
param.type.getDisplayString(withNullability: false),
8290
defaultValue: param.defaultValueCode);

pkg/analysis_server/lib/src/lsp/client_configuration.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ class LspClientConfiguration {
1010
bool get enableSdkFormatter => _settings['enableSdkFormatter'] ?? true;
1111
int get lineLength => _settings['lineLength'];
1212

13+
/// A preview flag for enabling commit characters for completions.
14+
///
15+
/// This is a temporary setting to allow this feature to be tested without
16+
/// defaulting to on for everybody.
17+
bool get previewCommitCharacters =>
18+
_settings['previewCommitCharacters'] ?? false;
19+
1320
void replace(Map<String, dynamic> newConfig) {
1421
_settings
1522
..clear()

pkg/analysis_server/lib/src/lsp/constants.dart

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44

55
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
66

7+
/// The characters that will cause the editor to automatically commit the selected
8+
/// completion item.
9+
///
10+
/// For example, pressing `(` at the location of `^` in the code below would
11+
/// automatically commit the functions name and insert a `(` to avoid either having
12+
/// to press `<enter>` and then `(` or having `()` included in the completion items
13+
/// `insertText` (which is incorrect when passing a function around rather than
14+
/// invoking it).
15+
///
16+
/// myLongFunctionName();
17+
/// print(myLong^)
18+
const dartCompletionCommitCharacters = ['.', '('];
19+
720
/// Set the characters that will cause the editor to automatically
821
/// trigger completion.
922
/// TODO(dantup): There are several characters that we want to conditionally
@@ -26,10 +39,11 @@ import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
2639
/// for the VS Code implementation of this.
2740
const dartCompletionTriggerCharacters = ['.', '=', '(', r'$'];
2841

29-
/// TODO(dantup): Signature help triggering is even more sensitive to
30-
/// bad chars, so we'll need to implement the logic described here:
31-
/// https://github.com/dart-lang/sdk/issues/34241
32-
const dartSignatureHelpTriggerCharacters = <String>[];
42+
/// Characters that refresh signature help only if it's already open on the client.
43+
const dartSignatureHelpRetriggerCharacters = <String>[','];
44+
45+
/// Characters that automatically trigger signature help when typed in the client.
46+
const dartSignatureHelpTriggerCharacters = <String>['('];
3347

3448
/// Characters to trigger formatting when format-on-type is enabled.
3549
const dartTypeFormattingCharacters = ['}', ';'];

pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,35 @@ import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
1010
import 'package:analysis_server/src/lsp/mapping.dart';
1111

1212
class SignatureHelpHandler
13-
extends MessageHandler<TextDocumentPositionParams, SignatureHelp> {
13+
extends MessageHandler<SignatureHelpParams, SignatureHelp> {
1414
SignatureHelpHandler(LspAnalysisServer server) : super(server);
1515
@override
1616
Method get handlesMessage => Method.textDocument_signatureHelp;
1717

1818
@override
19-
LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
20-
TextDocumentPositionParams.jsonHandler;
19+
LspJsonHandler<SignatureHelpParams> get jsonHandler =>
20+
SignatureHelpParams.jsonHandler;
2121

2222
@override
2323
Future<ErrorOr<SignatureHelp>> handle(
24-
TextDocumentPositionParams params, CancellationToken token) async {
24+
SignatureHelpParams params, CancellationToken token) async {
2525
if (!isDartDocument(params.textDocument)) {
2626
return success(null);
2727
}
2828

29+
// If triggered automatically by pressing the trigger character, we will
30+
// only provide results if the character we typed was the one that actually
31+
// starts the argument list. This is to avoid popping open signature help
32+
// whenever the user types a `(` that might not be the start of an argument
33+
// list, as the client does not have any context and will always send the
34+
// request.
35+
final autoTriggered = params.context?.triggerKind ==
36+
SignatureHelpTriggerKind.TriggerCharacter &&
37+
// Retriggers can be ignored (treated as manual invocations) as it's
38+
// fine to always generate results if the signature help is already
39+
// visible on the client (it will just update, it doesn't pop up new UI).
40+
params.context?.isRetrigger == false;
41+
2942
final pos = params.position;
3043
final path = pathOfDoc(params.textDocument);
3144
final unit = await path.mapResult(requireResolvedUnit);
@@ -43,6 +56,17 @@ class SignatureHelpHandler
4356
if (signature == null) {
4457
return success(); // No error, just no valid hover.
4558
}
59+
60+
// Skip results if this was an auto-trigger but not from the start of the
61+
// argument list.
62+
// The ArgumentList's offset is before the paren, but the request offset
63+
// will be after.
64+
if (autoTriggered &&
65+
computer.argumentList != null &&
66+
offset != computer.argumentList.offset + 1) {
67+
return success();
68+
}
69+
4670
final formats = server?.clientCapabilities?.textDocument?.signatureHelp
4771
?.signatureInformation?.documentationFormat;
4872
return success(toSignatureHelp(formats, signature));

pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class ServerCapabilitiesComputer {
106106
clientCapabilities.textDocument?.rename?.prepareSupport ?? false;
107107

108108
final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
109+
final previewCommitCharacters =
110+
_server.clientConfiguration.previewCommitCharacters;
109111

110112
final dynamicRegistrations = ClientDynamicRegistrations(clientCapabilities);
111113

@@ -132,6 +134,9 @@ class ServerCapabilitiesComputer {
132134
? null
133135
: CompletionOptions(
134136
triggerCharacters: dartCompletionTriggerCharacters,
137+
allCommitCharacters: previewCommitCharacters
138+
? dartCompletionCommitCharacters
139+
: null,
135140
resolveProvider: true,
136141
),
137142
hoverProvider: dynamicRegistrations.hover
@@ -141,6 +146,7 @@ class ServerCapabilitiesComputer {
141146
? null
142147
: SignatureHelpOptions(
143148
triggerCharacters: dartSignatureHelpTriggerCharacters,
149+
retriggerCharacters: dartSignatureHelpRetriggerCharacters,
144150
),
145151
definitionProvider: dynamicRegistrations.definition
146152
? null
@@ -242,6 +248,8 @@ class ServerCapabilitiesComputer {
242248
final registrations = <Registration>[];
243249

244250
final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
251+
final previewCommitCharacters =
252+
_server.clientConfiguration.previewCommitCharacters;
245253

246254
/// Helper for creating registrations with IDs.
247255
void register(bool condition, Method method, [ToJsonable options]) {
@@ -279,6 +287,8 @@ class ServerCapabilitiesComputer {
279287
CompletionRegistrationOptions(
280288
documentSelector: allTypes,
281289
triggerCharacters: dartCompletionTriggerCharacters,
290+
allCommitCharacters:
291+
previewCommitCharacters ? dartCompletionCommitCharacters : null,
282292
resolveProvider: true,
283293
),
284294
);
@@ -293,6 +303,7 @@ class ServerCapabilitiesComputer {
293303
SignatureHelpRegistrationOptions(
294304
documentSelector: allTypes,
295305
triggerCharacters: dartSignatureHelpTriggerCharacters,
306+
retriggerCharacters: dartSignatureHelpRetriggerCharacters,
296307
),
297308
);
298309
register(

0 commit comments

Comments
 (0)