Version 2.14.0-18.0.dev
Merge commit 'd217bb11a3a5e42c66a110f41f90bd1f5a95dd4b' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b563cd..c1377e8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,12 @@
- new lint: `require_trailing_commas`.
- new lint: `prefer_null_aware_method_calls`.
+### Language
+
+* Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the
+ sign bit. On the web platform `int.>>>` shifts the low 32 bits interpreted
+ as an unsigned integer, so `a >>> b` gives the same result as
+ `a.toUnsigned(32) >>> b` on the VM.
## 2.13.0
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index fd739c7..046c9c0 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -188,7 +188,7 @@
}
final String file;
- final num offset;
+ final int offset;
Map<String, dynamic> toJson() {
var __result = <String, dynamic>{};
@@ -226,8 +226,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['offset'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['offset'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -295,11 +295,11 @@
final String displayUri;
final String file;
- final num iLength;
- final num libId;
- final num offset;
- final num rLength;
- final num rOffset;
+ final int iLength;
+ final int libId;
+ final int offset;
+ final int rLength;
+ final int rOffset;
Map<String, dynamic> toJson() {
var __result = <String, dynamic>{};
@@ -325,8 +325,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['libId'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['libId'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -359,8 +359,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['rOffset'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['rOffset'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -376,8 +376,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['iLength'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['iLength'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -393,8 +393,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['rLength'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['rLength'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -427,8 +427,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['offset'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['offset'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -484,7 +484,7 @@
return DartDiagnosticServer(port: port);
}
- final num port;
+ final int port;
Map<String, dynamic> toJson() {
var __result = <String, dynamic>{};
@@ -504,8 +504,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['port'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['port'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -1207,7 +1207,7 @@
}
final String file;
- final num offset;
+ final int offset;
final String packageName;
Map<String, dynamic> toJson() {
@@ -1264,8 +1264,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['offset'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['offset'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index c183159..48503cb 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -6320,10 +6320,10 @@
const CompletionItemKind(this._value);
const CompletionItemKind.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
static const Text = CompletionItemKind(1);
@@ -6370,10 +6370,10 @@
const CompletionItemTag(this._value);
const CompletionItemTag.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// Render a completion as obsolete, usually using a strike-out.
@@ -10715,10 +10715,10 @@
const DocumentHighlightKind(this._value);
const DocumentHighlightKind.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// A textual occurrence.
@@ -13758,10 +13758,10 @@
const FileChangeType(this._value);
const FileChangeType.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// The file got created.
@@ -16902,7 +16902,7 @@
const InsertTextFormat._(this._value);
const InsertTextFormat.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
switch (obj) {
@@ -18204,10 +18204,10 @@
const MessageType(this._value);
const MessageType.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// An error message.
@@ -19499,10 +19499,10 @@
///
/// If the character value is greater than the line length it defaults back to
/// the line length.
- final num character;
+ final int character;
/// Line position in a document (zero-based).
- final num line;
+ final int line;
Map<String, dynamic> toJson() {
var __result = <String, dynamic>{};
@@ -19523,8 +19523,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['line'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['line'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -19540,8 +19540,8 @@
reporter.reportError('must not be null');
return false;
}
- if (!(obj['character'] is num)) {
- reporter.reportError('must be of type num');
+ if (!(obj['character'] is int)) {
+ reporter.reportError('must be of type int');
return false;
}
} finally {
@@ -28247,10 +28247,10 @@
const SymbolKind(this._value);
const SymbolKind.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
static const File = SymbolKind(1);
@@ -29926,10 +29926,10 @@
const TextDocumentSaveReason(this._value);
const TextDocumentSaveReason.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// Manually triggered, e.g. by the user pressing save, by starting debugging,
@@ -30183,10 +30183,10 @@
const TextDocumentSyncKind(this._value);
const TextDocumentSyncKind.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// Documents should not be synced at all.
@@ -31206,10 +31206,10 @@
const WatchKind(this._value);
const WatchKind.fromJson(this._value);
- final num _value;
+ final int _value;
static bool canParse(Object obj, LspJsonReporter reporter) {
- return obj is num;
+ return obj is int;
}
/// Interested in create events.
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 5fab9db..796e555 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -73,8 +73,8 @@
/// The object used to manage the SDK's known to this server.
final DartSdkManager sdkManager;
- /// The [SearchEngine] for this server, may be `null` if indexing is disabled.
- SearchEngine? searchEngine;
+ /// The [SearchEngine] for this server.
+ late SearchEngine searchEngine;
late ByteStore byteStore;
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 01eed28..2468770 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -85,9 +85,8 @@
/// [server].
EditDomainHandler(AnalysisServer server) : super(server) {
var search = searchEngine = server.searchEngine;
- refactoringWorkspace = search == null
- ? null
- : RefactoringWorkspace(server.driverMap.values, search);
+ refactoringWorkspace =
+ RefactoringWorkspace(server.driverMap.values, search);
_newRefactoringManager();
}
diff --git a/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart b/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart
index 993ab3a..2d9aa2c 100644
--- a/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/lsp/channel/lsp_byte_stream_channel.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -51,7 +49,7 @@
@override
void listen(void Function(Message message) onMessage,
- {Function onError, void Function() onDone}) {
+ {Function? onError, void Function()? onDone}) {
_input.transform(LspPacketTransformer()).listen(
(String data) => _readMessage(data, onMessage),
onError: onError,
@@ -95,7 +93,7 @@
}
/// Sends a message prefixed with the required LSP headers.
- void _sendLsp(Map<String, Object> json) {
+ void _sendLsp(Map<String, dynamic> json) {
// Don't send any further responses after the communication channel is
// closed.
if (_closeRequested) {
diff --git a/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart b/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart
index 5163e84..8d488b6 100644
--- a/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart
+++ b/pkg/analysis_server/lib/src/lsp/channel/lsp_channel.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 459a0f3..b57dbbe 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -20,7 +18,7 @@
String get commandName => 'Organize Imports';
@override
- Future<ErrorOr<void>> handle(List<dynamic> arguments,
+ Future<ErrorOr<void>> handle(List<dynamic>? arguments,
ProgressReporter reporter, CancellationToken cancellationToken) async {
if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
return ErrorOr.error(ResponseError(
@@ -43,8 +41,8 @@
}
return result.mapResult((result) {
- final code = result.content;
- final unit = result.unit;
+ final code = result.content!;
+ final unit = result.unit!;
if (hasScanParseErrors(result.errors)) {
// It's not uncommon for editors to run this command automatically on-save
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index fccceba..fff5d0c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -26,7 +24,7 @@
String get commandName => 'Perform Refactor';
@override
- Future<ErrorOr<void>> handle(List<dynamic> arguments,
+ Future<ErrorOr<void>> handle(List<dynamic>? arguments,
ProgressReporter reporter, CancellationToken cancellationToken) async {
if (arguments == null ||
arguments.length != 6 ||
@@ -60,26 +58,29 @@
// If the token we were given is not cancellable, replace it with one that
// is for the rest of this request, as a future refactor may need to cancel
// this request.
- if (cancellationToken is! CancelableToken) {
- cancellationToken = CancelableToken();
- }
- _manager.begin(cancellationToken);
+ // The original token should be kept and also checked for cancellation.
+ final cancelableToken = cancellationToken is CancelableToken
+ ? cancellationToken
+ : CancelableToken();
+ _manager.begin(cancelableToken);
try {
reporter.begin('Refactoring…');
final status = await refactoring.checkAllConditions();
if (status.hasError) {
- return error(ServerErrorCodes.RefactorFailed, status.message);
+ return error(ServerErrorCodes.RefactorFailed, status.message!);
}
- if (cancellationToken.isCancellationRequested) {
+ if (cancellationToken.isCancellationRequested ||
+ cancelableToken.isCancellationRequested) {
return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
}
final change = await refactoring.createChange();
- if (cancellationToken.isCancellationRequested) {
+ if (cancellationToken.isCancellationRequested ||
+ cancelableToken.isCancellationRequested) {
return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
}
@@ -94,7 +95,7 @@
} on InconsistentAnalysisException {
return fileModifiedError;
} finally {
- _manager.end(cancellationToken);
+ _manager.end(cancelableToken);
reporter.end();
}
});
@@ -106,7 +107,7 @@
ResolvedUnitResult result,
int offset,
int length,
- Map<String, dynamic> options,
+ Map<String, dynamic>? options,
) async {
switch (kind) {
case RefactoringKind.EXTRACT_METHOD:
@@ -168,7 +169,7 @@
/// Manages a running refactor to help ensure only one refactor runs at a time.
class _RefactorManager {
/// The cancellation token for the current in-progress refactor (or null).
- CancelableToken _currentRefactoringCancellationToken;
+ CancelableToken? _currentRefactoringCancellationToken;
/// Begins a new refactor, cancelling any other in-progress refactors.
void begin(CancelableToken cancelToken) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
index 1f81768..2fbaea1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -26,7 +24,7 @@
String get commandName => 'Send Workspace Edit';
@override
- Future<ErrorOr<void>> handle(List<dynamic> arguments,
+ Future<ErrorOr<void>> handle(List<dynamic>? arguments,
ProgressReporter reporter, CancellationToken cancellationToken) async {
if (arguments == null ||
arguments.length != 1 ||
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
index 5494e3e..df12d35 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/simple_edit_handler.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -39,9 +37,22 @@
return success(null);
}
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
+ final lineInfo = unit.lineInfo;
+ if (lineInfo == null) {
+ return error(ErrorCodes.InternalError,
+ 'Unable to produce edits for $docIdentifier as no LineInfo was found');
+ }
+
final workspaceEdit = toWorkspaceEdit(
- server.clientCapabilities,
- [FileEditInformation(docIdentifier, unit.lineInfo, edits)],
+ clientCapabilities,
+ [FileEditInformation(docIdentifier, lineInfo, edits)],
);
return sendWorkspaceEditToClient(workspaceEdit);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
index 5eec574..7fea763 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -21,7 +19,7 @@
String get commandName => 'Sort Members';
@override
- Future<ErrorOr<void>> handle(List<dynamic> arguments,
+ Future<ErrorOr<void>> handle(List<dynamic>? arguments,
ProgressReporter reporter, CancellationToken cancellationToken) async {
if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
return ErrorOr.error(ResponseError(
@@ -38,20 +36,19 @@
final docIdentifier = server.getVersionedDocumentIdentifier(path);
var driver = server.getAnalysisDriver(path);
- final result0 = await driver?.parseFile2(path);
+ final result = await driver?.parseFile2(path);
if (cancellationToken.isCancellationRequested) {
return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
}
- if (result0 is! ParsedUnitResult) {
+ if (result is! ParsedUnitResult) {
return ErrorOr.error(ResponseError(
code: ServerErrorCodes.FileNotAnalyzed,
message: '$commandName is only available for analyzed files',
));
}
- // TODO(scheglov) inline after migration
- var result = result0 as ParsedUnitResult;
+
final code = result.content;
final unit = result.unit;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
index 8c8d812..af7f163 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
@@ -23,7 +21,13 @@
@override
Future<ErrorOr<DartDiagnosticServer>> handle(
void _, CancellationToken token) async {
- final port = await server.diagnosticServer.getServerPort();
+ final diagnosticServer = server.diagnosticServer;
+ if (diagnosticServer == null) {
+ return error(ServerErrorCodes.FeatureDisabled,
+ 'The diagnostic server is not available');
+ }
+
+ final port = await diagnosticServer.getServerPort();
return success(DartDiagnosticServer(port: port));
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
index ed8824fc..3b5caac 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_reanalyze.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
index 50f0c5d..af2d137 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_super.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -11,9 +9,10 @@
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/search/type_hierarchy.dart';
+import 'package:collection/collection.dart';
class SuperHandler
- extends MessageHandler<TextDocumentPositionParams, Location> {
+ extends MessageHandler<TextDocumentPositionParams, Location?> {
SuperHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => CustomMethods.super_;
@@ -23,7 +22,7 @@
TextDocumentPositionParams.jsonHandler;
@override
- Future<ErrorOr<Location>> handle(
+ Future<ErrorOr<Location?>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
@@ -44,8 +43,8 @@
// finding supers even if the cursor location was inside a method or on its
// return type.
var element = server.getElementOfNode(node);
- while (element == null && node.parent != null) {
- node = node.parent;
+ while (element == null && node?.parent != null) {
+ node = node?.parent;
element = server.getElementOfNode(node);
}
if (element == null) {
@@ -64,21 +63,22 @@
// The class will have a memberElement if we were searching for an element
// otherwise we're looking for a class.
final isMember = items.first.memberElement != null;
- final superItem = items.skip(1).firstWhere(
- (elm) =>
- isMember ? elm.memberElement != null : elm.classElement != null,
- orElse: () => null,
- );
+ final superItem = items.skip(1).firstWhereOrNull(
+ (elm) => isMember ? elm.memberElement != null : true);
- if (superItem == null) {
+ final location = superItem?.memberElement?.location ??
+ superItem?.classElement.location;
+
+ if (location == null) {
return success(null);
}
- final location = isMember
- ? superItem.memberElement.location
- : superItem.classElement.location;
+ final locationLineInfo = server.getLineInfo(location.file);
+ if (locationLineInfo == null) {
+ return success(null);
+ }
- return success(toLocation(location, server.getLineInfo(location.file)));
+ return success(toLocation(location, locationLineInfo));
});
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
index 46c0e60..0707e09 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index 9b7df1e..9a530d3 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -32,13 +30,12 @@
return success(null);
}
- final added = params?.event?.added
- ?.map((wf) => Uri.parse(wf.uri).toFilePath())
- ?.toList();
+ final added =
+ params.event.added.map((wf) => Uri.parse(wf.uri).toFilePath()).toList();
- final removed = params?.event?.removed
- ?.map((wf) => Uri.parse(wf.uri).toFilePath())
- ?.toList();
+ final removed = params.event.removed
+ .map((wf) => Uri.parse(wf.uri).toFilePath())
+ .toList();
server.updateWorkspaceFolders(added, removed);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 219138b..c74cdb2 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
@@ -50,18 +48,21 @@
return success(const []);
}
- final supportsApplyEdit = server.clientCapabilities.applyEdit;
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
- final supportsLiteralCodeActions =
- server.clientCapabilities.literalCodeActions;
-
- final supportedKinds = server.clientCapabilities.codeActionKinds;
-
- final supportedDiagnosticTags = server.clientCapabilities.diagnosticTags;
+ final supportsApplyEdit = clientCapabilities.applyEdit;
+ final supportsLiteralCodeActions = clientCapabilities.literalCodeActions;
+ final supportedKinds = clientCapabilities.codeActionKinds;
+ final supportedDiagnosticTags = clientCapabilities.diagnosticTags;
final unit = await path.mapResult(requireResolvedUnit);
- bool shouldIncludeKind(CodeActionKind kind) {
+ bool shouldIncludeKind(CodeActionKind? kind) {
/// Checks whether the kind matches the [wanted] kind.
///
/// If `wanted` is `refactor.foo` then:
@@ -72,8 +73,9 @@
kind == wanted || kind.toString().startsWith('${wanted.toString()}.');
// If the client wants only a specific set, use only that filter.
- if (params.context?.only != null) {
- return params.context.only.any(isMatch);
+ final only = params.context.only;
+ if (only != null) {
+ return only.any(isMatch);
}
// Otherwise, filter out anything not supported by the client (if they
@@ -108,11 +110,14 @@
}
/// Creates a comparer for [CodeActions] that compares the column distance from [pos].
- Function(CodeAction a, CodeAction b) _codeActionColumnDistanceComparer(
+ int Function(CodeAction a, CodeAction b) _codeActionColumnDistanceComparer(
Position pos) {
- Position posOf(CodeAction action) => action.diagnostics.isNotEmpty
- ? action.diagnostics.first.range.start
- : pos;
+ Position posOf(CodeAction action) {
+ final diagnostics = action.diagnostics;
+ return diagnostics != null && diagnostics.isNotEmpty
+ ? diagnostics.first.range.start
+ : pos;
+ }
return (a, b) => _columnDistance(posOf(a), pos)
.compareTo(_columnDistance(posOf(b), pos));
@@ -174,7 +179,7 @@
List<CodeAction> _dedupeActions(Iterable<CodeAction> actions, Position pos) {
final groups = groupBy(actions, (CodeAction action) => action.title);
return groups.keys.map((title) {
- final actions = groups[title];
+ final actions = groups[title]!;
// If there's only one in the group, just return it.
if (actions.length == 1) {
@@ -213,7 +218,7 @@
}
Future<List<Either2<Command, CodeAction>>> _getAssistActions(
- bool Function(CodeActionKind) shouldIncludeKind,
+ bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiteralCodeActions,
Range range,
int offset,
@@ -248,7 +253,7 @@
}
Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
- bool Function(CodeActionKind) shouldIncludeKind,
+ bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiterals,
bool supportsWorkspaceApplyEdit,
Set<DiagnosticTag> supportedDiagnosticTags,
@@ -274,7 +279,7 @@
}
Future<List<Either2<Command, CodeAction>>> _getFixActions(
- bool Function(CodeActionKind) shouldIncludeKind,
+ bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiteralCodeActions,
Set<DiagnosticTag> supportedDiagnosticTags,
Range range,
@@ -301,10 +306,10 @@
var workspace = DartChangeWorkspace(server.currentSessions);
var context = DartFixContextImpl(
server.instrumentationService, workspace, unit, error, (name) {
- var tracker = server.declarationsTracker;
+ var tracker = server.declarationsTracker!;
return TopLevelDeclarationsProvider(tracker).get(
unit.session.analysisContext,
- unit.path,
+ unit.path!,
name,
);
});
@@ -357,7 +362,7 @@
CodeActionKind actionKind,
String name,
RefactoringKind refactorKind, [
- Map<String, dynamic> options,
+ Map<String, dynamic>? options,
]) {
return _commandOrCodeAction(
supportsLiteralCodeActions,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 4f68075..751fdca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:math' as math;
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
@@ -51,15 +49,22 @@
@override
Future<ErrorOr<List<CompletionItem>>> handle(
CompletionParams params, CancellationToken token) async {
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
final includeSuggestionSets =
- suggestFromUnimportedLibraries && server.clientCapabilities.applyEdit;
+ suggestFromUnimportedLibraries && clientCapabilities.applyEdit;
final triggerCharacter = params.context?.triggerCharacter;
final pos = params.position;
final path = pathOfDoc(params.textDocument);
final unit = await path.mapResult(requireResolvedUnit);
- final lineInfo = unit.map<ErrorOr<LineInfo>>(
+ final lineInfo = await unit.map(
// If we don't have a unit, we can still try to obtain the line info for
// plugin contributors.
(error) => path.mapResult(getLineInfo),
@@ -69,13 +74,13 @@
await lineInfo.mapResult((lineInfo) => toOffset(lineInfo, pos));
return offset.mapResult((offset) async {
- Future<ErrorOr<List<CompletionItem>>> serverResultsFuture;
+ Future<ErrorOr<List<CompletionItem>>>? serverResultsFuture;
final pathContext = server.resourceProvider.pathContext;
final fileExtension = pathContext.extension(path.result);
if (fileExtension == '.dart' && !unit.isError) {
serverResultsFuture = _getServerDartItems(
- server.clientCapabilities,
+ clientCapabilities,
includeSuggestionSets,
unit.result,
offset,
@@ -83,7 +88,7 @@
token,
);
} else if (fileExtension == '.yaml') {
- YamlCompletionGenerator generator;
+ YamlCompletionGenerator? generator;
if (file_paths.isAnalysisOptionsYaml(pathContext, path.result)) {
generator = AnalysisOptionsGenerator(server.resourceProvider);
} else if (file_paths.isFixDataYaml(pathContext, path.result)) {
@@ -95,7 +100,7 @@
if (generator != null) {
serverResultsFuture = _getServerYamlItems(
generator,
- server.clientCapabilities,
+ clientCapabilities,
path.result,
lineInfo.result,
offset,
@@ -107,7 +112,7 @@
serverResultsFuture ??= Future.value(success(const <CompletionItem>[]));
final pluginResultsFuture = _getPluginResults(
- server.clientCapabilities, lineInfo.result, path.result, offset);
+ clientCapabilities, lineInfo.result, path.result, offset);
// Await both server + plugin results together to allow async/IO to
// overlap.
@@ -138,14 +143,15 @@
if (importedLibrary == null) continue;
for (var element in import.namespace.definedNames.values) {
- if (element.librarySource != null) {
- final declaringLibraryUri = element.librarySource.uri;
- final elementName = element.name;
+ final librarySource = element.librarySource;
+ final elementName = element.name;
+ if (librarySource != null && elementName != null) {
+ final declaringLibraryUri = librarySource.uri;
final key =
_createImportedSymbolKey(elementName, declaringLibraryUri);
alreadyImportedSymbols.putIfAbsent(key, () => <String>{});
- alreadyImportedSymbols[key]
+ alreadyImportedSymbols[key]!
.add('${importedLibrary.librarySource.uri}');
}
}
@@ -194,12 +200,12 @@
bool includeSuggestionSets,
ResolvedUnitResult unit,
int offset,
- String triggerCharacter,
+ String? triggerCharacter,
CancellationToken token,
) async {
final performance = CompletionPerformance();
performance.path = unit.path;
- performance.setContentsAndOffset(unit.content, offset);
+ performance.setContentsAndOffset(unit.content!, offset);
server.performanceStats.completion.add(performance);
return await performance.runRequestOperation((perf) async {
@@ -217,9 +223,9 @@
}
}
- Set<ElementKind> includedElementKinds;
- Set<String> includedElementNames;
- List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+ Set<ElementKind>? includedElementKinds;
+ Set<String>? includedElementNames;
+ List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
if (includeSuggestionSets) {
includedElementKinds = <ElementKind>{};
includedElementNames = <String>{};
@@ -288,98 +294,101 @@
// Now compute items in suggestion sets.
var includedSuggestionSets = <IncludedSuggestionSet>[];
- if (includedElementKinds != null && unit != null) {
+ final declarationsTracker = server.declarationsTracker;
+ if (declarationsTracker != null &&
+ includedElementKinds != null &&
+ includedElementNames != null &&
+ includedSuggestionRelevanceTags != null) {
computeIncludedSetList(
- server.declarationsTracker,
+ declarationsTracker,
unit,
includedSuggestionSets,
includedElementNames,
);
+
+ // Build a fast lookup for imported symbols so that we can filter out
+ // duplicates.
+ final alreadyImportedSymbols = _buildLookupOfImportedSymbols(unit);
+
+ includedSuggestionSets.forEach((includedSet) {
+ final library = declarationsTracker.getLibrary(includedSet.id);
+ if (library == null) {
+ return;
+ }
+
+ // Make a fast lookup for tag relevance.
+ final tagBoosts = <String, int>{};
+ includedSuggestionRelevanceTags!
+ .forEach((t) => tagBoosts[t.tag] = t.relevanceBoost);
+
+ // Only specific types of child declarations should be included.
+ // This list matches what's in _protocolAvailableSuggestion in
+ // the DAS implementation.
+ bool shouldIncludeChild(Declaration child) =>
+ child.kind == DeclarationKind.CONSTRUCTOR ||
+ child.kind == DeclarationKind.ENUM_CONSTANT ||
+ (child.kind == DeclarationKind.GETTER && child.isStatic) ||
+ (child.kind == DeclarationKind.FIELD && child.isStatic);
+
+ // Collect declarations and their children.
+ final allDeclarations = library.declarations
+ .followedBy(library.declarations
+ .expand((decl) => decl.children.where(shouldIncludeChild)))
+ .toList();
+
+ final setResults = allDeclarations
+ // Filter to only the kinds we should return.
+ .where((item) => includedElementKinds!
+ .contains(protocolElementKind(item.kind)))
+ .where((item) {
+ // Check existing imports to ensure we don't already import
+ // this element (this exact element from its declaring
+ // library, not just something with the same name). If we do
+ // we'll want to skip it.
+ final declaringUri =
+ item.parent?.locationLibraryUri ?? item.locationLibraryUri!;
+
+ // For enums and named constructors, only the parent enum/class is in
+ // the list of imported symbols so we use the parents name.
+ final nameKey = item.kind == DeclarationKind.ENUM_CONSTANT ||
+ item.kind == DeclarationKind.CONSTRUCTOR
+ ? item.parent!.name
+ : item.name;
+ final key = _createImportedSymbolKey(nameKey, declaringUri);
+ final importingUris = alreadyImportedSymbols[key];
+
+ // Keep it only if there are either:
+ // - no URIs importing it
+ // - the URIs importing it include this one
+ return importingUris == null ||
+ importingUris.contains('${library.uri}');
+ }).map((item) => declarationToCompletionItem(
+ capabilities,
+ unit.path!,
+ offset,
+ includedSet,
+ library,
+ tagBoosts,
+ unit.lineInfo,
+ item,
+ completionRequest.replacementOffset,
+ insertLength,
+ completionRequest.replacementLength,
+ // TODO(dantup): Including commit characters in every completion
+ // increases the payload size. The LSP spec is ambigious
+ // about how this should be handled (and VS Code requires it) but
+ // this should be removed (or made conditional based on a capability)
+ // depending on how the spec is updated.
+ // https://github.com/microsoft/vscode-languageserver-node/issues/673
+ includeCommitCharacters:
+ server.clientConfiguration.previewCommitCharacters,
+ completeFunctionCalls:
+ server.clientConfiguration.completeFunctionCalls,
+ ));
+ results.addAll(setResults);
+ });
}
- // Build a fast lookup for imported symbols so that we can filter out
- // duplicates.
- final alreadyImportedSymbols = _buildLookupOfImportedSymbols(unit);
-
- includedSuggestionSets.forEach((includedSet) {
- final library = server.declarationsTracker.getLibrary(includedSet.id);
- if (library == null) {
- return;
- }
-
- // Make a fast lookup for tag relevance.
- final tagBoosts = <String, int>{};
- includedSuggestionRelevanceTags
- .forEach((t) => tagBoosts[t.tag] = t.relevanceBoost);
-
- // Only specific types of child declarations should be included.
- // This list matches what's in _protocolAvailableSuggestion in
- // the DAS implementation.
- bool shouldIncludeChild(Declaration child) =>
- child.kind == DeclarationKind.CONSTRUCTOR ||
- child.kind == DeclarationKind.ENUM_CONSTANT ||
- (child.kind == DeclarationKind.GETTER && child.isStatic) ||
- (child.kind == DeclarationKind.FIELD && child.isStatic);
-
- // Collect declarations and their children.
- final allDeclarations = library.declarations
- .followedBy(library.declarations
- .expand((decl) => decl.children.where(shouldIncludeChild)))
- .toList();
-
- final setResults = allDeclarations
- // Filter to only the kinds we should return.
- .where((item) =>
- includedElementKinds.contains(protocolElementKind(item.kind)))
- .where((item) {
- // Check existing imports to ensure we don't already import
- // this element (this exact element from its declaring
- // library, not just something with the same name). If we do
- // we'll want to skip it.
- final declaringUri = item.parent != null
- ? item.parent.locationLibraryUri
- : item.locationLibraryUri;
-
- // For enums and named constructors, only the parent enum/class is in
- // the list of imported symbols so we use the parents name.
- final nameKey = item.kind == DeclarationKind.ENUM_CONSTANT ||
- item.kind == DeclarationKind.CONSTRUCTOR
- ? item.parent.name
- : item.name;
- final key = _createImportedSymbolKey(nameKey, declaringUri);
- final importingUris = alreadyImportedSymbols[key];
-
- // Keep it only if there are either:
- // - no URIs importing it
- // - the URIs importing it include this one
- return importingUris == null ||
- importingUris.contains('${library.uri}');
- }).map((item) => declarationToCompletionItem(
- capabilities,
- unit.path,
- offset,
- includedSet,
- library,
- tagBoosts,
- unit.lineInfo,
- item,
- completionRequest.replacementOffset,
- insertLength,
- completionRequest.replacementLength,
- // TODO(dantup): Including commit characters in every completion
- // increases the payload size. The LSP spec is ambigious
- // about how this should be handled (and VS Code requires it) but
- // this should be removed (or made conditional based on a capability)
- // depending on how the spec is updated.
- // https://github.com/microsoft/vscode-languageserver-node/issues/673
- includeCommitCharacters:
- server.clientConfiguration.previewCommitCharacters,
- completeFunctionCalls:
- server.clientConfiguration.completeFunctionCalls,
- ));
- results.addAll(setResults);
- });
-
// Perform fuzzy matching based on the identifier in front of the caret to
// reduce the size of the payload.
final fuzzyPattern = dartCompletionRequest.targetPrefix;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index d5de4c1..1463107 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
@@ -24,7 +22,7 @@
/// Used to abort previous requests in async handlers if another resolve request
/// arrives while the previous is being processed (for clients that don't send
/// cancel events).
- CompletionItem _latestCompletionItem;
+ CompletionItem? _latestCompletionItem;
CompletionResolveHandler(LspAnalysisServer server) : super(server);
@@ -55,6 +53,13 @@
DartCompletionItemResolutionInfo data,
CancellationToken token,
) async {
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
final lineInfo = server.getLineInfo(data.file);
if (lineInfo == null) {
return error(
@@ -68,7 +73,7 @@
// extracting (with support for the different types of responses between
// the servers). Where is an appropriate place to put it?
- var library = server.declarationsTracker.getLibrary(data.libId);
+ var library = server.declarationsTracker?.getLibrary(data.libId);
if (library == null) {
return error(
ErrorCodes.InvalidParams,
@@ -94,16 +99,19 @@
_latestCompletionItem = item;
while (item == _latestCompletionItem && timer.elapsed < timeout) {
try {
- var analysisDriver = server.getAnalysisDriver(data.file);
- var session = analysisDriver.currentSession;
+ final analysisDriver = server.getAnalysisDriver(data.file);
+ final session = analysisDriver?.currentSession;
- if (token.isCancellationRequested) {
+ // We shouldn't not get a driver/session, but if we did perhaps the file
+ // was removed from the analysis set so assume the request is no longer
+ // valid.
+ if (session == null || token.isCancellationRequested) {
return cancelled();
}
analyzer.LibraryElement requestedLibraryElement;
{
- var result = await session.getLibraryByUri2(library.uriStr);
+ final result = await session.getLibraryByUri2(library.uriStr);
if (result is LibraryElementResult) {
requestedLibraryElement = result.element;
} else {
@@ -150,7 +158,7 @@
// If this completion involves editing other files, we'll need to build
// a command that the client will call to apply those edits later.
- Command command;
+ Command? command;
if (otherFilesChanges.isNotEmpty) {
final workspaceEdit =
createPlainWorkspaceEdit(server, otherFilesChanges);
@@ -161,19 +169,19 @@
}
// Documentation is added on during resolve for LSP.
- final formats =
- server.clientCapabilities.completionDocumentationFormats;
+ final formats = clientCapabilities.completionDocumentationFormats;
final supportsInsertReplace =
- server.clientCapabilities.insertReplaceCompletionRanges;
+ clientCapabilities.insertReplaceCompletionRanges;
final dartDoc =
analyzer.getDartDocPlainText(requestedElement.documentationComment);
- final documentation = asStringOrMarkupContent(formats, dartDoc);
+ final documentation =
+ dartDoc != null ? asStringOrMarkupContent(formats, dartDoc) : null;
return success(CompletionItem(
label: item.label,
kind: item.kind,
tags: item.tags,
- detail: data.displayUri != null && thisFilesChanges.isNotEmpty
+ detail: thisFilesChanges.isNotEmpty
? "Auto import from '${data.displayUri}'\n\n${item.detail ?? ''}"
.trim()
: item.detail,
@@ -234,13 +242,14 @@
return cancelled();
}
+ final description = packageDetails?.description;
return success(CompletionItem(
label: item.label,
kind: item.kind,
tags: item.tags,
detail: item.detail,
- documentation: packageDetails?.description != null
- ? Either2<String, MarkupContent>.t1(packageDetails.description)
+ documentation: description != null
+ ? Either2<String, MarkupContent>.t1(description)
: null,
deprecated: item.deprecated,
preselect: item.preselect,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index 5b52c33..a9bc050 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol_generated.dart'
@@ -18,6 +16,7 @@
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
+import 'package:collection/collection.dart';
class DefinitionHandler extends MessageHandler<TextDocumentPositionParams,
Either2<List<Location>, List<LocationLink>>>
@@ -53,9 +52,10 @@
NavigationCollectorImpl(collectCodeLocations: supportsLocationLink);
final result = await server.getResolvedUnit(path);
- if (result?.state == ResultState.VALID) {
+ final unit = result?.unit;
+ if (result?.state == ResultState.VALID && unit != null) {
computeDartNavigation(
- server.resourceProvider, collector, result.unit, offset, 0);
+ server.resourceProvider, collector, unit, offset, 0);
collector.createRegions();
}
@@ -66,8 +66,14 @@
@override
Future<ErrorOr<Either2<List<Location>, List<LocationLink>>>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
- final supportsLocationLink =
- server.clientCapabilities.definitionLocationLink;
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
+ final supportsLocationLink = clientCapabilities.definitionLocationLink;
final pos = params.position;
final path = pathOfDoc(params.textDocument);
@@ -94,20 +100,27 @@
final mergedResults = merger.mergeNavigation(allResults);
final mergedTargets = mergedResults?.targets ?? [];
+ if (mergedResults == null) {
+ return success(
+ Either2<List<Location>, List<LocationLink>>.t1(const []),
+ );
+ }
+
// Convert and filter the results using the correct type of Location class
// depending on the client capabilities.
if (supportsLocationLink) {
final convertedResults = convert(
mergedTargets,
- (target) => _toLocationLink(mergedResults, lineInfo, target),
- ).toList();
+ (NavigationTarget target) =>
+ _toLocationLink(mergedResults, lineInfo, target),
+ ).whereNotNull().toList();
final results = _filterResults(
convertedResults,
params.textDocument.uri,
pos.line,
- (element) => element.targetUri,
- (element) => element.targetSelectionRange,
+ (LocationLink element) => element.targetUri,
+ (LocationLink element) => element.targetSelectionRange,
);
return success(
@@ -116,15 +129,15 @@
} else {
final convertedResults = convert(
mergedTargets,
- (target) => _toLocation(mergedResults, target),
- ).toList();
+ (NavigationTarget target) => _toLocation(mergedResults, target),
+ ).whereNotNull().toList();
final results = _filterResults(
convertedResults,
params.textDocument.uri,
pos.line,
- (element) => element.uri,
- (element) => element.range,
+ (Location element) => element.uri,
+ (Location element) => element.range,
);
return success(
@@ -159,19 +172,24 @@
return otherResults.isNotEmpty ? otherResults : results;
}
- Location _toLocation(
+ Location? _toLocation(
AnalysisNavigationParams mergedResults, NavigationTarget target) {
final targetFilePath = mergedResults.files[target.fileIndex];
final targetLineInfo = server.getLineInfo(targetFilePath);
- return navigationTargetToLocation(targetFilePath, target, targetLineInfo);
+ return targetLineInfo != null
+ ? navigationTargetToLocation(targetFilePath, target, targetLineInfo)
+ : null;
}
- LocationLink _toLocationLink(AnalysisNavigationParams mergedResults,
+ LocationLink? _toLocationLink(AnalysisNavigationParams mergedResults,
LineInfo sourceLineInfo, NavigationTarget target) {
final region = mergedResults.regions.first;
final targetFilePath = mergedResults.files[target.fileIndex];
final targetLineInfo = server.getLineInfo(targetFilePath);
- return navigationTargetToLocationLink(
- region, sourceLineInfo, targetFilePath, target, targetLineInfo);
+
+ return targetLineInfo != null
+ ? navigationTargetToLocationLink(
+ region, sourceLineInfo, targetFilePath, target, targetLineInfo)
+ : null;
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index 9573acc..ff213a4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/domains/analysis/occurrences.dart';
@@ -13,7 +11,7 @@
import 'package:analysis_server/src/lsp/mapping.dart';
class DocumentHighlightsHandler extends MessageHandler<
- TextDocumentPositionParams, List<DocumentHighlight>> {
+ TextDocumentPositionParams, List<DocumentHighlight>?> {
DocumentHighlightsHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_documentHighlight;
@@ -23,7 +21,7 @@
TextDocumentPositionParams.jsonHandler;
@override
- Future<ErrorOr<List<DocumentHighlight>>> handle(
+ Future<ErrorOr<List<DocumentHighlight>?>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
@@ -36,7 +34,7 @@
return offset.mapResult((requestedOffset) {
final collector = OccurrencesCollectorImpl();
- addDartOccurrences(collector, unit.result.unit);
+ addDartOccurrences(collector, unit.result.unit!);
// Find an occurrence that has an instance that spans the position.
for (final occurrence in collector.allOccurrences) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
index b4b6f14..0c1141d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
@@ -16,7 +14,7 @@
import 'package:analyzer/source/line_info.dart';
class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams,
- Either2<List<DocumentSymbol>, List<SymbolInformation>>> {
+ Either2<List<DocumentSymbol>, List<SymbolInformation>>?> {
DocumentSymbolHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_documentSymbol;
@@ -26,9 +24,10 @@
DocumentSymbolParams.jsonHandler;
@override
- Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>>
+ Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>?>>
handle(DocumentSymbolParams params, CancellationToken token) async {
- if (!isDartDocument(params.textDocument)) {
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null || !isDartDocument(params.textDocument)) {
return success(
Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2([]),
);
@@ -37,7 +36,7 @@
final path = pathOfDoc(params.textDocument);
final unit = await path.mapResult(requireResolvedUnit);
return unit.mapResult(
- (unit) => _getSymbols(server.clientCapabilities, path.result, unit));
+ (unit) => _getSymbols(clientCapabilities, path.result, unit));
}
DocumentSymbol _asDocumentSymbol(
@@ -45,41 +44,49 @@
LineInfo lineInfo,
Outline outline,
) {
+ final codeRange = toRange(lineInfo, outline.codeOffset, outline.codeLength);
+ final nameLocation = outline.element.location;
+ final nameRange = nameLocation != null
+ ? toRange(lineInfo, nameLocation.offset, nameLocation.length)
+ : null;
return DocumentSymbol(
name: toElementName(outline.element),
detail: outline.element.parameters,
kind: elementKindToSymbolKind(supportedKinds, outline.element.kind),
deprecated: outline.element.isDeprecated,
- range: toRange(lineInfo, outline.codeOffset, outline.codeLength),
- selectionRange: toRange(lineInfo, outline.element.location.offset,
- outline.element.location.length),
+ range: codeRange,
+ selectionRange: nameRange ?? codeRange,
children: outline.children
?.map((child) => _asDocumentSymbol(supportedKinds, lineInfo, child))
- ?.toList(),
+ .toList(),
);
}
- SymbolInformation _asSymbolInformation(
- String containerName,
+ SymbolInformation? _asSymbolInformation(
+ String? containerName,
Set<SymbolKind> supportedKinds,
String documentUri,
LineInfo lineInfo,
Outline outline,
) {
+ final location = outline.element.location;
+ if (location == null) {
+ return null;
+ }
+
return SymbolInformation(
name: toElementName(outline.element),
kind: elementKindToSymbolKind(supportedKinds, outline.element.kind),
deprecated: outline.element.isDeprecated,
location: Location(
uri: documentUri,
- range: toRange(lineInfo, outline.element.location.offset,
- outline.element.location.length),
+ range: toRange(lineInfo, location.offset, location.length),
),
containerName: containerName,
);
}
- ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>> _getSymbols(
+ ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>?> _getSymbols(
LspClientCapabilities capabilities,
String path,
ResolvedUnitResult unit,
@@ -90,12 +97,16 @@
if (capabilities.hierarchicalSymbols) {
// Return a tree of DocumentSymbol only if the client shows explicit support
// for it.
+ final children = outline.children;
+ if (children == null) {
+ return success(null);
+ }
return success(
Either2<List<DocumentSymbol>, List<SymbolInformation>>.t1(
- outline?.children
- ?.map((child) => _asDocumentSymbol(
+ children
+ .map((child) => _asDocumentSymbol(
capabilities.documentSymbolKinds, unit.lineInfo, child))
- ?.toList(),
+ .toList(),
),
);
} else {
@@ -105,20 +116,23 @@
// Adds a symbol and it's children recursively, supplying the parent
// name as required by SymbolInformation.
- void addSymbol(Outline outline, {String parentName}) {
- allSymbols.add(_asSymbolInformation(
+ void addSymbol(Outline outline, {String? parentName}) {
+ final symbol = _asSymbolInformation(
parentName,
capabilities.documentSymbolKinds,
documentUri,
unit.lineInfo,
outline,
- ));
+ );
+ if (symbol != null) {
+ allSymbols.add(symbol);
+ }
outline.children?.forEach(
(c) => addSymbol(c, parentName: outline.element.name),
);
}
- outline?.children?.forEach(addSymbol);
+ outline.children?.forEach(addSymbol);
return success(
Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2(allSymbols),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index 40e0e03..533798f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -18,7 +16,7 @@
/// Handles workspace/executeCommand messages by delegating to a specific handler
/// based on the command.
class ExecuteCommandHandler
- extends MessageHandler<ExecuteCommandParams, Object> {
+ extends MessageHandler<ExecuteCommandParams, Object?> {
final Map<String, CommandHandler> commandHandlers;
ExecuteCommandHandler(LspAnalysisServer server)
: commandHandlers = {
@@ -37,7 +35,7 @@
ExecuteCommandParams.jsonHandler;
@override
- Future<ErrorOr<Object>> handle(
+ Future<ErrorOr<Object?>> handle(
ExecuteCommandParams params, CancellationToken cancellationToken) async {
final handler = commandHandlers[params.command];
if (handler == null) {
@@ -45,9 +43,10 @@
'${params.command} is not a valid command identifier', null);
}
- final progress = params.workDoneToken != null
- ? ProgressReporter.clientProvided(server, params.workDoneToken)
- : server.clientCapabilities.workDoneProgress
+ final workDoneToken = params.workDoneToken;
+ final progress = workDoneToken != null
+ ? ProgressReporter.clientProvided(server, workDoneToken)
+ : server.clientCapabilities?.workDoneProgress ?? false
? ProgressReporter.serverCreated(server)
: ProgressReporter.noop;
return handler.handle(params.arguments, progress, cancellationToken);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
index 89a4776..a5850a5 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
index cda2b35..d67f740 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/computer/computer_folding.dart';
@@ -31,11 +29,11 @@
return path.mapResult((path) async {
final partialResults = <List<FoldingRegion>>[];
- LineInfo lineInfo;
+ LineInfo? lineInfo;
final unit = server.getParsedUnit(path);
if (unit?.state == ResultState.VALID) {
- lineInfo = unit.lineInfo;
+ lineInfo = unit!.lineInfo;
final regions = DartUnitFoldingComputer(lineInfo, unit.unit).compute();
partialResults.insert(0, regions);
@@ -59,7 +57,7 @@
notificationManager.merger.mergeFoldingRegions(partialResults);
return success(
- regions.map((region) => toFoldingRange(lineInfo, region)).toList(),
+ regions.map((region) => toFoldingRange(lineInfo!, region)).toList(),
);
});
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 2c3b193..1ed3a71 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -14,7 +12,7 @@
import 'package:analyzer/dart/analysis/results.dart';
class FormatOnTypeHandler
- extends MessageHandler<DocumentOnTypeFormattingParams, List<TextEdit>> {
+ extends MessageHandler<DocumentOnTypeFormattingParams, List<TextEdit>?> {
FormatOnTypeHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_onTypeFormatting;
@@ -23,14 +21,14 @@
LspJsonHandler<DocumentOnTypeFormattingParams> get jsonHandler =>
DocumentOnTypeFormattingParams.jsonHandler;
- ErrorOr<List<TextEdit>> formatFile(String path) {
+ ErrorOr<List<TextEdit>?> formatFile(String path) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
}
final result = server.getParsedUnit(path);
- if (result.state != ResultState.VALID || result.errors.isNotEmpty) {
+ if (result?.state != ResultState.VALID || result!.errors.isNotEmpty) {
return success(null);
}
@@ -39,7 +37,7 @@
}
@override
- Future<ErrorOr<List<TextEdit>>> handle(
+ Future<ErrorOr<List<TextEdit>?>> handle(
DocumentOnTypeFormattingParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
index 934cd2a..d6f7247 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -14,7 +12,7 @@
import 'package:analyzer/dart/analysis/results.dart';
class FormatRangeHandler
- extends MessageHandler<DocumentRangeFormattingParams, List<TextEdit>> {
+ extends MessageHandler<DocumentRangeFormattingParams, List<TextEdit>?> {
FormatRangeHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_rangeFormatting;
@@ -23,14 +21,14 @@
LspJsonHandler<DocumentRangeFormattingParams> get jsonHandler =>
DocumentRangeFormattingParams.jsonHandler;
- ErrorOr<List<TextEdit>> formatRange(String path, Range range) {
+ ErrorOr<List<TextEdit>?> formatRange(String path, Range range) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
}
final result = server.getParsedUnit(path);
- if (result.state != ResultState.VALID || result.errors.isNotEmpty) {
+ if (result?.state != ResultState.VALID || result!.errors.isNotEmpty) {
return success(null);
}
@@ -40,7 +38,7 @@
}
@override
- Future<ErrorOr<List<TextEdit>>> handle(
+ Future<ErrorOr<List<TextEdit>?>> handle(
DocumentRangeFormattingParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index e2cf8e1..75b7a41 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -14,7 +12,7 @@
import 'package:analyzer/dart/analysis/results.dart';
class FormattingHandler
- extends MessageHandler<DocumentFormattingParams, List<TextEdit>> {
+ extends MessageHandler<DocumentFormattingParams, List<TextEdit>?> {
FormattingHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_formatting;
@@ -23,14 +21,14 @@
LspJsonHandler<DocumentFormattingParams> get jsonHandler =>
DocumentFormattingParams.jsonHandler;
- ErrorOr<List<TextEdit>> formatFile(String path) {
+ ErrorOr<List<TextEdit>?> formatFile(String path) {
final file = server.resourceProvider.getFile(path);
if (!file.exists) {
return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
}
final result = server.getParsedUnit(path);
- if (result.state != ResultState.VALID || result.errors.isNotEmpty) {
+ if (result?.state != ResultState.VALID || result!.errors.isNotEmpty) {
return success(null);
}
@@ -39,7 +37,7 @@
}
@override
- Future<ErrorOr<List<TextEdit>>> handle(
+ Future<ErrorOr<List<TextEdit>?>> handle(
DocumentFormattingParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index 8c82497..1bef994 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -15,7 +13,7 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/line_info.dart';
-class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover> {
+class HoverHandler extends MessageHandler<TextDocumentPositionParams, Hover?> {
HoverHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_hover;
@@ -25,7 +23,7 @@
TextDocumentPositionParams.jsonHandler;
@override
- Future<ErrorOr<Hover>> handle(
+ Future<ErrorOr<Hover?>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
@@ -38,7 +36,7 @@
return offset.mapResult((offset) => _getHover(unit.result, offset));
}
- Hover toHover(LineInfo lineInfo, HoverInformation hover) {
+ Hover? toHover(LineInfo lineInfo, HoverInformation? hover) {
if (hover == null) {
return null;
}
@@ -55,16 +53,16 @@
// Description.
if (hover.elementDescription != null) {
content.writeln('```dart');
- if (hover.isDeprecated) {
+ if (hover.isDeprecated ?? false) {
content.write('(deprecated) ');
}
content..writeln(hover.elementDescription)..writeln('```');
}
// Source library.
- if (hover.containingLibraryName != null &&
- hover.containingLibraryName.isNotEmpty) {
- content..writeln('*${hover.containingLibraryName}*')..writeln();
+ final containingLibraryName = hover.containingLibraryName;
+ if (containingLibraryName != null && containingLibraryName.isNotEmpty) {
+ content..writeln('*$containingLibraryName*')..writeln();
}
// Doc comments.
@@ -75,7 +73,7 @@
content.writeln(cleanDartdoc(hover.dartdoc));
}
- final formats = server.clientCapabilities.hoverContentFormats;
+ final formats = server.clientCapabilities?.hoverContentFormats;
return Hover(
contents:
asStringOrMarkupContent(formats, content.toString().trimRight()),
@@ -83,9 +81,14 @@
);
}
- ErrorOr<Hover> _getHover(ResolvedUnitResult unit, int offset) {
+ ErrorOr<Hover?> _getHover(ResolvedUnitResult unit, int offset) {
+ final compilationUnit = unit.unit;
+ if (compilationUnit == null) {
+ return success(null);
+ }
+
final hover = DartUnitHoverComputer(
- server.getDartdocDirectiveInfoFor(unit), unit.unit, offset)
+ server.getDartdocDirectiveInfoFor(unit), compilationUnit, offset)
.compute();
return success(toHover(unit.lineInfo, hover));
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
index 822398c..ca6c915 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -11,6 +9,7 @@
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/search/type_hierarchy.dart';
+import 'package:collection/collection.dart';
class ImplementationHandler
extends MessageHandler<TextDocumentPositionParams, List<Location>> {
@@ -38,22 +37,27 @@
}
Future<ErrorOr<List<Location>>> _getImplementations(
- String file, int offset, CancelableToken token) async {
+ String file, int offset, CancellationToken token) async {
final element = await server.getElementAtOffset(file, offset);
+ if (element == null) {
+ return success([]);
+ }
+
final computer = TypeHierarchyComputer(server.searchEngine, element);
+
if (token.isCancellationRequested) {
return cancelled();
}
- final items = await computer.compute();
+ final items = await computer.compute();
if (items == null || items.isEmpty) {
return success([]);
}
Iterable<TypeHierarchyItem> getDescendants(TypeHierarchyItem item) => item
.subclasses
- ?.map((i) => items[i])
- ?.followedBy(item.subclasses.expand((i) => getDescendants(items[i])));
+ .map((i) => items[i])
+ .followedBy(item.subclasses.expand((i) => getDescendants(items[i])));
// [TypeHierarchyComputer] returns the whole tree, but we specifically only
// want implementations (sub-classes). Find the referenced element and then
@@ -61,8 +65,9 @@
var currentItem = items.firstWhere(
(item) {
final location =
- item.memberElement?.location ?? item.classElement?.location;
- return location.offset <= offset &&
+ item.memberElement?.location ?? item.classElement.location;
+ return location != null &&
+ location.offset <= offset &&
location.offset + location.length >= offset;
},
// If we didn't find an item spanning our offset, we must've been at a
@@ -70,23 +75,32 @@
orElse: () => items.first,
);
- final isClass = currentItem.memberElement == null;
+ final isMember = currentItem.memberElement != null;
+ final locations = getDescendants(currentItem)
+ // Filter based on type, so when searching for members we don't include
+ // any intermediate classes that don't have implementations for the
+ // method.
+ .where((item) => isMember ? item.memberElement != null : true)
+ .map((item) {
+ final elementLocation =
+ item.memberElement?.location ?? item.classElement.location;
+ if (elementLocation == null) {
+ return null;
+ }
- final locations = getDescendants(currentItem).where((item) {
- // Filter based on type, so when searching for members we don't include
- // any intermediate classes that don't have implementations for the
- // method.
- return isClass ? item.classElement != null : item.memberElement != null;
- }).map((item) {
- final elementLocation =
- item.memberElement?.location ?? item.classElement?.location;
- final lineInfo = server.getLineInfo(elementLocation.file);
- return Location(
- uri: Uri.file(elementLocation.file).toString(),
- range:
- toRange(lineInfo, elementLocation.offset, elementLocation.length),
- );
- }).toList();
+ final lineInfo = server.getLineInfo(elementLocation.file);
+ if (lineInfo == null) {
+ return null;
+ }
+
+ return Location(
+ uri: Uri.file(elementLocation.file).toString(),
+ range: toRange(
+ lineInfo, elementLocation.offset, elementLocation.length),
+ );
+ })
+ .whereNotNull()
+ .toList();
return success(locations);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index 091f1e0..146b2c1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -32,12 +30,15 @@
);
final openWorkspacePaths = <String>[];
+ final workspaceFolders = params.workspaceFolders;
+ final rootUri = params.rootUri;
+ final rootPath = params.rootPath;
// The onlyAnalyzeProjectsWithOpenFiles flag allows opening huge folders
// without setting them as analysis roots. Instead, analysis roots will be
// based only on the open files.
if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
- if (params.workspaceFolders != null) {
- params.workspaceFolders.forEach((wf) {
+ if (workspaceFolders != null) {
+ workspaceFolders.forEach((wf) {
final uri = Uri.parse(wf.uri);
// Only file URIs are supported, but there's no way to signal this to
// the LSP client (and certainly not before initialization).
@@ -46,13 +47,13 @@
}
});
}
- if (params.rootUri != null) {
- final uri = Uri.parse(params.rootUri);
+ if (rootUri != null) {
+ final uri = Uri.parse(rootUri);
if (uri.isScheme('file')) {
openWorkspacePaths.add(uri.toFilePath());
}
- } else if (params.rootPath != null) {
- openWorkspacePaths.add(params.rootPath);
+ } else if (rootPath != null) {
+ openWorkspacePaths.add(rootPath);
}
}
@@ -61,8 +62,9 @@
openWorkspacePaths,
);
- server.capabilities = server.capabilitiesComputer
- .computeServerCapabilities(server.clientCapabilities);
+ final capabilities = server.capabilitiesComputer
+ .computeServerCapabilities(server.clientCapabilities!);
+ server.capabilities = capabilities;
var sdkVersion = Platform.version;
if (sdkVersion.contains(' ')) {
@@ -70,7 +72,7 @@
}
return success(InitializeResult(
- capabilities: server.capabilities,
+ capabilities: capabilities,
serverInfo: InitializeResultServerInfo(
name: 'Dart SDK LSP Analysis Server',
version: sdkVersion,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index 114216b..d842bbb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index bfd1405..b302227 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -17,9 +15,10 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
+import 'package:collection/collection.dart';
class ReferencesHandler
- extends MessageHandler<ReferenceParams, List<Location>> {
+ extends MessageHandler<ReferenceParams, List<Location>?> {
ReferencesHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_references;
@@ -29,7 +28,7 @@
ReferenceParams.jsonHandler;
@override
- Future<ErrorOr<List<Location>>> handle(
+ Future<ErrorOr<List<Location>?>> handle(
ReferenceParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
@@ -50,21 +49,23 @@
return convert(collector.targets, (NavigationTarget target) {
final targetFilePath = collector.files[target.fileIndex];
final lineInfo = server.getLineInfo(targetFilePath);
- return navigationTargetToLocation(targetFilePath, target, lineInfo);
- }).toList();
+ return lineInfo != null
+ ? navigationTargetToLocation(targetFilePath, target, lineInfo)
+ : null;
+ }).whereNotNull().toList();
}
- Future<ErrorOr<List<Location>>> _getRefererences(String path, int offset,
+ Future<ErrorOr<List<Location>?>> _getRefererences(String path, int offset,
ReferenceParams params, ResolvedUnitResult unit) async {
var element = await server.getElementAtOffset(path, offset);
if (element is ImportElement) {
- element = (element as ImportElement).prefix;
+ element = element.prefix;
}
if (element is FieldFormalParameterElement) {
- element = (element as FieldFormalParameterElement).field;
+ element = element.field;
}
if (element is PropertyAccessorElement) {
- element = (element as PropertyAccessorElement).variable;
+ element = element.variable;
}
if (element == null) {
return success(null);
@@ -73,16 +74,18 @@
final computer = ElementReferencesComputer(server.searchEngine);
final results = await computer.compute(element, false);
- Location toLocation(SearchResult result) {
+ Location? toLocation(SearchResult result) {
final lineInfo = server.getLineInfo(result.location.file);
return searchResultToLocation(result, lineInfo);
}
- final referenceResults = convert(results, toLocation).toList();
+ final referenceResults =
+ convert(results, toLocation).whereNotNull().toList();
- if (params.context?.includeDeclaration == true) {
+ final compilationUnit = unit.unit;
+ if (compilationUnit != null && params.context.includeDeclaration == true) {
// Also include the definition for the symbol at this location.
- referenceResults.addAll(_getDeclarations(unit.unit, offset));
+ referenceResults.addAll(_getDeclarations(compilationUnit, offset));
}
return success(referenceResults);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
index e841a61..dbcefeb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -11,7 +9,7 @@
/// A [MessageHandler] that rejects specific tpyes of messages with a given
/// error code/message.
-class RejectMessageHandler extends MessageHandler<Object, void> {
+class RejectMessageHandler extends MessageHandler<Object?, void> {
@override
final Method handlesMessage;
final ErrorCodes errorCode;
@@ -21,7 +19,7 @@
: super(server);
@override
- LspJsonHandler<void> get jsonHandler => NullJsonHandler;
+ LspJsonHandler<Object?> get jsonHandler => NullJsonHandler;
@override
ErrorOr<void> handle(void _, CancellationToken token) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index caa7c78..6773974 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/constants.dart';
@@ -13,7 +11,7 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
class PrepareRenameHandler
- extends MessageHandler<TextDocumentPositionParams, RangeAndPlaceholder> {
+ extends MessageHandler<TextDocumentPositionParams, RangeAndPlaceholder?> {
PrepareRenameHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_prepareRename;
@@ -23,7 +21,7 @@
TextDocumentPositionParams.jsonHandler;
@override
- Future<ErrorOr<RangeAndPlaceholder>> handle(
+ Future<ErrorOr<RangeAndPlaceholder?>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
@@ -43,6 +41,10 @@
final refactorDetails =
RenameRefactoring.getElementToRename(node, element);
+ if (refactorDetails == null) {
+ return success(null);
+ }
+
final refactoring = RenameRefactoring.create(
server.refactoringWorkspace, unit.result, refactorDetails.element);
if (refactoring == null) {
@@ -53,7 +55,7 @@
final initStatus = await refactoring.checkInitialConditions();
if (initStatus.hasFatalError) {
return error(
- ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
+ ServerErrorCodes.RenameNotValid, initStatus.problem!.message, null);
}
return success(RangeAndPlaceholder(
@@ -72,7 +74,7 @@
}
}
-class RenameHandler extends MessageHandler<RenameParams, WorkspaceEdit> {
+class RenameHandler extends MessageHandler<RenameParams, WorkspaceEdit?> {
RenameHandler(LspAnalysisServer server) : super(server);
@override
@@ -82,7 +84,7 @@
LspJsonHandler<RenameParams> get jsonHandler => RenameParams.jsonHandler;
@override
- Future<ErrorOr<WorkspaceEdit>> handle(
+ Future<ErrorOr<WorkspaceEdit?>> handle(
RenameParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
@@ -116,6 +118,10 @@
final refactorDetails =
RenameRefactoring.getElementToRename(node, element);
+ if (refactorDetails == null) {
+ return success(null);
+ }
+
final refactoring = RenameRefactoring.create(
server.refactoringWorkspace, unit.result, refactorDetails.element);
if (refactoring == null) {
@@ -135,7 +141,7 @@
}
if (initStatus.hasFatalError) {
return error(
- ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
+ ServerErrorCodes.RenameNotValid, initStatus.problem!.message, null);
}
// Check the name is valid.
@@ -143,7 +149,7 @@
final optionsStatus = refactoring.checkNewName();
if (optionsStatus.hasError) {
return error(ServerErrorCodes.RenameNotValid,
- optionsStatus.problem.message, null);
+ optionsStatus.problem!.message, null);
}
// Final validation.
@@ -152,13 +158,13 @@
return cancelled();
}
if (finalStatus.hasFatalError) {
- return error(
- ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
+ return error(ServerErrorCodes.RenameNotValid,
+ finalStatus.problem!.message, null);
} else if (finalStatus.hasError || finalStatus.hasWarning) {
// Ask the user whether to proceed with the rename.
final userChoice = await server.showUserPrompt(
MessageType.Warning,
- finalStatus.message,
+ finalStatus.message!,
[
MessageActionItem(title: UserPromptActions.renameAnyway),
MessageActionItem(title: UserPromptActions.cancel),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart
index 61e411e..7552f3f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_semantic_tokens.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -18,7 +16,7 @@
import 'package:analyzer_plugin/protocol/protocol_common.dart';
abstract class AbstractSemanticTokensHandler<T>
- extends MessageHandler<T, SemanticTokens>
+ extends MessageHandler<T, SemanticTokens?>
with LspPluginRequestHandlerMixin {
AbstractSemanticTokensHandler(LspAnalysisServer server) : super(server);
@@ -28,17 +26,18 @@
}
Future<List<SemanticTokenInfo>> getServerResult(
- String path, SourceRange range) async {
+ String path, SourceRange? range) async {
final result = await server.getResolvedUnit(path);
- if (result?.state == ResultState.VALID) {
- final computer = DartUnitHighlightsComputer(result.unit, range: range);
+ final unit = result?.unit;
+ if (result?.state == ResultState.VALID && unit != null) {
+ final computer = DartUnitHighlightsComputer(unit, range: range);
return computer.computeSemanticTokens();
}
return [];
}
Iterable<SemanticTokenInfo> _filter(
- Iterable<SemanticTokenInfo> tokens, SourceRange range) {
+ Iterable<SemanticTokenInfo> tokens, SourceRange? range) {
if (range == null) {
return tokens;
}
@@ -48,9 +47,9 @@
token.offset > range.end));
}
- Future<ErrorOr<SemanticTokens>> _handleImpl(
+ Future<ErrorOr<SemanticTokens?>> _handleImpl(
TextDocumentIdentifier textDocument, CancellationToken token,
- {Range range}) async {
+ {Range? range}) async {
final path = pathOfDoc(textDocument);
return path.mapResult((path) async {
@@ -61,7 +60,7 @@
return success(null);
}
- return toSourceRange(lineInfo, range).mapResult((range) async {
+ return toSourceRangeNullable(lineInfo, range).mapResult((range) async {
final serverTokens = await getServerResult(path, range);
final pluginHighlightRegions =
getPluginResults(path).expand((results) => results).toList();
@@ -125,7 +124,7 @@
SemanticTokensParams.jsonHandler;
@override
- Future<ErrorOr<SemanticTokens>> handle(
+ Future<ErrorOr<SemanticTokens?>> handle(
SemanticTokensParams params, CancellationToken token) =>
_handleImpl(params.textDocument, token);
}
@@ -142,7 +141,7 @@
SemanticTokensRangeParams.jsonHandler;
@override
- Future<ErrorOr<SemanticTokens>> handle(
+ Future<ErrorOr<SemanticTokens?>> handle(
SemanticTokensRangeParams params, CancellationToken token) =>
_handleImpl(params.textDocument, token, range: params.range);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
index a94c410..b226c29 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index 3dd708c..b57381e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/computer/computer_signature.dart';
@@ -12,7 +10,7 @@
import 'package:analysis_server/src/lsp/mapping.dart';
class SignatureHelpHandler
- extends MessageHandler<SignatureHelpParams, SignatureHelp> {
+ extends MessageHandler<SignatureHelpParams, SignatureHelp?> {
SignatureHelpHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.textDocument_signatureHelp;
@@ -22,12 +20,19 @@
SignatureHelpParams.jsonHandler;
@override
- Future<ErrorOr<SignatureHelp>> handle(
+ Future<ErrorOr<SignatureHelp?>> handle(
SignatureHelpParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
}
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
// If triggered automatically by pressing the trigger character, we will
// only provide results if the character we typed was the one that actually
// starts the argument list. This is to avoid popping open signature help
@@ -49,7 +54,7 @@
return offset.mapResult((offset) {
final computer = DartUnitSignatureComputer(
server.getDartdocDirectiveInfoFor(unit.result),
- unit.result.unit,
+ unit.result.unit!,
offset);
if (!computer.offsetIsValid) {
return success(null); // No error, just no valid hover.
@@ -63,14 +68,11 @@
// argument list.
// The ArgumentList's offset is before the paren, but the request offset
// will be after.
- if (autoTriggered &&
- computer.argumentList != null &&
- offset != computer.argumentList.offset + 1) {
+ if (autoTriggered && offset != computer.argumentList.offset + 1) {
return success(null);
}
- final formats =
- server.clientCapabilities.signatureHelpDocumentationFormats;
+ final formats = clientCapabilities.signatureHelpDocumentationFormats;
return success(toSignatureHelp(formats, signature));
});
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index 27041af..c8b201d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -48,7 +46,7 @@
FailureStateMessageHandler(LspAnalysisServer server) : super(server);
@override
- FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
+ FutureOr<ErrorOr<Object?>> handleUnknownMessage(IncomingMessage message) {
return error(
ErrorCodes.InternalError,
'An unrecoverable error occurred and the server cannot process messages',
@@ -126,7 +124,7 @@
}
@override
- ErrorOr<void> handleUnknownMessage(IncomingMessage message) {
+ ErrorOr<Object?> handleUnknownMessage(IncomingMessage message) {
// Silently drop non-requests.
if (message is! RequestMessage) {
server.instrumentationService
@@ -146,7 +144,7 @@
}
@override
- FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
+ FutureOr<ErrorOr<Object?>> handleUnknownMessage(IncomingMessage message) {
// Silently drop non-requests.
if (message is! RequestMessage) {
server.instrumentationService
@@ -166,7 +164,7 @@
}
@override
- FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
+ FutureOr<ErrorOr<Object?>> handleUnknownMessage(IncomingMessage message) {
// Silently drop non-requests.
if (message is! RequestMessage) {
server.instrumentationService
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index a03eb33..003917f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -2,7 +2,7 @@
// 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.
-// @dart = 2.9
+import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
@@ -23,14 +23,15 @@
DidChangeTextDocumentParams.jsonHandler;
@override
- ErrorOr<Null> handle(
+ FutureOr<ErrorOr<Null>> handle(
DidChangeTextDocumentParams params, CancellationToken token) {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) => _changeFile(path, params));
}
- ErrorOr<Null> _changeFile(String path, DidChangeTextDocumentParams params) {
- String oldContents;
+ FutureOr<ErrorOr<Null>> _changeFile(
+ String path, DidChangeTextDocumentParams params) {
+ String? oldContents;
if (server.resourceProvider.hasOverlay(path)) {
oldContents = server.resourceProvider.getFile(path).readAsStringSync();
}
@@ -66,7 +67,7 @@
DidCloseTextDocumentParams.jsonHandler;
@override
- ErrorOr<Null> handle(
+ FutureOr<ErrorOr<Null>> handle(
DidCloseTextDocumentParams params, CancellationToken token) {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) {
@@ -91,7 +92,7 @@
DidOpenTextDocumentParams.jsonHandler;
@override
- ErrorOr<Null> handle(
+ FutureOr<ErrorOr<Null>> handle(
DidOpenTextDocumentParams params, CancellationToken token) {
final doc = params.textDocument;
final path = pathOfDocItem(doc);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
index c256d6d..d08152f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -11,7 +9,8 @@
import 'package:analysis_server/src/lsp/mapping.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
-class WillRenameFilesHandler extends MessageHandler<RenameFilesParams, void> {
+class WillRenameFilesHandler
+ extends MessageHandler<RenameFilesParams, WorkspaceEdit?> {
WillRenameFilesHandler(LspAnalysisServer server) : super(server);
@override
Method get handlesMessage => Method.workspace_willRenameFiles;
@@ -21,9 +20,9 @@
RenameFilesParams.jsonHandler;
@override
- Future<ErrorOr<WorkspaceEdit>> handle(
+ Future<ErrorOr<WorkspaceEdit?>> handle(
RenameFilesParams params, CancellationToken token) async {
- final files = params?.files ?? [];
+ final files = params.files;
// For performance reasons, only single-file rename/moves are currently supported.
if (files.length > 1 || files.any((f) => !f.oldUri.endsWith('.dart'))) {
return success(null);
@@ -36,7 +35,7 @@
newPath.mapResult((newPath) => _renameFile(oldPath, newPath)));
}
- Future<ErrorOr<WorkspaceEdit>> _renameFile(
+ Future<ErrorOr<WorkspaceEdit?>> _renameFile(
String oldPath, String newPath) async {
final resolvedUnit = await server.getResolvedUnit(oldPath);
if (resolvedUnit == null) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_configuration.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_configuration.dart
index 067641c..36d5372 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_configuration.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
index 37f455b..96a2cae 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -24,15 +22,25 @@
@override
Future<ErrorOr<List<SymbolInformation>>> handle(
WorkspaceSymbolParams params, CancellationToken token) async {
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
// Respond to empty queries with an empty list. The spec says this should
// be non-empty, however VS Code's client sends empty requests (but then
// appears to not render the results we supply anyway).
- final query = params?.query ?? '';
+ // TODO(dantup): The spec has been updated to allow empty queries. Clients
+ // may expect a full list in this case, though we may choose not to send
+ // it on performance grounds until they type a filter.
+ final query = params.query;
if (query == '') {
return success([]);
}
- final supportedSymbolKinds = server.clientCapabilities.workspaceSymbolKinds;
+ final supportedSymbolKinds = clientCapabilities.workspaceSymbolKinds;
// Convert the string input into a case-insensitive regex that has wildcards
// between every character and at start/end to allow for fuzzy matching.
@@ -45,7 +53,7 @@
var remainingResults = 500;
final filePathsHashSet = <String>{};
- final tracker = server.declarationsTracker;
+ final tracker = server.declarationsTracker!;
final declarations = search.WorkspaceSymbols(tracker).declarations(
regex,
remainingResults,
@@ -89,10 +97,9 @@
range: range,
);
- final hasParameters =
- declaration.parameters != null && declaration.parameters.isNotEmpty;
- final nameSuffix =
- hasParameters ? (declaration.parameters == '()' ? '()' : '(…)') : '';
+ final parameters = declaration.parameters;
+ final hasParameters = parameters != null && parameters.isNotEmpty;
+ final nameSuffix = hasParameters ? (parameters == '()' ? '()' : '(…)') : '';
return SymbolInformation(
name: '${declaration.name}$nameSuffix',
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index 4a26e3c..6e31bf2 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -46,21 +44,22 @@
}
abstract class CommandHandler<P, R> with Handler<P, R> {
- CommandHandler(LspAnalysisServer server) {
- this.server = server;
- }
+ @override
+ final LspAnalysisServer server;
- Future<ErrorOr<void>> handle(List<dynamic> arguments,
+ CommandHandler(this.server);
+
+ Future<ErrorOr<Object?>> handle(List<dynamic>? arguments,
ProgressReporter progress, CancellationToken cancellationToken);
}
mixin Handler<P, R> {
- LspAnalysisServer server;
-
final fileModifiedError = error<R>(ErrorCodes.ContentModified,
'Document was modified before operation completed', null);
- bool fileHasBeenModified(String path, int clientVersion) {
+ LspAnalysisServer get server;
+
+ bool fileHasBeenModified(String path, num? clientVersion) {
final serverDocIdentifier = server.getVersionedDocumentIdentifier(path);
return clientVersion != null &&
clientVersion != serverDocIdentifier.version;
@@ -81,7 +80,7 @@
if (result?.state != ResultState.VALID) {
return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
}
- return success(result);
+ return success(result!);
}
ErrorOr<ParsedUnitResult> requireUnresolvedUnit(String path) {
@@ -89,7 +88,7 @@
if (result?.state != ResultState.VALID) {
return error(ServerErrorCodes.InvalidFilePath, 'Invalid file path', path);
}
- return success(result);
+ return success(result!);
}
}
@@ -103,7 +102,7 @@
final driver = server.getAnalysisDriver(path);
final pluginFutures = server.pluginManager.broadcastRequest(
params,
- contextRoot: driver.analysisContext.contextRoot,
+ contextRoot: driver?.analysisContext?.contextRoot,
);
return waitForResponses(pluginFutures,
@@ -116,9 +115,10 @@
/// Clients may not extend, implement or mix-in this class.
abstract class MessageHandler<P, R>
with Handler<P, R>, RequestHandlerMixin<LspAnalysisServer> {
- MessageHandler(LspAnalysisServer server) {
- this.server = server;
- }
+ @override
+ final LspAnalysisServer server;
+
+ MessageHandler(this.server);
/// The method that this handler can handle.
Method get handlesMessage;
@@ -169,7 +169,7 @@
/// Handle the given [message]. If the [message] is a [RequestMessage], then the
/// return value will be sent back in a [ResponseMessage].
/// [NotificationMessage]s are not expected to return results.
- FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async {
+ FutureOr<ErrorOr<Object?>> handleMessage(IncomingMessage message) async {
final handler = _messageHandlers[message.method];
if (handler == null) {
return handleUnknownMessage(message);
@@ -197,7 +197,7 @@
}
}
- FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
+ FutureOr<ErrorOr<Object?>> handleUnknownMessage(IncomingMessage message) {
// If it's an optional *Notification* we can ignore it (return success).
// Otherwise respond with failure. Optional Requests must still be responded
// to so they don't leave open requests on the client.
@@ -207,11 +207,6 @@
}
void registerHandler(MessageHandler handler) {
- assert(
- handler.handlesMessage != null,
- 'Unable to register handler ${handler.runtimeType} because it does '
- 'not declare which messages it can handle');
-
_messageHandlers[handler.handlesMessage] = handler;
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index c987a3f..1447e55 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
@@ -59,11 +57,11 @@
/// them.
class LspAnalysisServer extends AbstractAnalysisServer {
/// The capabilities of the LSP client. Will be null prior to initialization.
- LspClientCapabilities _clientCapabilities;
+ LspClientCapabilities? _clientCapabilities;
/// Initialization options provided by the LSP client. Allows opting in/out of
/// specific server functionality. Will be null prior to initialization.
- LspInitializationOptions _initializationOptions;
+ LspInitializationOptions? _initializationOptions;
/// Configuration for the workspace from the client. This is similar to
/// initializationOptions but can be updated dynamically rather than set
@@ -76,7 +74,7 @@
/// The workspace for rename refactorings. Should be accessed through the
/// refactoringWorkspace getter to be automatically created (lazily).
- RefactoringWorkspace _refactoringWorkspace;
+ RefactoringWorkspace? _refactoringWorkspace;
/// The versions of each document known to the server (keyed by path), used to
/// send back to the client for server-initiated edits so that the client can
@@ -87,7 +85,7 @@
/// not known.
final Map<String, VersionedTextDocumentIdentifier> documentVersions = {};
- ServerStateMessageHandler messageHandler;
+ late ServerStateMessageHandler messageHandler;
int nextRequestId = 1;
@@ -95,8 +93,8 @@
/// Capabilities of the server. Will be null prior to initialization as
/// the server capabilities depend on the client capabilities.
- ServerCapabilities capabilities;
- ServerCapabilitiesComputer capabilitiesComputer;
+ ServerCapabilities? capabilities;
+ late ServerCapabilitiesComputer capabilitiesComputer;
LspPerformance performanceStats = LspPerformance();
@@ -104,13 +102,13 @@
/// automatically.
bool willExit = false;
- StreamSubscription _pluginChangeSubscription;
+ StreamSubscription? _pluginChangeSubscription;
/// The current workspace folders provided by the client. Used as analysis roots.
final _workspaceFolders = <String>{};
/// A progress reporter for analysis status.
- ProgressReporter analyzingProgressReporter;
+ ProgressReporter? analyzingProgressReporter;
/// The number of times contexts have been created/recreated.
@visibleForTesting
@@ -125,8 +123,8 @@
DartSdkManager sdkManager,
CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
InstrumentationService instrumentationService, {
- http.Client httpClient,
- DiagnosticServer diagnosticServer,
+ http.Client? httpClient,
+ DiagnosticServer? diagnosticServer,
// Disable to avoid using this in unit tests.
bool enableBazelWatcher = false,
}) : super(
@@ -157,16 +155,18 @@
}
/// The capabilities of the LSP client. Will be null prior to initialization.
- LspClientCapabilities get clientCapabilities => _clientCapabilities;
+ LspClientCapabilities? get clientCapabilities => _clientCapabilities;
Future<void> get exited => channel.closed;
/// Initialization options provided by the LSP client. Allows opting in/out of
/// specific server functionality. Will be null prior to initialization.
- LspInitializationOptions get initializationOptions => _initializationOptions;
+ LspInitializationOptions get initializationOptions =>
+ _initializationOptions as LspInitializationOptions;
@override
- LspNotificationManager get notificationManager => super.notificationManager;
+ LspNotificationManager get notificationManager =>
+ super.notificationManager as LspNotificationManager;
@override
set pluginManager(PluginManager value) {
@@ -202,7 +202,7 @@
/// Fetches configuration from the client (if supported) and then sends
/// register/unregister requests for any supported/enabled dynamic registrations.
Future<void> fetchClientConfigurationAndPerformDynamicRegistration() async {
- if (clientCapabilities.configuration) {
+ if (clientCapabilities?.configuration ?? false) {
// Fetch all configuration we care about from the client. This is just
// "dart" for now, but in future this may be extended to include
// others (for example "flutter").
@@ -243,8 +243,8 @@
/// Return the LineInfo for the file with the given [path]. The file is
/// analyzed in one of the analysis drivers to which the file was added,
/// otherwise in the first driver, otherwise `null` is returned.
- LineInfo getLineInfo(String path) {
- return getAnalysisDriver(path)?.getFileSync(path)?.lineInfo;
+ LineInfo? getLineInfo(String path) {
+ return getAnalysisDriver(path)?.getFileSync(path).lineInfo;
}
/// Gets the version of a document known to the server, returning a
@@ -263,16 +263,22 @@
_initializationOptions = LspInitializationOptions(initializationOptions);
performanceAfterStartup = ServerPerformance();
- performance = performanceAfterStartup;
+ performance = performanceAfterStartup!;
}
/// Handles a response from the client by invoking the completer that the
/// outbound request created.
void handleClientResponse(ResponseMessage message) {
- // The ID from the client is an Either2<num, String>, though it's not valid
- // for it to be a string because it should match a request we sent to the
- // client (and we always use numeric IDs for outgoing requests).
- message.id.map(
+ // The ID from the client is an Either2<num, String>?, though it's not valid
+ // for it to be a null or a string because it should match a request we sent
+ // to the client (and we always use numeric IDs for outgoing requests).
+ final id = message.id;
+ if (id == null) {
+ showErrorMessageToUser('Unexpected response with no ID!');
+ return;
+ }
+
+ id.map(
(id) {
// It's possible that even if we got a numeric ID that it's not valid.
// If it's not in our completers list (which is a list of the
@@ -366,7 +372,7 @@
exceptions.add(ServerException(
message,
exception,
- stackTrace is StackTrace ? stackTrace : null,
+ stackTrace is StackTrace ? stackTrace : StackTrace.current,
false,
));
@@ -399,8 +405,8 @@
///
/// If the result of applying the edits is already known, [newContent] can be
/// set to avoid doing that calculation twice.
- void onOverlayUpdated(String path, Iterable<plugin.SourceEdit> edits,
- {String newContent}) {
+ void onOverlayUpdated(String path, List<plugin.SourceEdit> edits,
+ {String? newContent}) {
assert(resourceProvider.hasOverlay(path));
if (newContent == null) {
final oldContent = resourceProvider.getFile(path).readAsStringSync();
@@ -538,7 +544,7 @@
// Send old custom notifications to clients that do not support $/progress.
// TODO(dantup): Remove this custom notification (and related classes) when
// it's unlikely to be in use by any clients.
- if (clientCapabilities.workDoneProgress != true) {
+ if (clientCapabilities?.workDoneProgress != true) {
channel.sendNotification(NotificationMessage(
method: CustomMethods.analyzerStatus,
params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
@@ -555,7 +561,7 @@
if (analyzingProgressReporter != null) {
// Do not null this out until after end completes, otherwise we may try
// to create a new token before it's really completed.
- await analyzingProgressReporter.end();
+ await analyzingProgressReporter?.end();
analyzingProgressReporter = null;
}
}
@@ -634,8 +640,8 @@
// TODO(dantup): This is currently case-sensitive!
_workspaceFolders
- ..addAll(addedPaths ?? const [])
- ..removeAll(removedPaths ?? const []);
+ ..addAll(addedPaths)
+ ..removeAll(removedPaths);
_refreshAnalysisRoots();
}
@@ -802,25 +808,35 @@
@override
void listenAnalysisDriver(nd.AnalysisDriver analysisDriver) {
- analysisServer.declarationsTracker
- ?.addContext(analysisDriver.analysisContext);
+ // TODO(dantup): Is this required, or covered by
+ // addContextsToDeclarationsTracker? The original server does not appear to
+ // have an equivalent call.
+ final analysisContext = analysisDriver.analysisContext;
+ if (analysisContext != null) {
+ analysisServer.declarationsTracker?.addContext(analysisContext);
+ }
analysisDriver.results.listen((result) {
var path = result.path;
+ if (path == null) {
+ // This shouldn't occur - result.path is marked with a TODO to become
+ // non-nullable.
+ return;
+ }
filesToFlush.add(path);
if (analysisServer.isAnalyzed(path)) {
final serverErrors = protocol.doAnalysisError_listFromEngine(result);
- recordAnalysisErrors(result.path, serverErrors);
+ recordAnalysisErrors(path, serverErrors);
}
- if (result.unit != null) {
+ final unit = result.unit;
+ if (unit != null) {
if (analysisServer.shouldSendClosingLabelsFor(path)) {
- final labels =
- DartUnitClosingLabelsComputer(result.lineInfo, result.unit)
- .compute()
- .map((l) => toClosingLabel(result.lineInfo, l))
- .toList();
+ final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
+ .compute()
+ .map((l) => toClosingLabel(result.lineInfo, l))
+ .toList();
- analysisServer.publishClosingLabels(result.path, labels);
+ analysisServer.publishClosingLabels(path, labels);
}
if (analysisServer.shouldSendOutlineFor(path)) {
final outline = DartUnitOutlineComputer(
@@ -828,12 +844,12 @@
withBasicFlutter: true,
).compute();
final lspOutline = toOutline(result.lineInfo, outline);
- analysisServer.publishOutline(result.path, lspOutline);
+ analysisServer.publishOutline(path, lspOutline);
}
if (analysisServer.shouldSendFlutterOutlineFor(path)) {
final outline = FlutterOutlineComputer(result).compute();
final lspOutline = toFlutterOutline(result.lineInfo, outline);
- analysisServer.publishFlutterOutline(result.path, lspOutline);
+ analysisServer.publishFlutterOutline(path, lspOutline);
}
}
});
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
index d567d37..25c012e 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_socket_server.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2018, 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.
-
+//
// @dart = 2.9
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 3f0b00c..f9d8355 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -2,12 +2,11 @@
// 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.
-// @dart = 2.9
-
import 'dart:math';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
as lsp;
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
@@ -32,7 +31,7 @@
import 'package:analyzer/src/services/available_declarations.dart' as dec;
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
import 'package:analyzer_plugin/utilities/pair.dart';
-import 'package:meta/meta.dart';
+import 'package:collection/collection.dart';
const languageSourceName = 'dart';
@@ -51,11 +50,7 @@
};
lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent(
- Set<lsp.MarkupKind> preferredFormats, String content) {
- if (content == null) {
- return null;
- }
-
+ Set<lsp.MarkupKind>? preferredFormats, String content) {
return preferredFormats == null
? lsp.Either2<String, lsp.MarkupContent>.t1(content)
: lsp.Either2<String, lsp.MarkupContent>.t2(
@@ -64,8 +59,8 @@
/// Builds an LSP snippet string with supplied ranges as tabstops.
String buildSnippetStringWithTabStops(
- String text,
- List<int> offsetLengthPairs,
+ String? text,
+ List<int>? offsetLengthPairs,
) {
text ??= '';
offsetLengthPairs ??= const [];
@@ -119,11 +114,13 @@
lsp.WorkspaceEdit createPlainWorkspaceEdit(
lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
return toWorkspaceEdit(
- server.clientCapabilities,
+ // Client capabilities are always available after initialization.
+ server.clientCapabilities!,
edits
.map((e) => FileEditInformation(
server.getVersionedDocumentIdentifier(e.file),
- server.getLineInfo(e.file),
+ // We should never produce edits for a file with no LineInfo.
+ server.getLineInfo(e.file)!,
e.edits,
// fileStamp == 1 is used by the server to indicate the file needs creating.
newFile: e.fileStamp == -1,
@@ -143,7 +140,7 @@
// In order to return snippets, we must ensure we are only modifying a single
// existing file with a single edit and that there is a linked edit group with
// only one position and no suggestions.
- if (!server.clientCapabilities.experimentalSnippetTextEdit ||
+ if (!server.clientCapabilities!.experimentalSnippetTextEdit ||
change.edits.length != 1 ||
change.edits.first.fileStamp == -1 || // new file
change.edits.first.edits.length != 1 ||
@@ -164,11 +161,12 @@
}
return toWorkspaceEdit(
- server.clientCapabilities,
+ server.clientCapabilities!,
change.edits
.map((e) => FileEditInformation(
server.getVersionedDocumentIdentifier(e.file),
- server.getLineInfo(e.file),
+ // We should never produce edits for a file with no LineInfo.
+ server.getLineInfo(e.file)!,
e.edits,
selectionOffsetRelative: selectionOffset - edit.offset,
selectionLength: selectionLength,
@@ -177,7 +175,7 @@
.toList());
}
-lsp.CompletionItemKind declarationKindToCompletionItemKind(
+lsp.CompletionItemKind? declarationKindToCompletionItemKind(
Set<lsp.CompletionItemKind> supportedCompletionKinds,
dec.DeclarationKind kind,
) {
@@ -210,12 +208,12 @@
}
}
- return getKindPreferences().firstWhere(isSupported, orElse: () => null);
+ return getKindPreferences().firstWhereOrNull(isSupported);
}
lsp.SymbolKind declarationKindToSymbolKind(
Set<lsp.SymbolKind> supportedSymbolKinds,
- server.DeclarationKind kind,
+ server.DeclarationKind? kind,
) {
bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);
@@ -274,26 +272,25 @@
int replacementOffset,
int insertLength,
int replacementLength, {
- @required bool includeCommitCharacters,
- @required bool completeFunctionCalls,
+ required bool includeCommitCharacters,
+ required bool completeFunctionCalls,
}) {
final supportsSnippets = capabilities.completionSnippets;
+ final parent = declaration.parent;
String completion;
switch (declaration.kind) {
case DeclarationKind.ENUM_CONSTANT:
- completion = '${declaration.parent.name}.${declaration.name}';
+ completion = '${parent!.name}.${declaration.name}';
break;
case DeclarationKind.GETTER:
case DeclarationKind.FIELD:
- completion = declaration.parent != null &&
- declaration.parent.name != null &&
- declaration.parent.name.isNotEmpty
- ? '${declaration.parent.name}.${declaration.name}'
+ completion = parent != null && parent.name.isNotEmpty
+ ? '${parent.name}.${declaration.name}'
: declaration.name;
break;
case DeclarationKind.CONSTRUCTOR:
- completion = declaration.parent.name;
+ completion = parent!.name;
if (declaration.name.isNotEmpty) {
completion += '.${declaration.name}';
}
@@ -347,10 +344,8 @@
capabilities.completionItemKinds, declaration.kind);
var relevanceBoost = 0;
- if (declaration.relevanceTags != null) {
- declaration.relevanceTags.forEach(
- (t) => relevanceBoost = max(relevanceBoost, tagBoosts[t] ?? 0));
- }
+ declaration.relevanceTags
+ .forEach((t) => relevanceBoost = max(relevanceBoost, tagBoosts[t] ?? 0));
final itemRelevance = includedSuggestionSet.relevance + relevanceBoost;
// Because we potentially send thousands of these items, we should minimise
@@ -392,14 +387,14 @@
file: file,
offset: offset,
libId: includedSuggestionSet.id,
- displayUri: includedSuggestionSet.displayUri ?? library.uri?.toString(),
+ displayUri: includedSuggestionSet.displayUri ?? library.uri.toString(),
rOffset: replacementOffset,
iLength: insertLength,
rLength: replacementLength),
);
}
-lsp.CompletionItemKind elementKindToCompletionItemKind(
+lsp.CompletionItemKind? elementKindToCompletionItemKind(
Set<lsp.CompletionItemKind> supportedCompletionKinds,
server.ElementKind kind,
) {
@@ -461,12 +456,12 @@
}
}
- return getKindPreferences().firstWhere(isSupported, orElse: () => null);
+ return getKindPreferences().firstWhereOrNull(isSupported);
}
lsp.SymbolKind elementKindToSymbolKind(
Set<lsp.SymbolKind> supportedSymbolKinds,
- server.ElementKind kind,
+ server.ElementKind? kind,
) {
bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);
@@ -538,20 +533,21 @@
.firstWhere(isSupported, orElse: () => lsp.SymbolKind.Obj);
}
-String getCompletionDetail(
+String? getCompletionDetail(
server.CompletionSuggestion suggestion,
- lsp.CompletionItemKind completionKind,
+ lsp.CompletionItemKind? completionKind,
bool supportsDeprecated,
) {
- final hasElement = suggestion.element != null;
- final hasParameters = hasElement &&
- suggestion.element.parameters != null &&
- suggestion.element.parameters.isNotEmpty;
- final hasReturnType = hasElement &&
- suggestion.element.returnType != null &&
- suggestion.element.returnType.isNotEmpty;
- final hasParameterType =
- suggestion.parameterType != null && suggestion.parameterType.isNotEmpty;
+ final element = suggestion.element;
+ final hasElement = element != null;
+ final parameters = element?.parameters;
+ final returnType = element?.returnType;
+ final parameterType = suggestion.parameterType;
+ final hasParameters =
+ hasElement && parameters != null && parameters.isNotEmpty;
+ final hasReturnType =
+ hasElement && returnType != null && returnType.isNotEmpty;
+ final hasParameterType = parameterType != null && parameterType.isNotEmpty;
final prefix =
supportsDeprecated || !suggestion.isDeprecated ? '' : '(Deprecated) ';
@@ -562,36 +558,34 @@
// To avoid this, always show only the return type, whether it's a getter
// or a setter.
return prefix +
- (suggestion.element.kind == server.ElementKind.GETTER
- ? suggestion.element.returnType
+ (element?.kind == server.ElementKind.GETTER
+ ? (returnType ?? '')
// Don't assume setters always have parameters
// See https://github.com/dart-lang/sdk/issues/27747
- : suggestion.element.parameters != null &&
- suggestion.element.parameters.isNotEmpty
+ : parameters != null && parameters.isNotEmpty
// Extract the type part from '(MyType value)`
- ? suggestion.element.parameters.substring(
- 1, suggestion.element.parameters.lastIndexOf(' '))
+ ? parameters.substring(1, parameters.lastIndexOf(' '))
: '');
} else if (hasParameters && hasReturnType) {
- return '$prefix${suggestion.element.parameters} → ${suggestion.element.returnType}';
+ return '$prefix$parameters → $returnType';
} else if (hasReturnType) {
- return '$prefix${suggestion.element.returnType}';
+ return '$prefix$returnType';
} else if (hasParameterType) {
- return '$prefix${suggestion.parameterType}';
+ return '$prefix$parameterType';
} else {
return prefix.isNotEmpty ? prefix : null;
}
}
-String getDeclarationCompletionDetail(
+String? getDeclarationCompletionDetail(
dec.Declaration declaration,
- lsp.CompletionItemKind completionKind,
+ lsp.CompletionItemKind? completionKind,
bool supportsDeprecated,
) {
- final hasParameters =
- declaration.parameters != null && declaration.parameters.isNotEmpty;
- final hasReturnType =
- declaration.returnType != null && declaration.returnType.isNotEmpty;
+ final parameters = declaration.parameters;
+ final hasParameters = parameters != null && parameters.isNotEmpty;
+ final returnType = declaration.returnType;
+ final hasReturnType = returnType != null && returnType.isNotEmpty;
final prefix =
supportsDeprecated || !declaration.isDeprecated ? '' : '(Deprecated) ';
@@ -603,15 +597,15 @@
// or a setter.
var suffix = '';
if (declaration.kind == dec.DeclarationKind.GETTER) {
- suffix = declaration.returnType;
+ suffix = declaration.returnType ?? '';
} else {
// Don't assume setters always have parameters
// See https://github.com/dart-lang/sdk/issues/27747
- if (declaration.parameters != null && declaration.parameters.isNotEmpty) {
+ if (parameters != null && parameters.isNotEmpty) {
// Extract the type part from `(MyType value)`, if there is a type.
- var spaceIndex = declaration.parameters.lastIndexOf(' ');
+ var spaceIndex = parameters.lastIndexOf(' ');
if (spaceIndex > 0) {
- suffix = declaration.parameters.substring(1, spaceIndex);
+ suffix = parameters.substring(1, spaceIndex);
}
}
}
@@ -625,51 +619,45 @@
}
}
-List<lsp.DiagnosticTag> getDiagnosticTags(
- Set<lsp.DiagnosticTag> supportedTags, plugin.AnalysisError error) {
+List<lsp.DiagnosticTag>? getDiagnosticTags(
+ Set<lsp.DiagnosticTag>? supportedTags, plugin.AnalysisError error) {
if (supportedTags == null) {
return null;
}
final tags = diagnosticTagsForErrorCode[error.code]
?.where(supportedTags.contains)
- ?.toList();
+ .toList();
return tags != null && tags.isNotEmpty ? tags : null;
}
-bool isDartDocument(lsp.TextDocumentIdentifier doc) =>
- doc?.uri?.endsWith('.dart');
+bool isDartDocument(lsp.TextDocumentIdentifier? doc) =>
+ doc?.uri.endsWith('.dart') ?? false;
lsp.Location navigationTargetToLocation(
String targetFilePath,
server.NavigationTarget target,
server.LineInfo targetLineInfo,
) {
- if (targetLineInfo == null) {
- return null;
- }
-
return lsp.Location(
uri: Uri.file(targetFilePath).toString(),
range: toRange(targetLineInfo, target.offset, target.length),
);
}
-lsp.LocationLink navigationTargetToLocationLink(
+lsp.LocationLink? navigationTargetToLocationLink(
server.NavigationRegion region,
server.LineInfo regionLineInfo,
String targetFilePath,
server.NavigationTarget target,
server.LineInfo targetLineInfo,
) {
- if (regionLineInfo == null || targetLineInfo == null) {
- return null;
- }
-
final nameRange = toRange(targetLineInfo, target.offset, target.length);
- final codeRange = target.codeOffset != null && target.codeLength != null
- ? toRange(targetLineInfo, target.codeOffset, target.codeLength)
+ final codeOffset = target.codeOffset;
+ final codeLength = target.codeLength;
+ final codeRange = codeOffset != null && codeLength != null
+ ? toRange(targetLineInfo, codeOffset, codeLength)
: nameRange;
return lsp.LocationLink(
@@ -682,21 +670,21 @@
/// Returns the file system path for a TextDocumentIdentifier.
ErrorOr<String> pathOfDoc(lsp.TextDocumentIdentifier doc) =>
- pathOfUri(Uri.tryParse(doc?.uri));
+ pathOfUri(Uri.tryParse(doc.uri));
/// Returns the file system path for a TextDocumentItem.
ErrorOr<String> pathOfDocItem(lsp.TextDocumentItem doc) =>
- pathOfUri(Uri.tryParse(doc?.uri));
+ pathOfUri(Uri.tryParse(doc.uri));
/// Returns the file system path for a file URI.
-ErrorOr<String> pathOfUri(Uri uri) {
+ErrorOr<String> pathOfUri(Uri? uri) {
if (uri == null) {
return ErrorOr<String>.error(ResponseError(
code: lsp.ServerErrorCodes.InvalidFilePath,
message: 'Document URI was not supplied',
));
}
- final isValidFileUri = uri?.isScheme('file') ?? false;
+ final isValidFileUri = uri.isScheme('file');
if (!isValidFileUri) {
return ErrorOr<String>.error(ResponseError(
code: lsp.ServerErrorCodes.InvalidFilePath,
@@ -719,13 +707,15 @@
lsp.Diagnostic pluginToDiagnostic(
server.LineInfo Function(String) getLineInfo,
plugin.AnalysisError error, {
- @required Set<lsp.DiagnosticTag> supportedTags,
+ required Set<lsp.DiagnosticTag>? supportedTags,
}) {
- List<lsp.DiagnosticRelatedInformation> relatedInformation;
- if (error.contextMessages != null && error.contextMessages.isNotEmpty) {
- relatedInformation = error.contextMessages
+ List<lsp.DiagnosticRelatedInformation>? relatedInformation;
+ final contextMessages = error.contextMessages;
+ if (contextMessages != null && contextMessages.isNotEmpty) {
+ relatedInformation = contextMessages
.map((message) =>
pluginToDiagnosticRelatedInformation(getLineInfo, message))
+ .whereNotNull()
.toList();
}
@@ -746,11 +736,16 @@
);
}
-lsp.DiagnosticRelatedInformation pluginToDiagnosticRelatedInformation(
- server.LineInfo Function(String) getLineInfo,
+lsp.DiagnosticRelatedInformation? pluginToDiagnosticRelatedInformation(
+ server.LineInfo? Function(String) getLineInfo,
plugin.DiagnosticMessage message) {
- var file = message.location.file;
- var lineInfo = getLineInfo(file);
+ final file = message.location.file;
+ final lineInfo = getLineInfo(file);
+ // We shouldn't get context messages for something we can't get a LineInfo for
+ // but if we did, it's better to omit the context than fail to send the errors.
+ if (lineInfo == null) {
+ return null;
+ }
return lsp.DiagnosticRelatedInformation(
location: lsp.Location(
uri: Uri.file(file).toString(),
@@ -781,8 +776,8 @@
}
}
-lsp.Location searchResultToLocation(
- server.SearchResult result, server.LineInfo lineInfo) {
+lsp.Location? searchResultToLocation(
+ server.SearchResult result, server.LineInfo? lineInfo) {
final location = result.location;
if (lineInfo == null) {
@@ -795,7 +790,7 @@
);
}
-lsp.CompletionItemKind suggestionKindToCompletionItemKind(
+lsp.CompletionItemKind? suggestionKindToCompletionItemKind(
Set<lsp.CompletionItemKind> supportedCompletionKinds,
server.CompletionSuggestionKind kind,
String label,
@@ -840,7 +835,7 @@
}
}
- return getKindPreferences().firstWhere(isSupported, orElse: () => null);
+ return getKindPreferences().firstWhereOrNull(isSupported);
}
lsp.ClosingLabel toClosingLabel(
@@ -849,7 +844,7 @@
range: toRange(lineInfo, label.offset, label.length),
label: label.label);
-lsp.CodeActionKind toCodeActionKind(String id, lsp.CodeActionKind fallback) {
+lsp.CodeActionKind toCodeActionKind(String? id, lsp.CodeActionKind fallback) {
if (id == null) {
return fallback;
}
@@ -872,9 +867,9 @@
int replacementOffset,
int insertLength,
int replacementLength, {
- @required bool includeCommitCharacters,
- @required bool completeFunctionCalls,
- Object resolutionData,
+ required bool includeCommitCharacters,
+ required bool completeFunctionCalls,
+ CompletionItemResolutionInfo? resolutionData,
}) {
// Build separate display and filter labels. Displayed labels may have additional
// info appended (for example '(...)' on callables) that should not be included
@@ -917,9 +912,10 @@
final supportsAsIsInsertMode =
capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);
- final completionKind = suggestion.element != null
+ final element = suggestion.element;
+ final completionKind = element != null
? elementKindToCompletionItemKind(
- capabilities.completionItemKinds, suggestion.element.kind)
+ capabilities.completionItemKinds, element.kind)
: suggestionKindToCompletionItemKind(
capabilities.completionItemKinds, suggestion.kind, label);
@@ -938,6 +934,7 @@
final insertText = insertTextInfo.first;
final insertTextFormat = insertTextInfo.last;
final isMultilineCompletion = insertText.contains('\n');
+ final cleanedDoc = cleanDartdoc(suggestion.docComplete);
// Because we potentially send thousands of these items, we should minimise
// the generated JSON as much as possible - for example using nulls in place
@@ -954,8 +951,9 @@
data: resolutionData,
detail: getCompletionDetail(suggestion, completionKind,
supportsCompletionDeprecatedFlag || supportsDeprecatedTag),
- documentation:
- asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)),
+ documentation: cleanedDoc != null
+ ? asStringOrMarkupContent(formats, cleanedDoc)
+ : null,
deprecated: supportsCompletionDeprecatedFlag && suggestion.isDeprecated
? true
: null,
@@ -997,27 +995,28 @@
lsp.Diagnostic toDiagnostic(
server.ResolvedUnitResult result,
server.AnalysisError error, {
- @required Set<lsp.DiagnosticTag> supportedTags,
- server.ErrorSeverity errorSeverity,
+ required Set<lsp.DiagnosticTag> supportedTags,
}) =>
pluginToDiagnostic((_) => result.lineInfo,
server.newAnalysisError_fromEngine(result, error),
supportedTags: supportedTags);
-lsp.Element toElement(server.LineInfo lineInfo, server.Element element) =>
- lsp.Element(
- range: element.location != null
- ? toRange(lineInfo, element.location.offset, element.location.length)
- : null,
- name: toElementName(element),
- kind: element.kind.name,
- parameters: element.parameters,
- typeParameters: element.typeParameters,
- returnType: element.returnType,
- );
+lsp.Element toElement(server.LineInfo lineInfo, server.Element element) {
+ final location = element.location;
+ return lsp.Element(
+ range: location != null
+ ? toRange(lineInfo, location.offset, location.length)
+ : null,
+ name: toElementName(element),
+ kind: element.kind.name,
+ parameters: element.parameters,
+ typeParameters: element.typeParameters,
+ returnType: element.returnType,
+ );
+}
String toElementName(server.Element element) {
- return element.name != null && element.name != ''
+ return element.name.isNotEmpty
? element.name
: (element.kind == server.ElementKind.EXTENSION
? '<unnamed extension>'
@@ -1025,37 +1024,40 @@
}
lsp.FlutterOutline toFlutterOutline(
- server.LineInfo lineInfo, server.FlutterOutline outline) =>
- lsp.FlutterOutline(
- kind: outline.kind.name,
- label: outline.label,
- className: outline.className,
- variableName: outline.variableName,
- attributes: outline.attributes != null
- ? outline.attributes
- .map(
- (attribute) => toFlutterOutlineAttribute(lineInfo, attribute))
- .toList()
- : null,
- dartElement: outline.dartElement != null
- ? toElement(lineInfo, outline.dartElement)
- : null,
- range: toRange(lineInfo, outline.offset, outline.length),
- codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
- children: outline.children != null
- ? outline.children.map((c) => toFlutterOutline(lineInfo, c)).toList()
- : null,
- );
+ server.LineInfo lineInfo, server.FlutterOutline outline) {
+ final attributes = outline.attributes;
+ final dartElement = outline.dartElement;
+ final children = outline.children;
+
+ return lsp.FlutterOutline(
+ kind: outline.kind.name,
+ label: outline.label,
+ className: outline.className,
+ variableName: outline.variableName,
+ attributes: attributes != null
+ ? attributes
+ .map((attribute) => toFlutterOutlineAttribute(lineInfo, attribute))
+ .toList()
+ : null,
+ dartElement: dartElement != null ? toElement(lineInfo, dartElement) : null,
+ range: toRange(lineInfo, outline.offset, outline.length),
+ codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
+ children: children != null
+ ? children.map((c) => toFlutterOutline(lineInfo, c)).toList()
+ : null,
+ );
+}
lsp.FlutterOutlineAttribute toFlutterOutlineAttribute(
- server.LineInfo lineInfo, server.FlutterOutlineAttribute attribute) =>
- lsp.FlutterOutlineAttribute(
- name: attribute.name,
- label: attribute.label,
- valueRange: attribute.valueLocation != null
- ? toRange(lineInfo, attribute.valueLocation.offset,
- attribute.valueLocation.length)
- : null);
+ server.LineInfo lineInfo, server.FlutterOutlineAttribute attribute) {
+ final valueLocation = attribute.valueLocation;
+ return lsp.FlutterOutlineAttribute(
+ name: attribute.name,
+ label: attribute.label,
+ valueRange: valueLocation != null
+ ? toRange(lineInfo, valueLocation.offset, valueLocation.length)
+ : null);
+}
lsp.FoldingRange toFoldingRange(
server.LineInfo lineInfo, server.FoldingRegion region) {
@@ -1068,7 +1070,7 @@
kind: toFoldingRangeKind(region.kind));
}
-lsp.FoldingRangeKind toFoldingRangeKind(server.FoldingKind kind) {
+lsp.FoldingRangeKind? toFoldingRangeKind(server.FoldingKind kind) {
switch (kind) {
case server.FoldingKind.COMMENT:
case server.FoldingKind.DOCUMENTATION_COMMENT:
@@ -1123,15 +1125,17 @@
lineInfo.getOffsetOfLine(pos.line) + pos.character);
}
-lsp.Outline toOutline(server.LineInfo lineInfo, server.Outline outline) =>
- lsp.Outline(
- element: toElement(lineInfo, outline.element),
- range: toRange(lineInfo, outline.offset, outline.length),
- codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
- children: outline.children != null
- ? outline.children.map((c) => toOutline(lineInfo, c)).toList()
- : null,
- );
+lsp.Outline toOutline(server.LineInfo lineInfo, server.Outline outline) {
+ final children = outline.children;
+ return lsp.Outline(
+ element: toElement(lineInfo, outline.element),
+ range: toRange(lineInfo, outline.offset, outline.length),
+ codeRange: toRange(lineInfo, outline.codeOffset, outline.codeLength),
+ children: children != null
+ ? children.map((c) => toOutline(lineInfo, c)).toList()
+ : null,
+ );
+}
lsp.Position toPosition(server.CharacterLocation location) {
// LSP is zero-based, but analysis server is 1-based.
@@ -1140,8 +1144,8 @@
}
lsp.Range toRange(server.LineInfo lineInfo, int offset, int length) {
- server.CharacterLocation start = lineInfo.getLocation(offset);
- server.CharacterLocation end = lineInfo.getLocation(offset + length);
+ final start = lineInfo.getLocation(offset) as server.CharacterLocation;
+ final end = lineInfo.getLocation(offset + length) as server.CharacterLocation;
return lsp.Range(
start: toPosition(start),
@@ -1149,7 +1153,7 @@
);
}
-lsp.SignatureHelp toSignatureHelp(Set<lsp.MarkupKind> preferredFormats,
+lsp.SignatureHelp toSignatureHelp(Set<lsp.MarkupKind>? preferredFormats,
server.AnalysisGetSignatureResult signature) {
// For now, we only support returning one (though we may wish to use named
// args. etc. to provide one for each possible "next" option when the cursor
@@ -1199,13 +1203,15 @@
return lsp.ParameterInformation(label: getParamLabel(param));
}
- final cleanDoc = cleanDartdoc(signature.dartdoc);
+ final cleanedDoc = cleanDartdoc(signature.dartdoc);
return lsp.SignatureHelp(
signatures: [
lsp.SignatureInformation(
label: getSignatureLabel(signature),
- documentation: asStringOrMarkupContent(preferredFormats, cleanDoc),
+ documentation: cleanedDoc != null
+ ? asStringOrMarkupContent(preferredFormats, cleanedDoc)
+ : null,
parameters: signature.parameters.map(toParameterInfo).toList(),
),
],
@@ -1227,8 +1233,7 @@
server.LineInfo lineInfo,
server.SourceEdit edit,
int selectionOffsetRelative,
- int selectionLength) {
- assert(selectionOffsetRelative != null);
+ int? selectionLength) {
return lsp.SnippetTextEdit(
insertTextFormat: lsp.InsertTextFormat.Snippet,
range: toRange(lineInfo, edit.offset, edit.length),
@@ -1239,27 +1244,27 @@
ErrorOr<server.SourceRange> toSourceRange(
server.LineInfo lineInfo, Range range) {
- if (range == null) {
- return success(null);
- }
-
// If there is a range, convert to offsets because that's what
// the tokens are computed using initially.
final start = toOffset(lineInfo, range.start);
final end = toOffset(lineInfo, range.end);
- if (start?.isError ?? false) {
+ if (start.isError) {
return failure(start);
}
- if (end?.isError ?? false) {
+ if (end.isError) {
return failure(end);
}
- final startOffset = start?.result;
- final endOffset = end?.result;
+ final startOffset = start.result;
+ final endOffset = end.result;
return success(server.SourceRange(startOffset, endOffset - startOffset));
}
+ErrorOr<server.SourceRange?> toSourceRangeNullable(
+ server.LineInfo lineInfo, Range? range) =>
+ range != null ? toSourceRange(lineInfo, range) : success(null);
+
lsp.TextDocumentEdit toTextDocumentEdit(
LspClientCapabilities capabilities, FileEditInformation edit) {
return lsp.TextDocumentEdit(
@@ -1276,8 +1281,8 @@
LspClientCapabilities capabilities,
server.LineInfo lineInfo,
server.SourceEdit edit, {
- int selectionOffsetRelative,
- int selectionLength,
+ int? selectionOffsetRelative,
+ int? selectionLength,
}) {
if (!capabilities.experimentalSnippetTextEdit ||
selectionOffsetRelative == null) {
@@ -1348,15 +1353,6 @@
lsp.MarkupContent _asMarkup(
Set<lsp.MarkupKind> preferredFormats, String content) {
- // It's not valid to call this function with a null format, as null formats
- // do not support MarkupContent. [asStringOrMarkupContent] is probably the
- // better choice.
- assert(preferredFormats != null);
-
- if (content == null) {
- return null;
- }
-
if (preferredFormats.isEmpty) {
preferredFormats.add(lsp.MarkupKind.Markdown);
}
@@ -1373,16 +1369,16 @@
}
Pair<String, lsp.InsertTextFormat> _buildInsertText({
- @required bool supportsSnippets,
- @required bool includeCommitCharacters,
- @required bool completeFunctionCalls,
- @required bool isCallable,
- @required bool isInvocation,
- @required String defaultArgumentListString,
- @required List<int> defaultArgumentListTextRanges,
- @required String completion,
- @required int selectionOffset,
- @required int selectionLength,
+ required bool supportsSnippets,
+ required bool includeCommitCharacters,
+ required bool completeFunctionCalls,
+ required bool isCallable,
+ required bool isInvocation,
+ required String? defaultArgumentListString,
+ required List<int>? defaultArgumentListTextRanges,
+ required String completion,
+ required int selectionOffset,
+ required int selectionLength,
}) {
var insertText = completion;
var insertTextFormat = lsp.InsertTextFormat.PlainText;
diff --git a/pkg/analysis_server/lib/src/lsp/notification_manager.dart b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
index 0866a25..dc45460 100644
--- a/pkg/analysis_server/lib/src/lsp/notification_manager.dart
+++ b/pkg/analysis_server/lib/src/lsp/notification_manager.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
@@ -20,7 +18,8 @@
/// The analysis server, used to fetch LineInfo in order to map plugin
/// data structures to LSP structures.
- LspAnalysisServer server;
+ late LspAnalysisServer
+ server; // Set externally immediately after construction
LspNotificationManager(this.channel, Context pathContext)
: super(pathContext);
@@ -31,9 +30,10 @@
String filePath, List<protocol.AnalysisError> errors) {
final diagnostics = errors
.map((error) => pluginToDiagnostic(
- server.getLineInfo,
+ // We should never errors for a file we can't get a LineInfo for
+ (path) => server.getLineInfo(path)!,
error,
- supportedTags: server.clientCapabilities.diagnosticTags,
+ supportedTags: server.clientCapabilities?.diagnosticTags,
))
.toList();
diff --git a/pkg/analysis_server/lib/src/lsp/progress.dart b/pkg/analysis_server/lib/src/lsp/progress.dart
index 6b87f74..fcb2dac 100644
--- a/pkg/analysis_server/lib/src/lsp/progress.dart
+++ b/pkg/analysis_server/lib/src/lsp/progress.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'dart:math';
@@ -27,13 +25,13 @@
///
/// If [token] is not supplied, a random identifier will be used.
factory ProgressReporter.serverCreated(LspAnalysisServer server,
- [Either2<num, String> token]) =>
+ [Either2<num, String>? token]) =>
_ServerCreatedProgressReporter(server, token);
ProgressReporter._();
// TODO(dantup): Add support for cancellable progress notifications.
- FutureOr<void> begin(String title, {String message});
+ FutureOr<void> begin(String title, {String? message});
FutureOr<void> end([String message]);
}
@@ -41,25 +39,25 @@
class _NoopProgressReporter extends ProgressReporter {
_NoopProgressReporter() : super._();
@override
- void begin(String title, {String message}) {}
+ void begin(String title, {String? message}) {}
@override
- void end([String message]) {}
+ void end([String? message]) {}
}
class _ServerCreatedProgressReporter extends _TokenProgressReporter {
static final _random = Random();
- Future<bool> _tokenBeginRequest;
+ Future<bool>? _tokenBeginRequest;
_ServerCreatedProgressReporter(
LspAnalysisServer server,
- Either2<num, String> token,
+ Either2<num, String>? token,
) : super(
server,
token ?? Either2<num, String>.t2(_randomTokenIdentifier()),
);
@override
- Future<void> begin(String title, {String message}) async {
+ Future<void> begin(String? title, {String? message}) async {
assert(_tokenBeginRequest == null,
'Begin should not be called more than once');
@@ -81,12 +79,13 @@
}
@override
- Future<void> end([String message]) async {
+ Future<void> end([String? message]) async {
// Only end the token after both create/begin have completed, and return
// a Future to indicate that has happened to callers know when it's safe
// to re-use the token identifier.
- if (_tokenBeginRequest != null) {
- final didBegin = await _tokenBeginRequest;
+ final beginRequest = _tokenBeginRequest;
+ if (beginRequest != null) {
+ final didBegin = await beginRequest;
if (didBegin) {
super.end(message);
}
@@ -109,14 +108,14 @@
_TokenProgressReporter(this._server, this._token) : super._();
@override
- void begin(String title, {String message}) {
+ void begin(String? title, {String? message}) {
_needsEnd = true;
_sendNotification(
WorkDoneProgressBegin(title: title ?? 'Working…', message: message));
}
@override
- void end([String message]) {
+ void end([String? message]) {
if (!_needsEnd) return;
_needsEnd = false;
_sendNotification(WorkDoneProgressEnd(message: message));
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index ad0241d..65af61f 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/client_capabilities.dart';
@@ -133,9 +131,7 @@
ServerCapabilities computeServerCapabilities(
LspClientCapabilities clientCapabilities) {
final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
-
final renameOptionsSupport = clientCapabilities.renameValidation;
-
final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
final previewCommitCharacters =
_server.clientConfiguration.previewCommitCharacters;
@@ -204,7 +200,7 @@
// `textDocument.codeAction.codeActionLiteralSupport`."
codeActionProvider: dynamicRegistrations.codeActions
? null
- : codeActionLiteralSupport != null
+ : codeActionLiteralSupport
? Either2<bool, CodeActionOptions>.t2(CodeActionOptions(
codeActionKinds: DartCodeActionKind.serverSupportedKinds,
))
@@ -322,17 +318,17 @@
_server.clientConfiguration.previewCommitCharacters;
/// Helper for creating registrations with IDs.
- void register(bool condition, Method method, [ToJsonable options]) {
+ void register(bool condition, Method method, [ToJsonable? options]) {
if (condition == true) {
registrations.add(Registration(
id: (_lastRegistrationId++).toString(),
- method: method.toJson(),
+ method: method.toString(),
registerOptions: options));
}
}
final dynamicRegistrations =
- ClientDynamicRegistrations(_server.clientCapabilities.raw);
+ ClientDynamicRegistrations(_server.clientCapabilities!.raw);
register(
dynamicRegistrations.textSync,
@@ -524,11 +520,12 @@
RegistrationParams(registrations: registrationsToAdd),
);
- if (registrationResponse.error != null) {
+ final error = registrationResponse.error;
+ if (error != null) {
_server.logErrorToClient(
'Failed to register capabilities with client: '
- '(${registrationResponse.error.code}) '
- '${registrationResponse.error.message}',
+ '(${error.code}) '
+ '${error.message}',
);
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index f4975617..cb8fe6f 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
@@ -12,6 +10,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -71,17 +70,17 @@
},
);
// If any change fails, immediately return the error.
- if (result?.isError ?? false) {
+ if (result != null && result.isError) {
return ErrorOr.error(result.error);
}
}
return ErrorOr.success(Pair(newContent, serverEdits));
}
-ErrorOr<List<TextEdit>> generateEditsForFormatting(
+ErrorOr<List<TextEdit>?> generateEditsForFormatting(
ParsedUnitResult result,
int lineLength, {
- Range range,
+ Range? range,
}) {
final unformattedSource = result.content;
@@ -112,7 +111,8 @@
List<TextEdit> _generateFullEdit(
LineInfo lineInfo, String unformattedSource, String formattedSource) {
- final end = lineInfo.getLocation(unformattedSource.length);
+ final end =
+ lineInfo.getLocation(unformattedSource.length) as CharacterLocation;
return [
TextEdit(
range:
@@ -133,17 +133,17 @@
ErrorOr<List<TextEdit>> _generateMinimalEdits(
ParsedUnitResult result,
String formatted, {
- Range range,
+ Range? range,
}) {
final unformatted = result.content;
final lineInfo = result.lineInfo;
final rangeStart = range != null ? toOffset(lineInfo, range.start) : null;
final rangeEnd = range != null ? toOffset(lineInfo, range.end) : null;
- if (rangeStart?.isError ?? false) {
+ if (rangeStart != null && rangeStart.isError) {
return failure(rangeStart);
}
- if (rangeEnd?.isError ?? false) {
+ if (rangeEnd != null && rangeEnd.isError) {
return failure(rangeEnd);
}
@@ -217,8 +217,9 @@
// edits in the same set.
edits.add(TextEdit(
range: Range(
- start: toPosition(lineInfo.getLocation(startOffset)),
- end: toPosition(lineInfo.getLocation(endOffset)),
+ start:
+ toPosition(lineInfo.getLocation(startOffset) as CharacterLocation),
+ end: toPosition(lineInfo.getLocation(endOffset) as CharacterLocation),
),
newText: newText,
));
@@ -276,21 +277,22 @@
/// Iterates over a token stream returning all tokens including comments.
Iterable<Token> _iterateAllTokens(Token token) sync* {
while (token.type != TokenType.EOF) {
- var commentToken = token.precedingComments;
+ Token? commentToken = token.precedingComments;
while (commentToken != null) {
yield commentToken;
commentToken = commentToken.next;
}
yield token;
- token = token.next;
+ token = token.next!;
}
}
/// Parse and return the first of the given Dart source, `null` if code cannot
/// be parsed.
-Token _parse(String s, FeatureSet featureSet) {
+Token? _parse(String s, FeatureSet featureSet) {
try {
- var scanner = Scanner(null, CharSequenceReader(s), null)
+ var scanner = Scanner(_SourceMock.instance, CharSequenceReader(s),
+ AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
@@ -310,11 +312,18 @@
final bool newFile;
/// The selection offset, relative to the edit.
- final int selectionOffsetRelative;
- final int selectionLength;
+ final int? selectionOffsetRelative;
+ final int? selectionLength;
FileEditInformation(this.doc, this.lineInfo, this.edits,
{this.newFile = false,
this.selectionOffsetRelative,
this.selectionLength});
}
+
+class _SourceMock implements Source {
+ static final Source instance = _SourceMock();
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index be6d158..05538df 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -17,9 +17,6 @@
Future<void> scheduleImplementedNotification(
AnalysisServer server, Iterable<String> files) async {
var searchEngine = server.searchEngine;
- if (searchEngine == null) {
- return;
- }
for (var file in files) {
var unit = server.getCachedResolvedUnit(file)?.unit;
var unitElement = unit?.declaredElement;
diff --git a/pkg/analysis_server/lib/src/server/dev_server.dart b/pkg/analysis_server/lib/src/server/dev_server.dart
index f15d228..62886da6 100644
--- a/pkg/analysis_server/lib/src/server/dev_server.dart
+++ b/pkg/analysis_server/lib/src/server/dev_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'dart:io';
@@ -26,7 +24,7 @@
final SocketServer socketServer;
int _nextId = 0;
- DevChannel _channel;
+ late DevChannel _channel;
/// Initialize a newly created stdio server.
DevAnalysisServer(this.socketServer);
@@ -53,9 +51,10 @@
var exitCode = 0;
void handleStatusNotification(Notification notification) {
- Map<String, dynamic> params = notification.params;
- if (params.containsKey('analysis')) {
- bool isAnalyzing = params['analysis']['isAnalyzing'];
+ var params = notification.params;
+ if (params != null && params.containsKey('analysis')) {
+ var isAnalyzing =
+ (params['analysis'] as Map<String, Object>)['isAnalyzing'] as bool;
if (!isAnalyzing) {
timer.stop();
var seconds = timer.elapsedMilliseconds / 1000.0;
@@ -66,8 +65,9 @@
}
void handleErrorsNotification(Notification notification) {
- String filePath = notification.params['file'];
- List<Map> errors = notification.params['errors'];
+ var params = notification.params!;
+ var filePath = params['file'] as String;
+ var errors = params['errors'] as List<Map>;
if (errors.isEmpty) {
return;
@@ -101,9 +101,9 @@
}
void handleServerError(Notification notification) {
- Map<String, dynamic> params = notification.params;
- String message = params['message'];
- String stackTrace = params['stackTrace'];
+ var params = notification.params!;
+ var message = params['message'] as String;
+ var stackTrace = params['stackTrace'] as String?;
print(message);
if (stackTrace != null) {
@@ -172,8 +172,8 @@
@override
void listen(
void Function(Request request) onRequest, {
- Function onError,
- void Function() onDone,
+ Function? onError,
+ void Function()? onDone,
}) {
_requestController.stream.listen(
onRequest,
diff --git a/pkg/analysis_server/lib/src/server/isolate_analysis_server.dart b/pkg/analysis_server/lib/src/server/isolate_analysis_server.dart
index aaf2ae3..2ef30d3 100644
--- a/pkg/analysis_server/lib/src/server/isolate_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/server/isolate_analysis_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io' show IOSink;
import 'dart:isolate';
diff --git a/pkg/analysis_server/lib/src/server/stdio_server.dart b/pkg/analysis_server/lib/src/server/stdio_server.dart
index 337436e..06c5030 100644
--- a/pkg/analysis_server/lib/src/server/stdio_server.dart
+++ b/pkg/analysis_server/lib/src/server/stdio_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
import 'package:analysis_server/src/channel/byte_stream_channel.dart';
diff --git a/pkg/analysis_server/lib/src/socket_server.dart b/pkg/analysis_server/lib/src/socket_server.dart
index df0d3e2..59cafe6 100644
--- a/pkg/analysis_server/lib/src/socket_server.dart
+++ b/pkg/analysis_server/lib/src/socket_server.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
@@ -18,11 +16,11 @@
import 'package:analyzer/src/generated/sdk.dart';
abstract class AbstractSocketServer {
- AbstractAnalysisServer get analysisServer;
+ AbstractAnalysisServer? get analysisServer;
AnalysisServerOptions get analysisServerOptions;
- DiagnosticServer get diagnosticServer;
+ DiagnosticServer? get diagnosticServer;
}
/// Instances of the class [SocketServer] implement the common parts of
@@ -38,15 +36,15 @@
final CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder;
final InstrumentationService instrumentationService;
- final RequestStatisticsHelper requestStatistics;
+ final RequestStatisticsHelper? requestStatistics;
@override
- final DiagnosticServer diagnosticServer;
- final DetachableFileSystemManager detachableFileSystemManager;
+ final DiagnosticServer? diagnosticServer;
+ final DetachableFileSystemManager? detachableFileSystemManager;
/// The analysis server that was created when a client established a
/// connection, or `null` if no such connection has yet been established.
@override
- AnalysisServer analysisServer;
+ AnalysisServer? analysisServer;
SocketServer(
this.analysisServerOptions,
@@ -73,7 +71,7 @@
var resourceProvider = PhysicalResourceProvider(
stateLocation: analysisServerOptions.cacheFolder);
- analysisServer = AnalysisServer(
+ var server = analysisServer = AnalysisServer(
serverChannel,
resourceProvider,
analysisServerOptions,
@@ -85,6 +83,6 @@
detachableFileSystemManager: detachableFileSystemManager,
enableBazelWatcher: true,
);
- detachableFileSystemManager?.setAnalysisServer(analysisServer);
+ detachableFileSystemManager?.setAnalysisServer(server);
}
}
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index b7877f9..53d4588 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -40,15 +38,14 @@
channel2.expectMsgCount(responseCount: 1);
expect(channel2.responsesReceived[0].id, equals(''));
expect(channel2.responsesReceived[0].error, isNotNull);
- expect(channel2.responsesReceived[0].error.code,
+ expect(channel2.responsesReceived[0].error!.code,
equals(RequestErrorCode.SERVER_ALREADY_STARTED));
channel2
.sendRequest(ServerShutdownParams().toRequest('0'))
.then((Response response) {
expect(response.id, equals('0'));
- expect(response.error, isNotNull);
- expect(
- response.error.code, equals(RequestErrorCode.SERVER_ALREADY_STARTED));
+ var error = response.error!;
+ expect(error.code, equals(RequestErrorCode.SERVER_ALREADY_STARTED));
channel2.expectMsgCount(responseCount: 2);
});
}
@@ -75,15 +72,15 @@
expect(
channel.notificationsReceived[0].event, SERVER_NOTIFICATION_CONNECTED);
var handler = _MockRequestHandler(false);
- server.analysisServer.handlers = [handler];
+ server.analysisServer!.handlers = [handler];
var request = ServerGetVersionParams().toRequest('0');
return channel.sendRequest(request).then((Response response) {
expect(response.id, equals('0'));
- expect(response.error, isNotNull);
- expect(response.error.code, equals(RequestErrorCode.SERVER_ERROR));
- expect(response.error.message, equals('mock request exception'));
- expect(response.error.stackTrace, isNotNull);
- expect(response.error.stackTrace, isNotEmpty);
+ var error = response.error!;
+ expect(error.code, equals(RequestErrorCode.SERVER_ERROR));
+ expect(error.message, equals('mock request exception'));
+ expect(error.stackTrace, isNotNull);
+ expect(error.stackTrace, isNotEmpty);
channel.expectMsgCount(responseCount: 1, notificationCount: 1);
});
}
@@ -92,7 +89,7 @@
var channel = MockServerChannel();
var server = _createSocketServer(channel);
var handler = _MockRequestHandler(true);
- server.analysisServer.handlers = [handler];
+ server.analysisServer!.handlers = [handler];
var request = ServerGetVersionParams().toRequest('0');
var response = await channel.sendRequest(request, throwOnError: false);
expect(response.id, equals('0'));
@@ -113,7 +110,7 @@
null);
server.createAnalysisServer(channel);
- errorNotifier.server = server.analysisServer;
+ errorNotifier.server = server.analysisServer!;
AnalysisEngine.instance.instrumentationService = errorNotifier;
return server;
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index 68c29f7..c134d20 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -133,7 +133,7 @@
}
bool _isSimpleType(TypeBase type) {
- const literals = ['num', 'String', 'bool'];
+ const literals = ['num', 'String', 'bool', 'int'];
return type is Type && literals.contains(type.dartType);
}
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 1cd4b7b..81f8eb0 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -202,7 +202,7 @@
}
final customTypes = <AstNode>[
- interface('DartDiagnosticServer', [field('port', type: 'number')]),
+ interface('DartDiagnosticServer', [field('port', type: 'int')]),
interface('AnalyzerStatusParams', [field('isAnalyzing', type: 'boolean')]),
interface('PublishClosingLabelsParams', [
field('uri', type: 'string'),
@@ -255,7 +255,7 @@
'CompletionItemResolutionInfo',
[
field('file', type: 'string'),
- field('offset', type: 'number'),
+ field('offset', type: 'int'),
],
),
interface(
@@ -263,11 +263,11 @@
[
// These fields have short-ish names because they're on the payload
// for all suggestion-set backed completions.
- field('libId', type: 'number'),
+ field('libId', type: 'int'),
field('displayUri', type: 'string'),
- field('rOffset', type: 'number'), // replacementOffset
- field('iLength', type: 'number'), // insertLength
- field('rLength', type: 'number'), // replacementLength
+ field('rOffset', type: 'int'), // replacementOffset
+ field('iLength', type: 'int'), // insertLength
+ field('rLength', type: 'int'), // replacementLength
],
baseType: 'CompletionItemResolutionInfo',
),
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 5ebb88d..7d36548 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -118,6 +118,10 @@
'ParameterInformation': {
'label': 'String',
},
+ 'Position': {
+ 'character': 'int',
+ 'line': 'int',
+ },
'ProgressParams': {
'value': 'object',
},
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 9dc61e0..5c9065e 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -46,7 +46,7 @@
final typeName = tokenType == TokenType.STRING
? 'string'
: tokenType == TokenType.NUMBER
- ? 'number'
+ ? 'int' // all literal numeric values in LSP spec are ints
: throw 'Unknown literal type $tokenType';
return Type.identifier(typeName);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index cc7a05d..80b996d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -182,7 +182,7 @@
isExpired: IsExpired.triple_shift,
documentation: 'Triple-shift operator',
experimentalReleaseVersion: null,
- releaseVersion: null,
+ releaseVersion: Version.parse('2.14.0'),
);
static final value_class = ExperimentalFeature(
@@ -240,7 +240,7 @@
static const bool spread_collections = true;
/// Default state of the experiment "triple-shift"
- static const bool triple_shift = false;
+ static const bool triple_shift = true;
/// Default state of the experiment "value-class"
static const bool value_class = false;
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 55feba8..c15e091 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -8,8 +8,10 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
+import 'package:collection/collection.dart';
import 'package:meta/meta.dart';
Element? declaredParameterElement(
@@ -606,7 +608,7 @@
@override
void visitConstructorName(ConstructorName node) {
- ConstructorElement? element = node.staticElement;
+ var element = node.staticElement?.declaration;
element = _getActualConstructorElement(element);
// record relation
if (node.name != null) {
@@ -907,10 +909,18 @@
ConstructorElement? _getActualConstructorElement(
ConstructorElement? constructor) {
var seenConstructors = <ConstructorElement?>{};
- while (constructor != null &&
- constructor.isSynthetic &&
- constructor.redirectedConstructor != null) {
- constructor = constructor.redirectedConstructor;
+ while (constructor is ConstructorElementImpl && constructor.isSynthetic) {
+ var enclosing = constructor.enclosingElement;
+ if (enclosing is ClassElement && enclosing.isMixinApplication) {
+ var superInvocation = constructor.constantInitializers
+ .whereType<SuperConstructorInvocation>()
+ .singleOrNull;
+ if (superInvocation != null) {
+ constructor = superInvocation.staticElement;
+ }
+ } else {
+ break;
+ }
// fail if a cycle is detected
if (!seenConstructors.add(constructor)) {
return null;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index a656852..9a69609 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -17,7 +17,9 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/constant/compute.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/value.dart';
@@ -41,6 +43,7 @@
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:analyzer/src/summary2/ast_binary_tokens.dart';
import 'package:analyzer/src/summary2/linked_unit_context.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
@@ -963,22 +966,22 @@
implicitConstructor.isSynthetic = true;
implicitConstructor.name = name;
implicitConstructor.nameOffset = -1;
- implicitConstructor._constantInitializers = const [];
- implicitConstructor.redirectedConstructor = superclassConstructor;
var hasMixinWithInstanceVariables = mixins.any(typeHasInstanceVariables);
implicitConstructor.isConst =
superclassConstructor.isConst && !hasMixinWithInstanceVariables;
List<ParameterElement> superParameters = superclassConstructor.parameters;
int count = superParameters.length;
+ var argumentsForSuperInvocation = <Expression>[];
if (count > 0) {
var implicitParameters = <ParameterElement>[];
for (int i = 0; i < count; i++) {
ParameterElement superParameter = superParameters[i];
ParameterElementImpl implicitParameter;
- if (superParameter is DefaultParameterElementImpl) {
+ if (superParameter is ConstVariableElement) {
+ var constVariable = superParameter as ConstVariableElement;
implicitParameter =
DefaultParameterElementImpl(superParameter.name, -1)
- ..constantInitializer = superParameter.constantInitializer;
+ ..constantInitializer = constVariable.constantInitializer;
} else {
implicitParameter = ParameterElementImpl(superParameter.name, -1);
}
@@ -990,10 +993,36 @@
implicitParameter.type =
substitution.substituteType(superParameter.type);
implicitParameters.add(implicitParameter);
+ argumentsForSuperInvocation.add(
+ astFactory.simpleIdentifier(
+ StringToken(TokenType.STRING, implicitParameter.name, -1),
+ )
+ ..staticElement = implicitParameter
+ ..staticType = implicitParameter.type,
+ );
}
implicitConstructor.parameters = implicitParameters;
}
implicitConstructor.enclosingElement = this;
+
+ var isNamed = superclassConstructor.name.isNotEmpty;
+ implicitConstructor.constantInitializers = [
+ astFactory.superConstructorInvocation(
+ Tokens.SUPER,
+ isNamed ? Tokens.PERIOD : null,
+ isNamed
+ ? (astFactory.simpleIdentifier(
+ StringToken(TokenType.STRING, superclassConstructor.name, -1),
+ )..staticElement = superclassConstructor)
+ : null,
+ astFactory.argumentList(
+ Tokens.OPEN_PAREN,
+ argumentsForSuperInvocation,
+ Tokens.CLOSE_PAREN,
+ ),
+ )..staticElement = superclassConstructor,
+ ];
+
return implicitConstructor;
}).toList(growable: false);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index 75eaf41..39c6c92 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -767,6 +767,90 @@
);
}
+ test_value_genericMixinApplication_inference_unnamedConstructor() async {
+ await assertNoErrorsInCode(r'''
+ class A<T> {
+ final T f;
+ const A(this.f);
+}
+
+mixin M {}
+
+class B<T> = A<T> with M;
+
+@B(42)
+void f() {}
+''');
+
+ var annotation = findNode.annotation('@B');
+ _assertResolvedNodeText(annotation, r'''
+Annotation
+ arguments: ArgumentList
+ arguments
+ IntegerLiteral
+ literal: 42
+ staticType: int
+ element: ConstructorMember
+ base: self::@class::B::@constructor::•
+ substitution: {T: int}
+ name: SimpleIdentifier
+ staticElement: self::@class::B
+ staticType: null
+ token: B
+''');
+ _assertAnnotationValueText(annotation, r'''
+B<int>
+ (super): A<int>
+ f: int 42
+''');
+ }
+
+ test_value_genericMixinApplication_typeArguments_unnamedConstructor() async {
+ await assertNoErrorsInCode(r'''
+ class A<T> {
+ final T f;
+ const A(this.f);
+}
+
+mixin M {}
+
+class B<T> = A<T> with M;
+
+@B<int>(42)
+void f() {}
+''');
+
+ var annotation = findNode.annotation('@B');
+ _assertResolvedNodeText(annotation, r'''
+Annotation
+ arguments: ArgumentList
+ arguments
+ IntegerLiteral
+ literal: 42
+ staticType: int
+ element: ConstructorMember
+ base: self::@class::B::@constructor::•
+ substitution: {T: int}
+ name: SimpleIdentifier
+ staticElement: self::@class::B
+ staticType: null
+ token: B
+ typeArguments: TypeArgumentList
+ arguments
+ TypeName
+ name: SimpleIdentifier
+ staticElement: dart:core::@class::int
+ staticType: null
+ token: int
+ type: int
+''');
+ _assertAnnotationValueText(annotation, r'''
+B<int>
+ (super): A<int>
+ f: int 42
+''');
+ }
+
test_value_otherLibrary_implicitConst() async {
newFile('$testPackageLibPath/a.dart', content: r'''
class A {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index e8bce34..cc3104a 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -19,16 +19,25 @@
import 'package:analyzer/src/summary2/reference.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'element_text.dart';
import 'resynthesize_common.dart';
import 'test_strategies.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ResynthesizeAst2Test);
+ // defineReflectiveTests(ApplyCheckElementTextReplacements);
});
}
@reflectiveTest
+class ApplyCheckElementTextReplacements {
+ test_applyReplacements() {
+ applyCheckElementTextReplacements();
+ }
+}
+
+@reflectiveTest
class ResynthesizeAst2Test extends AbstractResynthesizeTest
with ResynthesizeTestCases {
/// The shared SDK bundle, computed once and shared among test invocations.
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 7403527..3ef5b4d 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -123,7 +123,7 @@
''');
checkElementText(library, r'''
class alias C extends D with E, F, G {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -144,7 +144,7 @@
''');
checkElementText(library, r'''
abstract class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -168,7 +168,7 @@
* Docs
*/
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -192,7 +192,7 @@
/// b
/// cc
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -216,7 +216,7 @@
* Docs
*/
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -234,7 +234,7 @@
''');
checkElementText(library, r'''
class alias Z extends A with B<int>, C<double> {
- synthetic Z() = A;
+ synthetic Z() : super();
}
class A {
}
@@ -253,7 +253,7 @@
''');
checkElementText(library, r'''
notSimplyBounded class alias C<T extends C<dynamic>> extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -272,7 +272,7 @@
''');
checkElementText(library, r'''
class alias C<T> extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -291,7 +291,7 @@
''');
checkElementText(library, r'''
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -313,26 +313,44 @@
class M {}
class MixinApp = Base with M;
''');
- checkElementText(library, r'''
+ checkElementText(
+ library,
+ r'''
import 'a.dart';
class M {
}
class alias MixinApp extends Base with M {
- synthetic const MixinApp() = Base;
- synthetic const MixinApp.named() = Base.named;
+ synthetic const MixinApp();
+ constantInitializers
+ SuperConstructorInvocation
+ argumentList: ArgumentList
+ staticElement: file:///a.dart::@class::Base::@constructor::•
+ synthetic const MixinApp.named();
+ constantInitializers
+ SuperConstructorInvocation
+ argumentList: ArgumentList
+ constructorName: SimpleIdentifier
+ staticElement: file:///a.dart::@class::Base::@constructor::named
+ staticType: null
+ token: named
+ staticElement: file:///a.dart::@class::Base::@constructor::named
}
-''');
+''',
+ withFullyResolvedAst: true);
}
test_class_alias_with_forwarding_constructors() async {
addLibrarySource('/a.dart', '''
class Base {
+ bool x = true;
Base._priv();
Base();
Base.noArgs();
Base.requiredArg(x);
Base.positionalArg([bool x = true]);
+ Base.positionalArg2([this.x = true]);
Base.namedArg({int x = 42});
+ Base.namedArg2({this.x = true});
factory Base.fact() => Base();
factory Base.fact2() = Base.noArgs;
}
@@ -347,11 +365,24 @@
class M {
}
class alias MixinApp extends Base with M {
- synthetic MixinApp() = Base;
- synthetic MixinApp.noArgs() = Base.noArgs;
- synthetic MixinApp.requiredArg(dynamic x) = Base.requiredArg;
- synthetic MixinApp.positionalArg([bool x = true]) = Base.positionalArg;
- synthetic MixinApp.namedArg({int x: 42}) = Base.namedArg;
+ synthetic MixinApp() : super();
+ synthetic MixinApp.noArgs() : super.
+ noArgs/*location: a.dart;Base;noArgs*/();
+ synthetic MixinApp.requiredArg(dynamic x) : super.
+ requiredArg/*location: a.dart;Base;requiredArg*/(
+ x/*location: test.dart;MixinApp;requiredArg;x*/);
+ synthetic MixinApp.positionalArg([bool x = true]) : super.
+ positionalArg/*location: a.dart;Base;positionalArg*/(
+ x/*location: test.dart;MixinApp;positionalArg;x*/);
+ synthetic MixinApp.positionalArg2([bool x = true]) : super.
+ positionalArg2/*location: a.dart;Base;positionalArg2*/(
+ x/*location: test.dart;MixinApp;positionalArg2;x*/);
+ synthetic MixinApp.namedArg({int x: 42}) : super.
+ namedArg/*location: a.dart;Base;namedArg*/(
+ x/*location: test.dart;MixinApp;namedArg;x*/);
+ synthetic MixinApp.namedArg2({bool x: true}) : super.
+ namedArg2/*location: a.dart;Base;namedArg2*/(
+ x/*location: test.dart;MixinApp;namedArg2;x*/);
}
''');
}
@@ -371,7 +402,10 @@
class M {
}
class alias MixinApp extends Base<dynamic> with M {
- synthetic MixinApp.ctor(dynamic t, List<dynamic> l) = Base<T>.ctor;
+ synthetic MixinApp.ctor(dynamic t, List<dynamic> l) : super.
+ ctor/*location: test.dart;Base;ctor*/(
+ t/*location: test.dart;MixinApp;ctor;t*/,
+ l/*location: test.dart;MixinApp;ctor;l*/);
}
''');
}
@@ -391,7 +425,10 @@
class M {
}
class alias MixinApp<U> extends Base<List<U>> with M {
- synthetic MixinApp.ctor(List<U> t, List<List<U>> l) = Base<T>.ctor;
+ synthetic MixinApp.ctor(List<U> t, List<List<U>> l) : super.
+ ctor/*location: test.dart;Base;ctor*/(
+ t/*location: test.dart;MixinApp;ctor;t*/,
+ l/*location: test.dart;MixinApp;ctor;l*/);
}
''');
}
@@ -408,7 +445,7 @@
}''');
checkElementText(library, r'''
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -2155,33 +2192,33 @@
class B/*codeOffset=12, codeLength=10*/ {
}
class alias Raw/*codeOffset=28, codeLength=29*/ extends Object with A, B {
- synthetic const Raw() = Object;
+ synthetic const Raw() : super();
}
/// Comment 1.
/// Comment 2.
class alias HasDocComment/*codeOffset=59, codeLength=69*/ extends Object with A, B {
- synthetic const HasDocComment() = Object;
+ synthetic const HasDocComment() : super();
}
@Object()
class alias HasAnnotation/*codeOffset=130, codeLength=49*/ extends Object with A, B {
- synthetic const HasAnnotation() = Object;
+ synthetic const HasAnnotation() : super();
}
/// Comment 1.
/// Comment 2.
@Object()
class alias AnnotationThenComment/*codeOffset=181, codeLength=87*/ extends Object with A, B {
- synthetic const AnnotationThenComment() = Object;
+ synthetic const AnnotationThenComment() : super();
}
/// Comment 1.
/// Comment 2.
@Object()
class alias CommentThenAnnotation/*codeOffset=270, codeLength=87*/ extends Object with A, B {
- synthetic const CommentThenAnnotation() = Object;
+ synthetic const CommentThenAnnotation() : super();
}
/// Comment 2.
@Object()
class alias CommentAroundAnnotation/*codeOffset=374, codeLength=74*/ extends Object with A, B {
- synthetic const CommentAroundAnnotation() = Object;
+ synthetic const CommentAroundAnnotation() : super();
}
''',
withCodeRanges: true,
@@ -6162,10 +6199,10 @@
class B {
}
class alias X extends A with M {
- synthetic X() = A;
+ synthetic X() : super();
}
class alias X extends B with M {
- synthetic X() = B;
+ synthetic X() : super();
}
mixin M on Object {
}
@@ -6438,7 +6475,7 @@
dynamic foo() {}
}
class alias D extends Object with M {
- synthetic const D() = Object;
+ synthetic const D() : super();
}
''');
}
@@ -9481,7 +9518,7 @@
await checkLibrary('class main = C with D; class C {} class D {}');
checkElementText(library, r'''
class alias main extends C with D {
- synthetic main() = C;
+ synthetic main() : super();
}
class C {
}
@@ -9678,7 +9715,7 @@
@
a/*location: test.dart;a?*/
class alias C extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
@@ -10052,7 +10089,15 @@
const A.named();
}
class alias C extends A with B {
- synthetic const C.named() = A.named;
+ synthetic const C.named();
+ constantInitializers
+ SuperConstructorInvocation
+ argumentList: ArgumentList
+ constructorName: SimpleIdentifier
+ staticElement: self::@class::A::@constructor::named
+ staticType: null
+ token: named
+ staticElement: self::@class::A::@constructor::named
}
typeParameters
T
@@ -10354,7 +10399,11 @@
const A();
}
class alias C extends A with B {
- synthetic const C() = A;
+ synthetic const C();
+ constantInitializers
+ SuperConstructorInvocation
+ argumentList: ArgumentList
+ staticElement: self::@class::A::@constructor::•
}
typeParameters
T
@@ -11076,7 +11125,7 @@
class alias C<@
a/*location: test.dart;a?*/
T> extends D with E {
- synthetic C() = D;
+ synthetic C() : super();
}
class D {
}
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
index a6d1deb..3e51b53 100644
--- a/pkg/dart2native/lib/dart2native.dart
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -5,7 +5,9 @@
import 'dart:io';
import 'dart:typed_data';
-const appSnapshotPageSize = 4096;
+// Maximum page size across all supported architectures (arm64 macOS has 16K
+// pages, the rest are all 4k pages).
+const elfPageSize = 16384;
const appjitMagicNumber = <int>[0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0];
enum Kind { aot, exe }
@@ -15,8 +17,7 @@
final dartaotruntime = File(dartaotruntimePath);
final int dartaotruntimeLength = dartaotruntime.lengthSync();
- final padding =
- ((appSnapshotPageSize - dartaotruntimeLength) % appSnapshotPageSize);
+ final padding = ((elfPageSize - dartaotruntimeLength) % elfPageSize);
final padBytes = Uint8List(padding);
final offset = dartaotruntimeLength + padding;
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 759b8fb..af04e106 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -90,7 +90,7 @@
ExperimentalFlag.nonfunctionTypeAliases: true,
ExperimentalFlag.setLiterals: true,
ExperimentalFlag.spreadCollections: true,
- ExperimentalFlag.tripleShift: false,
+ ExperimentalFlag.tripleShift: true,
ExperimentalFlag.valueClass: false,
ExperimentalFlag.variance: false,
};
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.expect
index d856926..376dfb4 100644
--- a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.expect
@@ -1,19 +1,11 @@
library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:40: Error: Constant evaluation error:
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:47: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '">>>"'.
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:14: Context: While analyzing:
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-//
import self as self;
import "dart:core" as core;
+import "dart:_internal" as _in;
-static const field core::Symbol* tripleShiftSymbol = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\">>>\"'.";
+static const field core::Symbol* tripleShiftSymbol = #C1;
static method main() → dynamic {}
+
+constants {
+ #C1 = #>>>
+}
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.outline.expect
index e41cc76..9194ec0 100644
--- a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.outline.expect
@@ -6,3 +6,8 @@
static const field core::Symbol* tripleShiftSymbol = const _in::Symbol::•(">>>");
static method main() → dynamic
;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:5:40 -> SymbolConstant(#>>>)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.transformed.expect
index d856926..376dfb4 100644
--- a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.weak.transformed.expect
@@ -1,19 +1,11 @@
library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:40: Error: Constant evaluation error:
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:47: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '">>>"'.
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:14: Context: While analyzing:
-// const Symbol tripleShiftSymbol = const Symbol(">>>");
-// ^
-//
import self as self;
import "dart:core" as core;
+import "dart:_internal" as _in;
-static const field core::Symbol* tripleShiftSymbol = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\">>>\"'.";
+static const field core::Symbol* tripleShiftSymbol = #C1;
static method main() → dynamic {}
+
+constants {
+ #C1 = #>>>
+}
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index 11abcb0..0520b9d 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -135,7 +135,13 @@
stripPrefix = "externally stripped ";
}
- Expect.approxEquals(expected, actual, 0.03 * actual,
+ // See Elf::kPages in runtime/vm/elf.h.
+ final segmentAlignment = 16384;
+ // Not every byte is accounted for by the snapshot profile, and data and
+ // instruction segments are padded to an alignment boundary.
+ final tolerance = 0.03 * actual + 2 * segmentAlignment;
+
+ Expect.approxEquals(expected, actual, tolerance,
"failed on $bareUsed $stripPrefix$fileType snapshot type.");
});
}
diff --git a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
index 8778573..3d88b62 100644
--- a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
@@ -135,7 +135,13 @@
stripPrefix = "externally stripped ";
}
- Expect.approxEquals(expected, actual, 0.03 * actual,
+ // See Elf::kPages in runtime/vm/elf.h.
+ final segmentAlignment = 16384;
+ // Not every byte is accounted for by the snapshot profile, and data and
+ // instruction segments are padded to an alignment boundary.
+ final tolerance = 0.03 * actual + 2 * segmentAlignment;
+
+ Expect.approxEquals(expected, actual, tolerance,
"failed on $bareUsed $stripPrefix$fileType snapshot type.");
});
}
diff --git a/runtime/third_party/binary_size/src/elf_symbolizer.py b/runtime/third_party/binary_size/src/elf_symbolizer.py
index 86a0a07..5154a9b 100644
--- a/runtime/third_party/binary_size/src/elf_symbolizer.py
+++ b/runtime/third_party/binary_size/src/elf_symbolizer.py
@@ -8,7 +8,7 @@
import multiprocessing
import os
import posixpath
-import Queue
+import queue
import re
import subprocess
import sys
@@ -241,7 +241,7 @@
# Objects required to handle the addr2line subprocess.
self._proc = None # Subprocess.Popen(...) instance.
self._thread = None # Threading.thread instance.
- self._out_queue = None # Queue.Queue instance (for buffering a2l stdout).
+ self._out_queue = None # queue.Queue instance (for buffering a2l stdout).
self._RestartAddr2LineProcess()
def EnqueueRequest(self, addr, callback_arg):
@@ -282,7 +282,7 @@
try:
lines = self._out_queue.get(block=True, timeout=0.25)
- except Queue.Empty:
+ except queue.Empty:
# On timeout (1/4 s.) repeat the inner loop and check if either the
# addr2line process did crash or we waited its output for too long.
continue
@@ -303,7 +303,7 @@
while True:
try:
lines = self._out_queue.get_nowait()
- except Queue.Empty:
+ except queue.Empty:
break
self._ProcessSymbolOutput(lines)
@@ -328,7 +328,7 @@
self._proc = None
def _WriteToA2lStdin(self, addr):
- self._proc.stdin.write('%s\n' % hex(addr))
+ self._proc.stdin.write(('%s\n' % hex(addr)).encode())
if self._symbolizer.inlines:
# In the case of inlines we output an extra blank line, which causes
# addr2line to emit a (??,??:0) tuple that we use as a boundary marker.
@@ -396,7 +396,7 @@
# The only reason of existence of this Queue (and the corresponding
# Thread below) is the lack of a subprocess.stdout.poll_avail_lines().
# Essentially this is a pipe able to extract a couple of lines atomically.
- self._out_queue = Queue.Queue()
+ self._out_queue = queue.Queue()
# Start the underlying addr2line process in line buffered mode.
@@ -408,7 +408,6 @@
cmd += ['--inlines']
self._proc = subprocess.Popen(
cmd,
- bufsize=1,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=sys.stderr,
@@ -442,8 +441,8 @@
try:
lines_for_one_symbol = []
while True:
- line1 = process_pipe.readline().rstrip('\r\n')
- line2 = process_pipe.readline().rstrip('\r\n')
+ line1 = process_pipe.readline().decode().rstrip('\r\n')
+ line2 = process_pipe.readline().decode().rstrip('\r\n')
if not line1 or not line2:
break
inline_has_more_lines = inlines and (
diff --git a/runtime/third_party/binary_size/src/run_binary_size_analysis.py b/runtime/third_party/binary_size/src/run_binary_size_analysis.py
index ac41f4a..dfd5b97 100755
--- a/runtime/third_party/binary_size/src/run_binary_size_analysis.py
+++ b/runtime/third_party/binary_size/src/run_binary_size_analysis.py
@@ -60,16 +60,16 @@
no_path_bucket = root_children[NAME_NO_PATH_BUCKET]
old_children = no_path_bucket[NODE_CHILDREN_KEY]
count = 0
- for symbol_type, symbol_bucket in old_children.iteritems():
+ for symbol_type, symbol_bucket in old_children.items():
count += len(symbol_bucket[NODE_CHILDREN_KEY])
if count > BIG_BUCKET_LIMIT:
new_children = {}
no_path_bucket[NODE_CHILDREN_KEY] = new_children
current_bucket = None
index = 0
- for symbol_type, symbol_bucket in old_children.iteritems():
+ for symbol_type, symbol_bucket in old_children.items():
for symbol_name, value in symbol_bucket[
- NODE_CHILDREN_KEY].iteritems():
+ NODE_CHILDREN_KEY].items():
if index % BIG_BUCKET_LIMIT == 0:
group_no = (index / BIG_BUCKET_LIMIT) + 1
current_bucket = _MkChild(
@@ -89,7 +89,7 @@
if NODE_CHILDREN_KEY in node:
largest_list_len = len(node[NODE_CHILDREN_KEY])
child_list = []
- for child in node[NODE_CHILDREN_KEY].itervalues():
+ for child in node[NODE_CHILDREN_KEY].values():
child_largest_list_len = MakeChildrenDictsIntoLists(child)
if child_largest_list_len > largest_list_len:
largest_list_len = child_largest_list_len
@@ -305,7 +305,8 @@
source_root_path=src_path)
user_interrupted = False
try:
- for line in nm_output_lines:
+ for binary_line in nm_output_lines:
+ line = binary_line.decode()
match = sNmPattern.match(line)
if match:
location = match.group(5)
@@ -344,7 +345,8 @@
symbol_path_origin_dir = os.path.dirname(os.path.abspath(library))
with open(outfile, 'w') as out:
- for line in nm_output_lines:
+ for binary_line in nm_output_lines:
+ line = binary_line.decode()
match = sNmPattern.match(line)
if match:
location = match.group(5)
@@ -496,7 +498,8 @@
since we are right now transitioning from DWARF2 to newer formats,
it's possible to have a mix of tools that are not compatible. Detect
that and abort rather than produce meaningless output."""
- tool_output = subprocess.check_output([addr2line_binary, '--version'])
+ tool_output = subprocess.check_output([addr2line_binary,
+ '--version']).decode()
version_re = re.compile(r'^GNU [^ ]+ .* (\d+).(\d+).*?$', re.M)
parsed_output = version_re.match(tool_output)
major = int(parsed_output.group(1))
@@ -636,7 +639,7 @@
# CPU power isn't the limiting factor. It's I/O limited, memory
# bus limited and available-memory-limited. Too many processes and
# the computer will run out of memory and it will be slow.
- opts.jobs = max(2, min(4, str(multiprocessing.cpu_count())))
+ opts.jobs = max(2, min(4, multiprocessing.cpu_count()))
if opts.addr2line_binary:
assert os.path.isfile(opts.addr2line_binary)
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index fdfe351..9953c0a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -311,7 +311,7 @@
case kArrayCid:
case kImmutableArrayCid:
case kTypeArgumentsCid:
- return kFourBytes;
+ return kEightBytes;
case kOneByteStringCid:
case kExternalOneByteStringCid:
return kByte;
diff --git a/runtime/vm/experimental_features.cc b/runtime/vm/experimental_features.cc
index 1c79061..162f8c8 100644
--- a/runtime/vm/experimental_features.cc
+++ b/runtime/vm/experimental_features.cc
@@ -18,7 +18,7 @@
bool GetExperimentalFeatureDefault(ExperimentalFeature feature) {
constexpr bool kFeatureValues[] = {
- true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true,
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureValues));
return kFeatureValues[static_cast<int>(feature)];
@@ -29,7 +29,7 @@
"nonfunction-type-aliases", "non-nullable",
"extension-methods", "constant-update-2018",
"control-flow-collections", "set-literals",
- "spread-collections",
+ "spread-collections", "triple-shift",
};
ASSERT(static_cast<size_t>(feature) < ARRAY_SIZE(kFeatureNames));
return kFeatureNames[static_cast<int>(feature)];
diff --git a/runtime/vm/experimental_features.h b/runtime/vm/experimental_features.h
index 035af24..0bb9e50 100644
--- a/runtime/vm/experimental_features.h
+++ b/runtime/vm/experimental_features.h
@@ -21,6 +21,7 @@
control_flow_collections,
set_literals,
spread_collections,
+ triple_shift,
};
bool GetExperimentalFeatureDefault(ExperimentalFeature feature);
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 0a8c71f..e075887 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -657,6 +657,17 @@
}
if (is_finalized()) {
+ // Make sure the declaration types parameter count matches for the two
+ // classes.
+ // ex. class A<int,B> {} cannot be replace with class A<B> {}.
+ auto group_context = context->group_reload_context();
+ if (NumTypeParameters() != replacement.NumTypeParameters()) {
+ group_context->AddReasonForCancelling(
+ new (context->zone())
+ TypeParametersChanged(context->zone(), *this, replacement));
+ return;
+ }
+
// Ensure the replacement class is also finalized.
const Error& error =
Error::Handle(replacement.EnsureIsFinalized(Thread::Current()));
diff --git a/tools/VERSION b/tools/VERSION
index a536092..5392156 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 17
+PRERELEASE 18
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index 55dfb4d..1881ab6 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -106,16 +106,6 @@
current-version: '2.14.0'
features:
- triple-shift:
- help: "Triple-shift operator"
- validation: |
- class A {
- operator>>>(int k) => 42;
- }
- void main() {
- if ((A() >>> 1) == 42) print('feature enabled');
- }
-
variance:
help: "Sound variance"
@@ -183,3 +173,14 @@
help: "Spread Collections"
enabledIn: '2.0.0'
expired: true
+
+ triple-shift:
+ help: "Triple-shift operator"
+ enabledIn: '2.14.0'
+ validation: |
+ class A {
+ operator>>>(int k) => 42;
+ }
+ void main() {
+ if ((A() >>> 1) == 42) print('feature enabled');
+ }
diff --git a/tools/gn.py b/tools/gn.py
index dc355cf..f711dd3 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -163,7 +163,7 @@
# Tell Crashpad's BUILD files which checkout layout to use.
gn_args['crashpad_dependencies'] = 'dart'
- if arch != HostCpuForArch(arch):
+ if DartTargetCpuForArch(arch) != HostCpuForArch(arch):
# Training an app-jit snapshot under a simulator is slow. Use script
# snapshots instead.
gn_args['dart_snapshot_kind'] = 'kernel'