Version 2.13.0-105.0.dev
Merge commit '9d803a52630ecae94e5afe60fbcb8fb8d281ce86' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 3ce1a567e..ec8d2fa 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-03-03T09:46:04.757962",
+ "generated": "2021-03-04T11:31:12.464706",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -300,6 +300,12 @@
"languageVersion": "2.7"
},
{
+ "name": "func",
+ "rootUri": "../third_party/pkg/func",
+ "packageUri": "lib/",
+ "languageVersion": "1.9"
+ },
+ {
"name": "glob",
"rootUri": "../third_party/pkg/glob",
"packageUri": "lib/",
@@ -443,6 +449,12 @@
"languageVersion": "2.0"
},
{
+ "name": "mustache4dart",
+ "rootUri": "../third_party/pkg/mustache4dart",
+ "packageUri": "lib/",
+ "languageVersion": "0.8"
+ },
+ {
"name": "native_stack_traces",
"rootUri": "../pkg/native_stack_traces",
"packageUri": "lib/",
@@ -512,6 +524,12 @@
"languageVersion": "2.12"
},
{
+ "name": "plugin",
+ "rootUri": "../third_party/pkg/plugin",
+ "packageUri": "lib/",
+ "languageVersion": "1.0"
+ },
+ {
"name": "pool",
"rootUri": "../third_party/pkg/pool",
"packageUri": "lib/",
@@ -734,6 +752,12 @@
"languageVersion": "2.12"
},
{
+ "name": "utf",
+ "rootUri": "../third_party/pkg/utf",
+ "packageUri": "lib/",
+ "languageVersion": "2.0"
+ },
+ {
"name": "vector_math",
"rootUri": "../third_party/pkg/vector_math",
"packageUri": "lib/",
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index 8f8a097..c78c614 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -7,7 +7,7 @@
import 'dart:io';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
-import 'package:analysis_server/src/lsp/handlers/handler_completion.dart';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:test/test.dart';
@@ -188,7 +188,7 @@
textDocumentCapabilities: withCompletionItemSnippetSupport(
withCompletionItemKinds(
emptyTextDocumentClientCapabilities,
- defaultSupportedCompletionKinds.toList(),
+ LspClientCapabilities.defaultSupportedCompletionKinds.toList(),
),
),
workspaceCapabilities: withDocumentChangesSupport(
diff --git a/pkg/analysis_server/lib/src/lsp/client_capabilities.dart b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
new file mode 100644
index 0000000..2c16de4
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
@@ -0,0 +1,160 @@
+// Copyright (c) 2021, 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.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+
+/// Wraps the client (editor) capabilities to improve performance.
+///
+/// Sets transferred as arrays in JSON will be converted to Sets for faster
+/// lookups and default values and nulls will be handled here.
+class LspClientCapabilities {
+ /// If the client does not provide capabilities.completion.completionItemKind.valueSet
+ /// then we must never send a kind that's not in this list.
+ static final Set<CompletionItemKind> defaultSupportedCompletionKinds = {
+ CompletionItemKind.Text,
+ CompletionItemKind.Method,
+ CompletionItemKind.Function,
+ CompletionItemKind.Constructor,
+ CompletionItemKind.Field,
+ CompletionItemKind.Variable,
+ CompletionItemKind.Class,
+ CompletionItemKind.Interface,
+ CompletionItemKind.Module,
+ CompletionItemKind.Property,
+ CompletionItemKind.Unit,
+ CompletionItemKind.Value,
+ CompletionItemKind.Enum,
+ CompletionItemKind.Keyword,
+ CompletionItemKind.Snippet,
+ CompletionItemKind.Color,
+ CompletionItemKind.File,
+ CompletionItemKind.Reference,
+ };
+
+ /// If the client does not provide capabilities.documentSymbol.symbolKind.valueSet
+ /// then we must never send a kind that's not in this list.
+ static final Set<SymbolKind> defaultSupportedSymbolKinds = {
+ SymbolKind.File,
+ SymbolKind.Module,
+ SymbolKind.Namespace,
+ SymbolKind.Package,
+ SymbolKind.Class,
+ SymbolKind.Method,
+ SymbolKind.Property,
+ SymbolKind.Field,
+ SymbolKind.Constructor,
+ SymbolKind.Enum,
+ SymbolKind.Interface,
+ SymbolKind.Function,
+ SymbolKind.Variable,
+ SymbolKind.Constant,
+ SymbolKind.Str,
+ SymbolKind.Number,
+ SymbolKind.Boolean,
+ SymbolKind.Array,
+ };
+
+ final ClientCapabilities raw;
+ final bool documentChanges;
+ final bool configuration;
+ final bool createResourceOperations;
+ final bool completionDeprecatedFlag;
+ final bool applyEdit;
+ final bool workDoneProgress;
+ final bool completionSnippets;
+ final bool renameValidation;
+ final bool literalCodeActions;
+ final bool insertReplaceCompletionRanges;
+ final bool definitionLocationLink;
+ final bool hierarchicalSymbols;
+ final Set<CodeActionKind> codeActionKinds;
+ final Set<CompletionItemTag> completionItemTags;
+ final Set<DiagnosticTag> diagnosticTags;
+ final Set<MarkupKind> completionDocumentationFormats;
+ final Set<MarkupKind> signatureHelpDocumentationFormats;
+ final Set<MarkupKind> hoverContentFormats;
+ final Set<SymbolKind> documentSymbolKinds;
+ final Set<SymbolKind> workspaceSymbolKinds;
+ final Set<CompletionItemKind> completionItemKinds;
+ final Set<InsertTextMode> completionInsertTextModes;
+
+ LspClientCapabilities(this.raw)
+ : applyEdit = raw?.workspace?.applyEdit ?? false,
+ codeActionKinds = _listToSet(raw?.textDocument?.codeAction
+ ?.codeActionLiteralSupport?.codeActionKind?.valueSet),
+ completionDeprecatedFlag =
+ raw.textDocument?.completion?.completionItem?.deprecatedSupport ??
+ false,
+ completionDocumentationFormats = _completionDocumentationFormats(raw),
+ completionInsertTextModes = _listToSet(raw.textDocument?.completion
+ ?.completionItem?.insertTextModeSupport?.valueSet),
+ completionItemKinds = _listToSet(
+ raw?.textDocument?.completion?.completionItemKind?.valueSet,
+ defaults: defaultSupportedCompletionKinds),
+ completionSnippets =
+ raw.textDocument?.completion?.completionItem?.snippetSupport ??
+ false,
+ configuration = raw?.workspace?.configuration ?? false,
+ createResourceOperations = raw
+ ?.workspace?.workspaceEdit?.resourceOperations
+ ?.contains(ResourceOperationKind.Create) ??
+ false,
+ definitionLocationLink =
+ raw?.textDocument?.definition?.linkSupport ?? false,
+ completionItemTags = _listToSet(raw
+ ?.textDocument?.completion?.completionItem?.tagSupport?.valueSet),
+ diagnosticTags = _listToSet(
+ raw?.textDocument?.publishDiagnostics?.tagSupport?.valueSet),
+ documentChanges =
+ raw?.workspace?.workspaceEdit?.documentChanges ?? false,
+ documentSymbolKinds = _listToSet(
+ raw?.textDocument?.documentSymbol?.symbolKind?.valueSet,
+ defaults: defaultSupportedSymbolKinds),
+ hierarchicalSymbols = raw?.textDocument?.documentSymbol
+ ?.hierarchicalDocumentSymbolSupport ??
+ false,
+ hoverContentFormats = _hoverContentFormats(raw),
+ insertReplaceCompletionRanges = raw?.textDocument?.completion
+ ?.completionItem?.insertReplaceSupport ??
+ false,
+ literalCodeActions =
+ raw?.textDocument?.codeAction?.codeActionLiteralSupport != null,
+ renameValidation = raw.textDocument?.rename?.prepareSupport ?? false,
+ signatureHelpDocumentationFormats = _sigHelpDocumentationFormats(raw),
+ workDoneProgress = raw.window?.workDoneProgress ?? false,
+ workspaceSymbolKinds = _listToSet(
+ raw?.workspace?.symbol?.symbolKind?.valueSet,
+ defaults: defaultSupportedSymbolKinds);
+
+ static Set<MarkupKind> _completionDocumentationFormats(
+ ClientCapabilities raw) {
+ // For formats, null is valid (which means only raw strings are supported,
+ // not [MarkupContent]), so use null as default.
+ return _listToSet(
+ raw?.textDocument?.completion?.completionItem?.documentationFormat,
+ defaults: null);
+ }
+
+ static Set<MarkupKind> _hoverContentFormats(ClientCapabilities raw) {
+ // For formats, null is valid (which means only raw strings are supported,
+ // not [MarkupContent]), so use null as default.
+ return _listToSet(raw?.textDocument?.hover?.contentFormat, defaults: null);
+ }
+
+ /// Converts a list to a `Set`, returning [defaults] if the list is null.
+ ///
+ /// If [defaults] is not supplied, will return an empty set.
+ static Set<T> _listToSet<T>(List<T> items, {Set<T> defaults = const {}}) {
+ return items != null ? {...items} : defaults;
+ }
+
+ static Set<MarkupKind> _sigHelpDocumentationFormats(ClientCapabilities raw) {
+ // For formats, null is valid (which means only raw strings are supported,
+ // not [MarkupContent]), so use null as default.
+ return _listToSet(
+ raw?.textDocument?.signatureHelp?.signatureInformation
+ ?.documentationFormat,
+ defaults: null);
+ }
+}
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 8a5727a..c8fa759 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
@@ -38,7 +38,7 @@
}
final workspaceEdit = toWorkspaceEdit(
- server.clientCapabilities?.workspace,
+ server.clientCapabilities,
[FileEditInformation(docIdentifier, unit.lineInfo, edits)],
);
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 762a4f8..f51367f 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.
-import 'dart:collection';
-
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,21 +48,14 @@
return success(const []);
}
- final capabilities = server?.clientCapabilities?.textDocument;
+ final supportsApplyEdit = server.clientCapabilities.applyEdit;
- final clientSupportsWorkspaceApplyEdit =
- server?.clientCapabilities?.workspace?.applyEdit == true;
+ final supportsLiteralCodeActions =
+ server.clientCapabilities.literalCodeActions;
- final clientSupportsLiteralCodeActions =
- capabilities?.codeAction?.codeActionLiteralSupport != null;
+ final supportedKinds = server.clientCapabilities.codeActionKinds;
- final clientSupportedCodeActionKinds = HashSet<CodeActionKind>.of(
- capabilities?.codeAction?.codeActionLiteralSupport?.codeActionKind
- ?.valueSet ??
- []);
-
- final clientSupportedDiagnosticTags = HashSet<DiagnosticTag>.of(
- capabilities?.publishDiagnostics?.tagSupport?.valueSet ?? []);
+ final supportedDiagnosticTags = server.clientCapabilities.diagnosticTags;
final unit = await path.mapResult(requireResolvedUnit);
@@ -85,8 +76,7 @@
// Otherwise, filter out anything not supported by the client (if they
// advertised that they provided the kinds).
- if (clientSupportsLiteralCodeActions &&
- !clientSupportedCodeActionKinds.any(isMatch)) {
+ if (supportsLiteralCodeActions && !supportedKinds.any(isMatch)) {
return false;
}
@@ -102,9 +92,9 @@
final length = endOffset - startOffset;
return _getCodeActions(
shouldIncludeKind,
- clientSupportsLiteralCodeActions,
- clientSupportsWorkspaceApplyEdit,
- clientSupportedDiagnosticTags,
+ supportsLiteralCodeActions,
+ supportsApplyEdit,
+ supportedDiagnosticTags,
path.result,
params.range,
offset,
@@ -133,11 +123,11 @@
/// Wraps a command in a CodeAction if the client supports it so that a
/// CodeActionKind can be supplied.
Either2<Command, CodeAction> _commandOrCodeAction(
- bool clientSupportsLiteralCodeActions,
+ bool supportsLiteralCodeActions,
CodeActionKind kind,
Command command,
) {
- return clientSupportsLiteralCodeActions
+ return supportsLiteralCodeActions
? Either2<Command, CodeAction>.t2(
CodeAction(title: command.title, kind: kind, command: command),
)
@@ -222,7 +212,7 @@
Future<List<Either2<Command, CodeAction>>> _getAssistActions(
bool Function(CodeActionKind) shouldIncludeKind,
- bool clientSupportsLiteralCodeActions,
+ bool supportsLiteralCodeActions,
Range range,
int offset,
int length,
@@ -259,7 +249,7 @@
bool Function(CodeActionKind) shouldIncludeKind,
bool supportsLiterals,
bool supportsWorkspaceApplyEdit,
- HashSet<DiagnosticTag> supportedDiagnosticTags,
+ Set<DiagnosticTag> supportedDiagnosticTags,
String path,
Range range,
int offset,
@@ -283,8 +273,8 @@
Future<List<Either2<Command, CodeAction>>> _getFixActions(
bool Function(CodeActionKind) shouldIncludeKind,
- bool clientSupportsLiteralCodeActions,
- HashSet<DiagnosticTag> supportedDiagnosticTags,
+ bool supportsLiteralCodeActions,
+ Set<DiagnosticTag> supportedDiagnosticTags,
Range range,
ResolvedUnitResult unit,
) async {
@@ -347,7 +337,7 @@
Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
bool Function(CodeActionKind) shouldIncludeKind,
- bool clientSupportsLiteralCodeActions,
+ bool supportsLiteralCodeActions,
String path,
int offset,
int length,
@@ -368,7 +358,7 @@
Map<String, dynamic> options,
]) {
return _commandOrCodeAction(
- clientSupportsLiteralCodeActions,
+ supportsLiteralCodeActions,
actionKind,
Command(
title: name,
@@ -425,8 +415,8 @@
/// source such as Sort Members and Organise Imports.
Future<List<Either2<Command, CodeAction>>> _getSourceActions(
bool Function(CodeActionKind) shouldIncludeKind,
- bool clientSupportsLiteralCodeActions,
- bool clientSupportsWorkspaceApplyEdit,
+ bool supportsLiteralCodeActions,
+ bool supportsApplyEdit,
String path,
) async {
// The source actions supported are only valid for Dart files.
@@ -437,14 +427,14 @@
// If the client does not support workspace/applyEdit, we won't be able to
// run any of these.
- if (!clientSupportsWorkspaceApplyEdit) {
+ if (!supportsApplyEdit) {
return const [];
}
return [
if (shouldIncludeKind(DartCodeActionKind.SortMembers))
_commandOrCodeAction(
- clientSupportsLiteralCodeActions,
+ supportsLiteralCodeActions,
DartCodeActionKind.SortMembers,
Command(
title: 'Sort Members',
@@ -453,7 +443,7 @@
),
if (shouldIncludeKind(CodeActionKind.SourceOrganizeImports))
_commandOrCodeAction(
- clientSupportsLiteralCodeActions,
+ supportsLiteralCodeActions,
CodeActionKind.SourceOrganizeImports,
Command(
title: 'Organize Imports',
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 e565b85..f6671c6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -2,13 +2,13 @@
// 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.
-import 'dart:collection';
import 'dart:math' as math;
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';
import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
@@ -28,29 +28,6 @@
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
-/// If the client does not provide capabilities.completion.completionItemKind.valueSet
-/// then we must never send a kind that's not in this list.
-final defaultSupportedCompletionKinds = HashSet<CompletionItemKind>.of([
- CompletionItemKind.Text,
- CompletionItemKind.Method,
- CompletionItemKind.Function,
- CompletionItemKind.Constructor,
- CompletionItemKind.Field,
- CompletionItemKind.Variable,
- CompletionItemKind.Class,
- CompletionItemKind.Interface,
- CompletionItemKind.Module,
- CompletionItemKind.Property,
- CompletionItemKind.Unit,
- CompletionItemKind.Value,
- CompletionItemKind.Enum,
- CompletionItemKind.Keyword,
- CompletionItemKind.Snippet,
- CompletionItemKind.Color,
- CompletionItemKind.File,
- CompletionItemKind.Reference,
-]);
-
class CompletionHandler
extends MessageHandler<CompletionParams, List<CompletionItem>>
with LspPluginRequestHandlerMixin {
@@ -69,17 +46,8 @@
@override
Future<ErrorOr<List<CompletionItem>>> handle(
CompletionParams params, CancellationToken token) async {
- final completionCapabilities =
- server?.clientCapabilities?.textDocument?.completion;
-
- final clientSupportedCompletionKinds =
- completionCapabilities?.completionItemKind?.valueSet != null
- ? HashSet<CompletionItemKind>.of(
- completionCapabilities.completionItemKind.valueSet)
- : defaultSupportedCompletionKinds;
-
- final includeSuggestionSets = suggestFromUnimportedLibraries &&
- server?.clientCapabilities?.workspace?.applyEdit == true;
+ final includeSuggestionSets =
+ suggestFromUnimportedLibraries && server.clientCapabilities.applyEdit;
final pos = params.position;
final path = pathOfDoc(params.textDocument);
@@ -101,8 +69,7 @@
if (fileExtension == '.dart' && !unit.isError) {
serverResultsFuture = _getServerDartItems(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ server.clientCapabilities,
includeSuggestionSets,
unit.result,
offset,
@@ -121,8 +88,7 @@
if (generator != null) {
serverResultsFuture = _getServerYamlItems(
generator,
- completionCapabilities,
- clientSupportedCompletionKinds,
+ server.clientCapabilities,
path.result,
lineInfo.result,
offset,
@@ -133,8 +99,8 @@
serverResultsFuture ??= Future.value(success(const <CompletionItem>[]));
- final pluginResultsFuture = _getPluginResults(completionCapabilities,
- clientSupportedCompletionKinds, lineInfo.result, path.result, offset);
+ final pluginResultsFuture = _getPluginResults(
+ server.clientCapabilities, lineInfo.result, path.result, offset);
// Await both server + plugin results together to allow async/IO to
// overlap.
@@ -195,8 +161,7 @@
'$name/$declaringUri';
Future<ErrorOr<List<CompletionItem>>> _getPluginResults(
- CompletionClientCapabilities completionCapabilities,
- HashSet<CompletionItemKind> clientSupportedCompletionKinds,
+ LspClientCapabilities capabilities,
LineInfo lineInfo,
String path,
int offset,
@@ -210,8 +175,7 @@
.toList();
return success(_pluginResultsToItems(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ capabilities,
lineInfo,
offset,
pluginResults,
@@ -219,8 +183,7 @@
}
Future<ErrorOr<List<CompletionItem>>> _getServerDartItems(
- CompletionClientCapabilities completionCapabilities,
- HashSet<CompletionItemKind> clientSupportedCompletionKinds,
+ LspClientCapabilities capabilities,
bool includeSuggestionSets,
ResolvedUnitResult unit,
int offset,
@@ -288,8 +251,7 @@
}
return toCompletionItem(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ capabilities,
unit.lineInfo,
item,
itemReplacementOffset,
@@ -378,8 +340,7 @@
return importingUris == null ||
importingUris.contains('${library.uri}');
}).map((item) => declarationToCompletionItem(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ capabilities,
unit.path,
offset,
includedSet,
@@ -424,8 +385,7 @@
Future<ErrorOr<List<CompletionItem>>> _getServerYamlItems(
YamlCompletionGenerator generator,
- CompletionClientCapabilities completionCapabilities,
- HashSet<CompletionItemKind> clientSupportedCompletionKinds,
+ LspClientCapabilities capabilities,
String path,
LineInfo lineInfo,
int offset,
@@ -440,8 +400,7 @@
final completionItems = suggestions.suggestions
.map(
(item) => toCompletionItem(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ capabilities,
lineInfo,
item,
suggestions.replacementOffset,
@@ -456,8 +415,7 @@
}
Iterable<CompletionItem> _pluginResultsToItems(
- CompletionClientCapabilities completionCapabilities,
- HashSet<CompletionItemKind> clientSupportedCompletionKinds,
+ LspClientCapabilities capabilities,
LineInfo lineInfo,
int offset,
List<plugin.CompletionGetSuggestionsResult> pluginResults,
@@ -465,8 +423,7 @@
return pluginResults.expand((result) {
return result.results.map(
(item) => toCompletionItem(
- completionCapabilities,
- clientSupportedCompletionKinds,
+ capabilities,
lineInfo,
item,
result.replacementOffset,
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 f2698dd..3c3ea2c 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
@@ -154,11 +154,10 @@
}
// Documentation is added on during resolve for LSP.
- final formats = server.clientCapabilities?.textDocument?.completion
- ?.completionItem?.documentationFormat;
- final supportsInsertReplace = server.clientCapabilities?.textDocument
- ?.completion?.completionItem?.insertReplaceSupport ==
- true;
+ final formats =
+ server.clientCapabilities.completionDocumentationFormats;
+ final supportsInsertReplace =
+ server.clientCapabilities.insertReplaceCompletionRanges;
final dartDoc =
analyzer.getDartDocPlainText(requestedElement.documentationComment);
final documentation = asStringOrMarkupContent(formats, dartDoc);
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 a6399a9..e3599b6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -46,9 +46,9 @@
}
Future<AnalysisNavigationParams> getServerResult(
- bool clientSupportsLocationLink, String path, int offset) async {
- final collector = NavigationCollectorImpl(
- collectCodeLocations: clientSupportsLocationLink);
+ bool supportsLocationLink, String path, int offset) async {
+ final collector =
+ NavigationCollectorImpl(collectCodeLocations: supportsLocationLink);
final result = await server.getResolvedUnit(path);
if (result?.state == ResultState.VALID) {
@@ -64,11 +64,8 @@
@override
Future<ErrorOr<Either2<List<Location>, List<LocationLink>>>> handle(
TextDocumentPositionParams params, CancellationToken token) async {
- final definitionCapabilities =
- server?.clientCapabilities?.textDocument?.definition;
-
- final clientSupportsLocationLink =
- definitionCapabilities?.linkSupport == true;
+ final supportsLocationLink =
+ server.clientCapabilities.definitionLocationLink;
final pos = params.position;
final path = pathOfDoc(params.textDocument);
@@ -87,7 +84,7 @@
return offset.mapResult((offset) async {
final allResults = [
- await getServerResult(clientSupportsLocationLink, path, offset),
+ await getServerResult(supportsLocationLink, path, offset),
...await getPluginResults(path, offset),
];
@@ -97,7 +94,7 @@
// Convert and filter the results using the correct type of Location class
// depending on the client capabilities.
- if (clientSupportsLocationLink) {
+ if (supportsLocationLink) {
final convertedResults = convert(
mergedTargets,
(target) => _toLocationLink(mergedResults, lineInfo, target),
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 2e383a0..f8ad0d6 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,11 +2,10 @@
// 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.
-import 'dart:collection';
-
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';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
@@ -14,29 +13,6 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/source/line_info.dart';
-// If the client does not provide capabilities.documentSymbol.symbolKind.valueSet
-// then we must never send a kind that's not in this list.
-final defaultSupportedSymbolKinds = HashSet<SymbolKind>.of([
- SymbolKind.File,
- SymbolKind.Module,
- SymbolKind.Namespace,
- SymbolKind.Package,
- SymbolKind.Class,
- SymbolKind.Method,
- SymbolKind.Property,
- SymbolKind.Field,
- SymbolKind.Constructor,
- SymbolKind.Enum,
- SymbolKind.Interface,
- SymbolKind.Function,
- SymbolKind.Variable,
- SymbolKind.Constant,
- SymbolKind.Str,
- SymbolKind.Number,
- SymbolKind.Boolean,
- SymbolKind.Array,
-]);
-
class DocumentSymbolHandler extends MessageHandler<DocumentSymbolParams,
Either2<List<DocumentSymbol>, List<SymbolInformation>>> {
DocumentSymbolHandler(LspAnalysisServer server) : super(server);
@@ -56,55 +32,41 @@
);
}
- final symbolCapabilities =
- server?.clientCapabilities?.textDocument?.documentSymbol;
-
- final clientSupportedSymbolKinds =
- symbolCapabilities?.symbolKind?.valueSet != null
- ? HashSet<SymbolKind>.of(symbolCapabilities.symbolKind.valueSet)
- : defaultSupportedSymbolKinds;
-
- final clientSupportsDocumentSymbol =
- symbolCapabilities?.hierarchicalDocumentSymbolSupport ?? false;
-
final path = pathOfDoc(params.textDocument);
final unit = await path.mapResult(requireResolvedUnit);
- return unit.mapResult((unit) => _getSymbols(clientSupportedSymbolKinds,
- clientSupportsDocumentSymbol, path.result, unit));
+ return unit.mapResult(
+ (unit) => _getSymbols(server.clientCapabilities, path.result, unit));
}
DocumentSymbol _asDocumentSymbol(
- HashSet<SymbolKind> clientSupportedSymbolKinds,
+ Set<SymbolKind> supportedKinds,
LineInfo lineInfo,
Outline outline,
) {
return DocumentSymbol(
name: toElementName(outline.element),
detail: outline.element.parameters,
- kind: elementKindToSymbolKind(
- clientSupportedSymbolKinds, outline.element.kind),
+ 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),
children: outline.children
- ?.map((child) =>
- _asDocumentSymbol(clientSupportedSymbolKinds, lineInfo, child))
+ ?.map((child) => _asDocumentSymbol(supportedKinds, lineInfo, child))
?.toList(),
);
}
SymbolInformation _asSymbolInformation(
String containerName,
- HashSet<SymbolKind> clientSupportedSymbolKinds,
+ Set<SymbolKind> supportedKinds,
String documentUri,
LineInfo lineInfo,
Outline outline,
) {
return SymbolInformation(
name: toElementName(outline.element),
- kind: elementKindToSymbolKind(
- clientSupportedSymbolKinds, outline.element.kind),
+ kind: elementKindToSymbolKind(supportedKinds, outline.element.kind),
deprecated: outline.element.isDeprecated,
location: Location(
uri: documentUri,
@@ -116,22 +78,21 @@
}
ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>> _getSymbols(
- HashSet<SymbolKind> clientSupportedSymbolKinds,
- bool clientSupportsDocumentSymbol,
+ LspClientCapabilities capabilities,
String path,
ResolvedUnitResult unit,
) {
final computer = DartUnitOutlineComputer(unit);
final outline = computer.compute();
- if (clientSupportsDocumentSymbol) {
+ if (capabilities.hierarchicalSymbols) {
// Return a tree of DocumentSymbol only if the client shows explicit support
// for it.
return success(
Either2<List<DocumentSymbol>, List<SymbolInformation>>.t1(
outline?.children
?.map((child) => _asDocumentSymbol(
- clientSupportedSymbolKinds, unit.lineInfo, child))
+ capabilities.documentSymbolKinds, unit.lineInfo, child))
?.toList(),
),
);
@@ -145,7 +106,7 @@
void addSymbol(Outline outline, {String parentName}) {
allSymbols.add(_asSymbolInformation(
parentName,
- clientSupportedSymbolKinds,
+ capabilities.documentSymbolKinds,
documentUri,
unit.lineInfo,
outline,
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 967e8e8..43d877e 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
@@ -45,7 +45,7 @@
final progress = params.workDoneToken != null
? ProgressReporter.clientProvided(server, params.workDoneToken)
- : server.clientCapabilities.window?.workDoneProgress == true
+ : server.clientCapabilities.workDoneProgress
? ProgressReporter.serverCreated(server)
: ProgressReporter.noop;
return handler.handle(params.arguments, progress, cancellationToken);
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 3b5561e..4e57b46 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -73,8 +73,7 @@
content.writeln(cleanDartdoc(hover.dartdoc));
}
- final formats =
- server?.clientCapabilities?.textDocument?.hover?.contentFormat;
+ final formats = server.clientCapabilities.hoverContentFormats;
return Hover(
contents:
asStringOrMarkupContent(formats, content.toString().trimRight()),
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 4a74f56..9174fb8 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -60,7 +60,7 @@
);
server.capabilities = server.capabilitiesComputer
- .computeServerCapabilities(params.capabilities);
+ .computeServerCapabilities(server.clientCapabilities);
var sdkVersion = Platform.version;
if (sdkVersion.contains(' ')) {
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 de886e7..d01e33d 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
@@ -67,8 +67,8 @@
return success();
}
- final formats = server?.clientCapabilities?.textDocument?.signatureHelp
- ?.signatureInformation?.documentationFormat;
+ final formats =
+ server.clientCapabilities.signatureHelpDocumentationFormats;
return success(toSignatureHelp(formats, signature));
});
}
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 fece08b..ef781d1 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,12 +2,8 @@
// 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.
-import 'dart:collection';
-
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_document_symbols.dart'
- show defaultSupportedSymbolKinds;
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
@@ -34,12 +30,7 @@
return success([]);
}
- final symbolCapabilities = server?.clientCapabilities?.workspace?.symbol;
-
- final clientSupportedSymbolKinds =
- symbolCapabilities?.symbolKind?.valueSet != null
- ? HashSet<SymbolKind>.of(symbolCapabilities.symbolKind.valueSet)
- : defaultSupportedSymbolKinds;
+ final supportedSymbolKinds = server.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.
@@ -67,7 +58,7 @@
final symbols = declarations
.map((declaration) => _asSymbolInformation(
declaration,
- clientSupportedSymbolKinds,
+ supportedSymbolKinds,
filePaths,
))
.toList();
@@ -77,13 +68,13 @@
SymbolInformation _asSymbolInformation(
search.Declaration declaration,
- HashSet<SymbolKind> clientSupportedSymbolKinds,
+ Set<SymbolKind> supportedKinds,
List<String> filePaths,
) {
final filePath = filePaths[declaration.fileIndex];
final kind = declarationKindToSymbolKind(
- clientSupportedSymbolKinds,
+ supportedKinds,
declaration.kind,
);
final range = toRange(
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 46e1fe1..19afc27 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:collection';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -18,6 +17,7 @@
show CompletionDomainHandler;
import 'package:analysis_server/src/flutter/flutter_outline_computer.dart';
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/client_configuration.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handler_states.dart';
@@ -55,7 +55,7 @@
/// them.
class LspAnalysisServer extends AbstractAnalysisServer {
/// The capabilities of the LSP client. Will be null prior to initialization.
- ClientCapabilities _clientCapabilities;
+ LspClientCapabilities _clientCapabilities;
/// Initialization options provided by the LSP client. Allows opting in/out of
/// specific server functionality. Will be null prior to initialization.
@@ -115,7 +115,7 @@
final _temporaryAnalysisRoots = <String, String>{};
/// The set of analysis roots explicitly added to the workspace.
- final _explicitAnalysisRoots = HashSet<String>();
+ final _explicitAnalysisRoots = <String>{};
/// A progress reporter for analysis status.
ProgressReporter analyzingProgressReporter;
@@ -164,7 +164,7 @@
}
/// The capabilities of the LSP client. Will be null prior to initialization.
- ClientCapabilities get clientCapabilities => _clientCapabilities;
+ LspClientCapabilities get clientCapabilities => _clientCapabilities;
Future<void> get exited => channel.closed;
@@ -214,7 +214,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.workspace?.configuration ?? false) {
+ if (clientCapabilities.configuration) {
// 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").
@@ -271,7 +271,7 @@
void handleClientConnection(
ClientCapabilities capabilities, dynamic initializationOptions) {
- _clientCapabilities = capabilities;
+ _clientCapabilities = LspClientCapabilities(capabilities);
_initializationOptions = LspInitializationOptions(initializationOptions);
performanceAfterStartup = ServerPerformance();
@@ -555,7 +555,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.window?.workDoneProgress != true) {
+ if (clientCapabilities.workDoneProgress != true) {
channel.sendNotification(NotificationMessage(
method: CustomMethods.analyzerStatus,
params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
@@ -809,11 +809,8 @@
analysisServer.declarationsTracker
?.addContext(analysisDriver.analysisContext);
- final textDocumentCapabilities =
- analysisServer.clientCapabilities?.textDocument;
- final supportedDiagnosticTags = HashSet<DiagnosticTag>.of(
- textDocumentCapabilities?.publishDiagnostics?.tagSupport?.valueSet ??
- []);
+ final supportedDiagnosticTags =
+ analysisServer.clientCapabilities.diagnosticTags;
analysisDriver.results.listen((result) {
var path = result.path;
filesToFlush.add(path);
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 1b8e024..298e997 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -2,7 +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.
-import 'dart:collection';
import 'dart:math';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart'
@@ -11,6 +10,8 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
+import 'package:analysis_server/src/collections.dart';
+import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/constants.dart' as lsp;
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/dartdoc.dart';
@@ -47,7 +48,7 @@
const languageSourceName = 'dart';
lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent(
- List<lsp.MarkupKind> preferredFormats, String content) {
+ Set<lsp.MarkupKind> preferredFormats, String content) {
if (content == null) {
return null;
}
@@ -113,7 +114,7 @@
lsp.WorkspaceEdit createWorkspaceEdit(
lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
return toWorkspaceEdit(
- server.clientCapabilities?.workspace,
+ server.clientCapabilities,
edits
.map((e) => FileEditInformation(
server.getVersionedDocumentIdentifier(e.file),
@@ -126,11 +127,11 @@
}
lsp.CompletionItemKind declarationKindToCompletionItemKind(
- HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
+ Set<lsp.CompletionItemKind> supportedCompletionKinds,
dec.DeclarationKind kind,
) {
bool isSupported(lsp.CompletionItemKind kind) =>
- clientSupportedCompletionKinds.contains(kind);
+ supportedCompletionKinds.contains(kind);
List<lsp.CompletionItemKind> getKindPreferences() {
switch (kind) {
@@ -162,11 +163,10 @@
}
lsp.SymbolKind declarationKindToSymbolKind(
- HashSet<lsp.SymbolKind> clientSupportedSymbolKinds,
+ Set<lsp.SymbolKind> supportedSymbolKinds,
server.DeclarationKind kind,
) {
- bool isSupported(lsp.SymbolKind kind) =>
- clientSupportedSymbolKinds.contains(kind);
+ bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);
List<lsp.SymbolKind> getKindPreferences() {
switch (kind) {
@@ -210,8 +210,7 @@
}
lsp.CompletionItem declarationToCompletionItem(
- lsp.CompletionClientCapabilities completionCapabilities,
- HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds,
+ LspClientCapabilities capabilities,
String file,
int offset,
server.IncludedSuggestionSet includedSuggestionSet,
@@ -225,8 +224,7 @@
@required bool includeCommitCharacters,
@required bool completeFunctionCalls,
}) {
- final supportsSnippets =
- completionCapabilities?.completionItem?.snippetSupport == true;
+ final supportsSnippets = capabilities.completionSnippets;
String completion;
switch (declaration.kind) {
@@ -286,19 +284,14 @@
final insertTextFormat = insertTextInfo.last;
final isMultilineCompletion = insertText.contains('\n');
- final supportsDeprecatedFlag =
- completionCapabilities?.completionItem?.deprecatedSupport == true;
- final supportedTags =
- completionCapabilities?.completionItem?.tagSupport?.valueSet ?? const [];
- final supportsDeprecatedTag =
- supportedTags.contains(lsp.CompletionItemTag.Deprecated);
- final supportsAsIsInsertMode = completionCapabilities
- ?.completionItem?.insertTextModeSupport?.valueSet
- ?.contains(InsertTextMode.asIs) ==
- true;
+ final supportsDeprecatedFlag = capabilities.completionDeprecatedFlag;
+ final supportsDeprecatedTag = capabilities.completionItemTags
+ .contains(lsp.CompletionItemTag.Deprecated);
+ final supportsAsIsInsertMode =
+ capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);
final completionKind = declarationKindToCompletionItemKind(
- supportedCompletionItemKinds, declaration.kind);
+ capabilities.completionItemKinds, declaration.kind);
var relevanceBoost = 0;
if (declaration.relevanceTags != null) {
@@ -354,11 +347,11 @@
}
lsp.CompletionItemKind elementKindToCompletionItemKind(
- HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
+ Set<lsp.CompletionItemKind> supportedCompletionKinds,
server.ElementKind kind,
) {
bool isSupported(lsp.CompletionItemKind kind) =>
- clientSupportedCompletionKinds.contains(kind);
+ supportedCompletionKinds.contains(kind);
List<lsp.CompletionItemKind> getKindPreferences() {
switch (kind) {
@@ -419,11 +412,10 @@
}
lsp.SymbolKind elementKindToSymbolKind(
- HashSet<lsp.SymbolKind> clientSupportedSymbolKinds,
+ Set<lsp.SymbolKind> supportedSymbolKinds,
server.ElementKind kind,
) {
- bool isSupported(lsp.SymbolKind kind) =>
- clientSupportedSymbolKinds.contains(kind);
+ bool isSupported(lsp.SymbolKind kind) => supportedSymbolKinds.contains(kind);
List<lsp.SymbolKind> getKindPreferences() {
switch (kind) {
@@ -496,7 +488,7 @@
String getCompletionDetail(
server.CompletionSuggestion suggestion,
lsp.CompletionItemKind completionKind,
- bool clientSupportsDeprecated,
+ bool supportsDeprecated,
) {
final hasElement = suggestion.element != null;
final hasParameters = hasElement &&
@@ -508,9 +500,8 @@
final hasParameterType =
suggestion.parameterType != null && suggestion.parameterType.isNotEmpty;
- final prefix = clientSupportsDeprecated || !suggestion.isDeprecated
- ? ''
- : '(Deprecated) ';
+ final prefix =
+ supportsDeprecated || !suggestion.isDeprecated ? '' : '(Deprecated) ';
if (completionKind == lsp.CompletionItemKind.Property) {
// Setters appear as methods with one arg but they also cause getters to not
@@ -542,16 +533,15 @@
String getDeclarationCompletionDetail(
dec.Declaration declaration,
lsp.CompletionItemKind completionKind,
- bool clientSupportsDeprecated,
+ bool supportsDeprecated,
) {
final hasParameters =
declaration.parameters != null && declaration.parameters.isNotEmpty;
final hasReturnType =
declaration.returnType != null && declaration.returnType.isNotEmpty;
- final prefix = clientSupportsDeprecated || !declaration.isDeprecated
- ? ''
- : '(Deprecated) ';
+ final prefix =
+ supportsDeprecated || !declaration.isDeprecated ? '' : '(Deprecated) ';
if (completionKind == lsp.CompletionItemKind.Property) {
// Setters appear as methods with one arg but they also cause getters to not
@@ -583,7 +573,7 @@
}
List<lsp.DiagnosticTag> getDiagnosticTags(
- HashSet<lsp.DiagnosticTag> supportedTags, server.AnalysisError error) {
+ Set<lsp.DiagnosticTag> supportedTags, server.AnalysisError error) {
if (supportedTags == null) {
return null;
}
@@ -637,8 +627,6 @@
);
}
-List<T> nullIfEmpty<T>(List<T> items) => items.isEmpty ? null : items;
-
/// Returns the file system path for a TextDocumentIdentifier.
ErrorOr<String> pathOfDoc(lsp.TextDocumentIdentifier doc) =>
pathOfUri(Uri.tryParse(doc?.uri));
@@ -753,12 +741,12 @@
}
lsp.CompletionItemKind suggestionKindToCompletionItemKind(
- HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
+ Set<lsp.CompletionItemKind> supportedCompletionKinds,
server.CompletionSuggestionKind kind,
String label,
) {
bool isSupported(lsp.CompletionItemKind kind) =>
- clientSupportedCompletionKinds.contains(kind);
+ supportedCompletionKinds.contains(kind);
List<lsp.CompletionItemKind> getKindPreferences() {
switch (kind) {
@@ -823,8 +811,7 @@
}
lsp.CompletionItem toCompletionItem(
- lsp.CompletionClientCapabilities completionCapabilities,
- HashSet<lsp.CompletionItemKind> supportedCompletionItemKinds,
+ LspClientCapabilities capabilities,
server.LineInfo lineInfo,
server.CompletionSuggestion suggestion,
int replacementOffset,
@@ -865,27 +852,21 @@
label += suggestion.parameterNames?.isNotEmpty ?? false ? '(…)' : '()';
}
- final supportsDeprecatedFlag =
- completionCapabilities?.completionItem?.deprecatedSupport == true;
- final supportedTags =
- completionCapabilities?.completionItem?.tagSupport?.valueSet ?? const [];
- final supportsDeprecatedTag =
- supportedTags.contains(lsp.CompletionItemTag.Deprecated);
- final formats = completionCapabilities?.completionItem?.documentationFormat;
- final supportsSnippets =
- completionCapabilities?.completionItem?.snippetSupport == true;
- final supportsInsertReplace =
- completionCapabilities?.completionItem?.insertReplaceSupport == true;
- final supportsAsIsInsertMode = completionCapabilities
- ?.completionItem?.insertTextModeSupport?.valueSet
- ?.contains(InsertTextMode.asIs) ==
- true;
+ final supportsCompletionDeprecatedFlag =
+ capabilities.completionDeprecatedFlag;
+ final supportsDeprecatedTag = capabilities.completionItemTags
+ .contains(lsp.CompletionItemTag.Deprecated);
+ final formats = capabilities.completionDocumentationFormats;
+ final supportsSnippets = capabilities.completionSnippets;
+ final supportsInsertReplace = capabilities.insertReplaceCompletionRanges;
+ final supportsAsIsInsertMode =
+ capabilities.completionInsertTextModes.contains(InsertTextMode.asIs);
final completionKind = suggestion.element != null
? elementKindToCompletionItemKind(
- supportedCompletionItemKinds, suggestion.element.kind)
+ capabilities.completionItemKinds, suggestion.element.kind)
: suggestionKindToCompletionItemKind(
- supportedCompletionItemKinds, suggestion.kind, label);
+ capabilities.completionItemKinds, suggestion.kind, label);
final insertTextInfo = _buildInsertText(
supportsSnippets: supportsSnippets,
@@ -917,10 +898,12 @@
includeCommitCharacters ? dartCompletionCommitCharacters : null,
data: resolutionData,
detail: getCompletionDetail(suggestion, completionKind,
- supportsDeprecatedFlag || supportsDeprecatedTag),
+ supportsCompletionDeprecatedFlag || supportsDeprecatedTag),
documentation:
asStringOrMarkupContent(formats, cleanDartdoc(suggestion.docComplete)),
- deprecated: supportsDeprecatedFlag && suggestion.isDeprecated ? true : null,
+ deprecated: supportsCompletionDeprecatedFlag && suggestion.isDeprecated
+ ? true
+ : null,
// Relevance is a number, highest being best. LSP does text sort so subtract
// from a large number so that a text sort will result in the correct order.
// 555 -> 999455
@@ -959,7 +942,7 @@
lsp.Diagnostic toDiagnostic(
server.ResolvedUnitResult result,
server.AnalysisError error, {
- @required HashSet<lsp.DiagnosticTag> supportedTags,
+ @required Set<lsp.DiagnosticTag> supportedTags,
server.ErrorSeverity errorSeverity,
}) {
var errorCode = error.errorCode;
@@ -1168,7 +1151,7 @@
);
}
-lsp.SignatureHelp toSignatureHelp(List<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
@@ -1282,15 +1265,12 @@
}
lsp.WorkspaceEdit toWorkspaceEdit(
- lsp.ClientCapabilitiesWorkspace capabilities,
+ LspClientCapabilities capabilities,
List<FileEditInformation> edits,
) {
- final clientSupportsTextDocumentEdits =
- capabilities?.workspaceEdit?.documentChanges == true;
- if (clientSupportsTextDocumentEdits) {
- final clientSupportsCreate = capabilities?.workspaceEdit?.resourceOperations
- ?.contains(ResourceOperationKind.Create) ??
- false;
+ final supportsDocumentChanges = capabilities.documentChanges;
+ if (supportsDocumentChanges) {
+ final supportsCreate = capabilities.createResourceOperations;
final changes = <
Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
lsp.DeleteFile>>[];
@@ -1299,7 +1279,7 @@
// CreateFile + a TextDocumentEdit depending on whether it's a new
// file.
for (final edit in edits) {
- if (clientSupportsCreate && edit.newFile) {
+ if (supportsCreate && edit.newFile) {
final create = lsp.CreateFile(uri: edit.doc.uri);
final createUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
lsp.RenameFile, lsp.DeleteFile>.t2(create);
@@ -1335,7 +1315,7 @@
}
lsp.MarkupContent _asMarkup(
- List<lsp.MarkupKind> preferredFormats, String content) {
+ 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.
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 f67feaa..808446a 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -4,6 +4,7 @@
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';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/semantic_tokens/legend.dart';
@@ -128,18 +129,17 @@
ServerCapabilitiesComputer(this._server);
ServerCapabilities computeServerCapabilities(
- ClientCapabilities clientCapabilities) {
- final codeActionLiteralSupport =
- clientCapabilities.textDocument?.codeAction?.codeActionLiteralSupport;
+ LspClientCapabilities clientCapabilities) {
+ final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
- final renameOptionsSupport =
- clientCapabilities.textDocument?.rename?.prepareSupport ?? false;
+ final renameOptionsSupport = clientCapabilities.renameValidation;
final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
final previewCommitCharacters =
_server.clientConfiguration.previewCommitCharacters;
- final dynamicRegistrations = ClientDynamicRegistrations(clientCapabilities);
+ final dynamicRegistrations =
+ ClientDynamicRegistrations(clientCapabilities.raw);
// When adding new capabilities to the server that may apply to specific file
// types, it's important to update
@@ -328,7 +328,7 @@
}
final dynamicRegistrations =
- ClientDynamicRegistrations(_server.clientCapabilities);
+ ClientDynamicRegistrations(_server.clientCapabilities.raw);
register(
dynamicRegistrations.textSync,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart
deleted file mode 100644
index c853976..0000000
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking_internal.dart
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
-import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-
-/// Fuzzy matching between static analysis and model-predicted lexemes
-/// that considers pairs like "main" and "main()" to be equal.
-bool areCompletionsEquivalent(String dasCompletion, String modelCompletion) {
- if (dasCompletion == null || modelCompletion == null) {
- return false;
- }
- if (dasCompletion == modelCompletion) {
- return true;
- }
-
- final index = dasCompletion.indexOf(RegExp(r'[^0-9A-Za-z_]'));
- // Disallow '.' since this gives all methods under a model-predicted token
- // the same probability.
- if (index == -1 || dasCompletion[index] == '.') {
- return false;
- }
-
- // Checks that the strings are equal until the first non-alphanumeric token.
- return dasCompletion.substring(0, index) == modelCompletion;
-}
-
-/// Finds the previous n tokens occurring before the cursor.
-List<String> constructQuery(DartCompletionRequest request, int n) {
- var token = getCursorToken(request);
- if (request.offset == null) {
- return null;
- }
-
- while (!isStopToken(token, request.offset)) {
- token = token.previous;
- }
-
- if (token?.offset == null || token?.type == null) {
- return null;
- }
-
- final result = <String>[];
- for (var size = 0;
- size < n && token != null && !token.isEof;
- token = token.previous) {
- if (!token.isSynthetic && token is! ErrorToken) {
- // Omit the optional new keyword as we remove it at training time to
- // prevent model from suggesting it.
- if (token.lexeme == 'new') {
- continue;
- }
-
- result.add(token.lexeme);
- size += 1;
- }
- }
-
- return result.reversed.toList(growable: false);
-}
-
-/// Maps included relevance tags formatted as
-/// '${element.librarySource.uri}::${element.name}' to element.name.
-String elementNameFromRelevanceTag(String tag) {
- final index = tag.lastIndexOf('::');
- if (index == -1) {
- return null;
- }
-
- return tag.substring(index + 2);
-}
-
-Token getCurrentToken(DartCompletionRequest request) {
- var token = getCursorToken(request);
- while (!isStopToken(token.previous, request.offset)) {
- token = token.previous;
- }
- return token;
-}
-
-/// Finds the token at which completion was requested.
-Token getCursorToken(DartCompletionRequest request) {
- final entity = request.target.entity;
- if (entity is AstNode) {
- return entity.endToken;
- }
- return entity is Token ? entity : null;
-}
-
-bool isLiteral(String lexeme) {
- if (lexeme == null || lexeme.isEmpty) {
- return false;
- }
- if (RegExp(r'^[0-9]+$').hasMatch(lexeme)) {
- // Check for number lexeme.
- return true;
- }
- return isStringLiteral(lexeme);
-}
-
-bool isNotWhitespace(String lexeme) {
- return lexeme
- .replaceAll("'", '')
- .split('')
- .any((String chr) => !RegExp(r'\s').hasMatch(chr));
-}
-
-/// Step to previous token until we are at the first token before where the
-/// cursor is located.
-bool isStopToken(Token token, int cursorOffset) {
- if (token == null) {
- return true;
- }
- if (token.isSynthetic && !token.isEof) {
- return false;
- }
- final position = token.offset + token.length;
- if (position == cursorOffset) {
- // If we are at the end of some token, step to previous only if the
- // token is NOT an identifier, keyword, or literal. The rationale is that
- // we want to keep moving if we have a situation like
- // FooBar foo^ since foo is not a previous token to pass to the model.
- return !token.lexeme[token.lexeme.length - 1]
- .contains(RegExp(r'[0-9A-Za-z_]'));
- }
- // Stop if the token's location is strictly before the cursor, continue
- // if the token's location is strictly after.
- return position < cursorOffset;
-}
-
-bool isStringLiteral(String lexeme) {
- if (lexeme == null || lexeme.isEmpty) {
- return false;
- }
- return (lexeme.length > 1 && lexeme[0] == "'") ||
- (lexeme.length > 2 && lexeme[0] == 'r' && lexeme[1] == "'");
-}
-
-bool isTokenDot(Token token) {
- return token != null && !token.isSynthetic && token.lexeme.endsWith('.');
-}
-
-/// Filters the entries list down to only those which represent string literals
-/// and then strips quotes.
-List<MapEntry<String, double>> selectStringLiterals(List<MapEntry> entries) {
- return entries
- .where((MapEntry entry) =>
- isStringLiteral(entry.key) && isNotWhitespace(entry.key))
- .map<MapEntry<String, double>>(
- (MapEntry entry) => MapEntry(trimQuotes(entry.key), entry.value))
- .toList();
-}
-
-/// Tests whether all completion suggestions are for named arguments.
-bool testNamedArgument(List<CompletionSuggestion> suggestions) {
- if (suggestions == null) {
- return false;
- }
-
- return suggestions.any((CompletionSuggestion suggestion) =>
- suggestion.kind == CompletionSuggestionKind.NAMED_ARGUMENT);
-}
-
-String trimQuotes(String input) {
- final result = input[0] == '\'' ? input.substring(1) : input;
- return result[result.length - 1] == '\''
- ? result.substring(0, result.length - 1)
- : result;
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart
index 58fa8e6..86ad614 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart
@@ -14,6 +14,9 @@
FixKind get fixKind => DartFixKind.USE_EQ_EQ_NULL;
@override
+ FixKind get multiFixKind => DartFixKind.USE_EQ_EQ_NULL_MULTI;
+
+ @override
Future<void> compute(ChangeBuilder builder) async {
if (coveredNode is IsExpression) {
var isExpression = coveredNode as IsExpression;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 270e10d..df6febc 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -323,6 +323,15 @@
],
),
],
+ HintCode.TYPE_CHECK_IS_NULL: [
+ FixInfo(
+ canBeAppliedToFile: true,
+ canBeBulkApplied: false,
+ generators: [
+ UseEqEqNull.newInstance,
+ ],
+ ),
+ ],
CompileTimeErrorCode.UNDEFINED_CLASS_BOOLEAN: [
FixInfo(
canBeAppliedToFile: true,
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index da5a030..368b129 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -964,7 +964,7 @@
if (server.clientCapabilities == null) {
p('Client capabilities have not yet been received.');
} else {
- prettyJson(server.clientCapabilities.toJson());
+ prettyJson(server.clientCapabilities.raw.toJson());
}
buf.writeln('</div>');
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 855f489..c968f5b 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -37,6 +37,5 @@
path: ../analyzer_utilities
logging: any
matcher: any
- mockito: any
pedantic: ^1.9.0
test_reflective_loader: any
diff --git a/pkg/analysis_server/test/lsp/mapping_test.dart b/pkg/analysis_server/test/lsp/mapping_test.dart
index 9d88d76..ce08941 100644
--- a/pkg/analysis_server/test/lsp/mapping_test.dart
+++ b/pkg/analysis_server/test/lsp/mapping_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.
-import 'dart:collection';
-
import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
import 'package:analysis_server/src/lsp/mapping.dart' as lsp;
import 'package:analysis_server/src/protocol_server.dart' as server;
@@ -24,10 +22,10 @@
// TYPE_PARAMETER maps to TypeParameter first, but since originally LSP
// did not support it, it'll map to Variable if the client doesn't support
// that.
- var supportedKinds = HashSet.of([
+ var supportedKinds = {
lsp.CompletionItemKind.TypeParameter,
lsp.CompletionItemKind.Variable,
- ]);
+ };
var result = lsp.elementKindToCompletionItemKind(
supportedKinds,
server.ElementKind.TYPE_PARAMETER,
@@ -39,7 +37,7 @@
// TYPE_PARAMETER maps to TypeParameter first, but since originally LSP
// did not support it, it'll map to Variable if the client doesn't support
// that.
- var supportedKinds = HashSet.of([lsp.CompletionItemKind.Variable]);
+ var supportedKinds = {lsp.CompletionItemKind.Variable};
var result = lsp.elementKindToCompletionItemKind(
supportedKinds,
server.ElementKind.TYPE_PARAMETER,
@@ -48,7 +46,7 @@
}
Future<void> test_completionItemKind_knownMapping() async {
- final supportedKinds = HashSet.of([lsp.CompletionItemKind.Class]);
+ final supportedKinds = {lsp.CompletionItemKind.Class};
final result = lsp.elementKindToCompletionItemKind(
supportedKinds,
server.ElementKind.CLASS,
@@ -57,7 +55,7 @@
}
Future<void> test_completionItemKind_notMapped() async {
- var supportedKinds = HashSet<lsp.CompletionItemKind>();
+ var supportedKinds = <lsp.CompletionItemKind>{};
var result = lsp.elementKindToCompletionItemKind(
supportedKinds,
server.ElementKind.UNKNOWN, // Unknown is not mapped.
@@ -66,7 +64,7 @@
}
Future<void> test_completionItemKind_notSupported() async {
- var supportedKinds = HashSet<lsp.CompletionItemKind>();
+ var supportedKinds = <lsp.CompletionItemKind>{};
var result = lsp.elementKindToCompletionItemKind(
supportedKinds,
server.ElementKind.CLASS,
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart
deleted file mode 100644
index 1510b22..0000000
--- a/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/src/protocol_server.dart';
-import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
-import 'package:analysis_server/src/services/completion/dart/completion_ranking_internal.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-
-void main() {
- group('getCursorToken', () {
- MockCompletionRequest request;
- MockCompletionTarget target;
-
- setUp(() {
- request = MockCompletionRequest();
- target = MockCompletionTarget();
- when(request.target).thenReturn(target);
- });
-
- test('areCompletionsEquivalent exact match', () {
- expect(areCompletionsEquivalent('foo', 'foo'), equals(true));
- });
-
- test('areCompletionsEquivalent function call', () {
- expect(areCompletionsEquivalent('foo()', 'foo'), equals(true));
- });
-
- test('areCompletionsEquivalent field name', () {
- expect(areCompletionsEquivalent('foo: ,', 'foo'), equals(true));
- });
-
- test('areCompletionsEquivalent different name', () {
- expect(areCompletionsEquivalent('foo', 'fooBar'), equals(false));
- });
-
- test('areCompletionsEquivalent method invocation', () {
- expect(areCompletionsEquivalent('foo.bar()', 'foo'), equals(false));
- });
-
- test('getCursorToken AstNode', () {
- final node = MockAstNode();
- final token = MockToken();
- when(target.entity).thenReturn(node);
- when(node.endToken).thenReturn(token);
- expect(getCursorToken(request), equals(token));
- });
-
- test('getCursorToken Token', () {
- final token = MockToken();
- when(target.entity).thenReturn(token);
- expect(getCursorToken(request), equals(token));
- });
-
- test('getCursorToken null', () {
- when(target.entity).thenReturn(null);
- expect(getCursorToken(request), equals(null));
- });
- });
-
- test('isStopToken null', () {
- expect(isStopToken(null, 5), equals(true));
- });
-
- test('isStopToken synthetic', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(true);
- when(token.isEof).thenReturn(false);
- expect(isStopToken(token, 5), equals(false));
- });
-
- test('isStopToken punctuation', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(false);
- when(token.offset).thenReturn(4);
- when(token.length).thenReturn(1);
- when(token.lexeme).thenReturn(')');
- expect(isStopToken(token, 5), equals(true));
- });
-
- test('isStopToken alphabetic', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(false);
- when(token.offset).thenReturn(2);
- when(token.length).thenReturn(3);
- when(token.lexeme).thenReturn('foo');
- expect(isStopToken(token, 5), equals(false));
- });
-
- test('isStringLiteral null', () {
- expect(isStringLiteral(null), equals(false));
- });
-
- test('isStringLiteral empty string', () {
- expect(isStringLiteral(''), equals(false));
- });
-
- test('isStringLiteral basic', () {
- expect(isStringLiteral("'foo'"), equals(true));
- });
-
- test('isStringLiteral raw', () {
- expect(isStringLiteral("r'foo'"), equals(true));
- });
-
- test('isLiteral string', () {
- expect(isLiteral("'foo'"), equals(true));
- });
-
- test('isLiteral numeric', () {
- expect(isLiteral('12345'), equals(true));
- });
-
- test('isLiteral not literal', () {
- expect(isLiteral('foo'), equals(false));
- });
-
- test('isTokenDot dot', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(false);
- when(token.lexeme).thenReturn('.');
- expect(isTokenDot(token), equals(true));
- });
-
- test('isTokenDot not dot', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(false);
- when(token.lexeme).thenReturn('foo');
- expect(isTokenDot(token), equals(false));
- });
-
- test('isTokenDot synthetic', () {
- final token = MockToken();
- when(token.isSynthetic).thenReturn(true);
- expect(isTokenDot(token), false);
- });
-
- test('getCurrentToken', () {
- final one = MockToken();
- final two = MockToken();
- final three = MockToken();
- when(three.previous).thenReturn(two);
- when(two.previous).thenReturn(one);
- final request = MockCompletionRequest();
- final target = MockCompletionTarget();
- when(request.offset).thenReturn(2);
- when(request.target).thenReturn(target);
- when(target.entity).thenReturn(three);
- when(two.isSynthetic).thenReturn(true);
- when(two.isEof).thenReturn(false);
- when(one.isSynthetic).thenReturn(false);
- when(one.offset).thenReturn(1);
- when(one.length).thenReturn(3);
- when(one.lexeme).thenReturn('foo');
- expect(getCurrentToken(request), equals(one));
- });
-
- test('constructQuery', () {
- final start = MockToken();
- when(start.isSynthetic).thenReturn(true);
- when(start.isEof).thenReturn(true);
- final one = MockToken();
- when(one.lexeme).thenReturn('class');
- when(one.offset).thenReturn(0);
- when(one.length).thenReturn(5);
- when(one.isSynthetic).thenReturn(false);
- when(one.isEof).thenReturn(false);
- when(one.type).thenReturn(Keyword.CLASS);
- final two = MockToken();
- when(two.lexeme).thenReturn('Animal');
- when(two.offset).thenReturn(6);
- when(two.length).thenReturn(6);
- when(two.isSynthetic).thenReturn(false);
- when(one.previous).thenReturn(start);
- when(two.previous).thenReturn(one);
- when(two.type).thenReturn(TokenType.IDENTIFIER);
- when(two.isEof).thenReturn(false);
- final request = MockCompletionRequest();
- final target = MockCompletionTarget();
- when(request.offset).thenReturn(13);
- when(request.target).thenReturn(target);
- when(target.entity).thenReturn(two);
- expect(constructQuery(request, 100), equals(['class', 'Animal']));
- });
-
- test('constructQuery cursor over paren', () {
- final start = MockToken();
- when(start.isSynthetic).thenReturn(true);
- when(start.isEof).thenReturn(true);
- final one = MockToken();
- when(one.lexeme).thenReturn('main');
- when(one.offset).thenReturn(0);
- when(one.length).thenReturn(4);
- when(one.isSynthetic).thenReturn(false);
- when(one.isEof).thenReturn(false);
- when(one.type).thenReturn(TokenType.IDENTIFIER);
- final two = MockToken();
- when(two.lexeme).thenReturn('(');
- when(two.offset).thenReturn(5);
- when(two.length).thenReturn(1);
- when(two.isSynthetic).thenReturn(false);
- when(one.previous).thenReturn(start);
- when(two.previous).thenReturn(one);
- when(two.type).thenReturn(TokenType.OPEN_PAREN);
- when(two.isEof).thenReturn(false);
- final request = MockCompletionRequest();
- final target = MockCompletionTarget();
- when(request.offset).thenReturn(6);
- when(request.target).thenReturn(target);
- when(target.entity).thenReturn(two);
- expect(constructQuery(request, 50), equals(['main', '(']));
- });
-
- test('elementNameFromRelevanceTag', () {
- final tag =
- 'package::flutter/src/widgets/preferred_size.dart::::PreferredSizeWidget';
- expect(elementNameFromRelevanceTag(tag), equals('PreferredSizeWidget'));
- });
-
- test('selectStringLiterals', () {
- final result = selectStringLiterals([
- MapEntry('foo', 0.2),
- MapEntry("'bar'", 0.3),
- MapEntry('\'baz\'', 0.1),
- MapEntry("'qu\'ux'", 0.4),
- ]);
- expect(result[0].key, equals('bar'));
- expect(result[1].key, equals('baz'));
- expect(result[2].key, equals('qu\'ux'));
- expect(result, hasLength(3));
- });
-
- test('testNamedArgument', () {
- expect(testNamedArgument([]), equals(false));
- expect(testNamedArgument(null), equals(false));
- expect(
- testNamedArgument([
- CompletionSuggestion(CompletionSuggestionKind.NAMED_ARGUMENT, 1,
- 'title: ,', 8, 0, false, false)
- ]),
- equals(true));
- expect(
- testNamedArgument([
- CompletionSuggestion(
- CompletionSuggestionKind.IDENTIFIER, 1, 'foo', 3, 0, false, false)
- ]),
- equals(false));
- expect(
- testNamedArgument([
- CompletionSuggestion(CompletionSuggestionKind.NAMED_ARGUMENT, 1,
- 'title: ,', 8, 0, false, false),
- CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, 1, 'foo', 3,
- 0, false, false),
- ]),
- equals(true));
- });
-}
-
-class MockAstNode extends Mock implements AstNode {}
-
-class MockCompletionRequest extends Mock implements DartCompletionRequest {}
-
-class MockCompletionTarget extends Mock implements CompletionTarget {}
-
-class MockToken extends Mock implements Token {}
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index bf9d30b..c8ccce6 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -7,8 +7,6 @@
import 'arglist_contributor_test.dart' as arglist_test;
import 'combinator_contributor_test.dart' as combinator_test;
import 'completion_manager_test.dart' as completion_manager;
-import 'completion_ranking_internal_test.dart'
- as completion_ranking_internal_test;
import 'extension_member_contributor_test.dart' as extension_member_contributor;
import 'field_formal_contributor_test.dart' as field_formal_contributor_test;
import 'imported_reference_contributor_test.dart' as imported_ref_test;
@@ -31,7 +29,6 @@
arglist_test.main();
combinator_test.main();
completion_manager.main();
- completion_ranking_internal_test.main();
extension_member_contributor.main();
field_formal_contributor_test.main();
imported_ref_test.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_in_file_test.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_in_file_test.dart
index c03d633b..482894f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_in_file_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_in_file_test.dart
@@ -88,7 +88,6 @@
''');
}
- @FailingTest(reason: 'enable once nonLintProducers are supported')
Future<void> test_fix_nonLint_isNull() async {
await resolveTestCode('''
bool f(p, q) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart b/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart
index 9a6d0ed..2e53d54 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/use_eq_eq_null_test.dart
@@ -11,11 +11,33 @@
void main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(UseEqEqNullMultiTest);
defineReflectiveTests(UseEqEqNullTest);
});
}
@reflectiveTest
+class UseEqEqNullMultiTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.USE_EQ_EQ_NULL_MULTI;
+
+ Future<void> test_isNull_all() async {
+ await resolveTestCode('''
+main(p, q) {
+ p is Null;
+ q is Null;
+}
+''');
+ await assertHasFixAllFix(HintCode.TYPE_CHECK_IS_NULL, '''
+main(p, q) {
+ p == null;
+ q == null;
+}
+''');
+ }
+}
+
+@reflectiveTest
class UseEqEqNullTest extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.USE_EQ_EQ_NULL;
@@ -32,20 +54,4 @@
}
''');
}
-
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/45026')
- Future<void> test_isNull_all() async {
- await resolveTestCode('''
-main(p, q) {
- p is Null;
- q is Null;
-}
-''');
- await assertHasFixAllFix(HintCode.TYPE_CHECK_IS_NULL, '''
-main(p, q) {
- p == null;
- q == null;
-}
-''');
- }
}
diff --git a/pkg/analyzer/lib/src/command_line/arguments.dart b/pkg/analyzer/lib/src/command_line/arguments.dart
index 4b72704..4d71ec1 100644
--- a/pkg/analyzer/lib/src/command_line/arguments.dart
+++ b/pkg/analyzer/lib/src/command_line/arguments.dart
@@ -4,13 +4,17 @@
import 'dart:collection';
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:args/args.dart';
const String analysisOptionsFileOption = 'options';
+const String defaultLanguageVersionOption = 'default-language-version';
const String defineVariableOption = 'D';
+const String enableExperimentOption = 'enable-experiment';
const String enableInitializingFormalAccessFlag = 'initializing-formal-access';
@deprecated
const String enableSuperMixinFlag = 'supermixin';
@@ -34,6 +38,14 @@
}
}
+ if (args.wasParsed(enableExperimentOption)) {
+ var flags = args[enableExperimentOption] as List<String>;
+ options.contextFeatures = FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
+ flags: flags,
+ );
+ }
+
if (args.wasParsed(implicitCastsFlag)) {
options.implicitCasts = args[implicitCastsFlag];
verbose('$implicitCastsFlag = ${options.implicitCasts}');
@@ -136,6 +148,10 @@
help: 'Disable declaration casts in strong mode (https://goo.gl/cTLz40)\n'
'This option is now ignored and will be removed in a future release.',
hide: ddc && hide);
+ parser.addMultiOption(enableExperimentOption,
+ help: 'Enable one or more experimental features. If multiple features '
+ 'are being added, they should be comma separated.',
+ splitCommas: true);
parser.addFlag(implicitCastsFlag,
negatable: true,
help: 'Disable implicit casts in strong mode (https://goo.gl/cTLz40).',
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index cb27bce..f8ac509 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -102,10 +102,15 @@
/// Return an analysis driver that is configured correctly to analyze code in
/// the directory with the given [path].
- AnalysisDriver buildDriver(ContextRoot contextRoot, Workspace workspace) {
+ AnalysisDriver buildDriver(ContextRoot contextRoot, Workspace workspace,
+ {void Function(AnalysisOptionsImpl)? updateAnalysisOptions}) {
String path = contextRoot.root;
var options = getAnalysisOptions(path, workspace, contextRoot: contextRoot);
+
+ if (updateAnalysisOptions != null) {
+ updateAnalysisOptions(options);
+ }
//_processAnalysisOptions(context, optionMap);
SummaryDataStore? summaryData;
diff --git a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
index d610cce..4de4a89 100644
--- a/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/analysis_context_collection.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:cli_util/cli_util.dart';
/// An implementation of [AnalysisContextCollection].
@@ -39,6 +40,7 @@
bool retainDataForTesting = false,
String? sdkPath,
AnalysisDriverScheduler? scheduler,
+ void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
}) : resourceProvider =
resourceProvider ?? PhysicalResourceProvider.INSTANCE {
sdkPath ??= getSdkPath();
@@ -71,6 +73,7 @@
retainDataForTesting: retainDataForTesting,
sdkPath: sdkPath,
scheduler: scheduler,
+ updateAnalysisOptions: updateAnalysisOptions,
);
contexts.add(context);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 4fcd8c8..ffead36 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -20,6 +20,7 @@
show FileContentOverlay;
import 'package:analyzer/src/dart/analysis/performance_logger.dart'
show PerformanceLog;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
import 'package:analyzer/src/generated/source.dart' show ContentCache;
import 'package:cli_util/cli_util.dart';
@@ -37,19 +38,21 @@
resourceProvider ?? PhysicalResourceProvider.INSTANCE;
@override
- AnalysisContext createContext(
- {ByteStore? byteStore,
- required ContextRoot contextRoot,
- DeclaredVariables? declaredVariables,
- bool drainStreams = true,
- bool enableIndex = false,
- FileContentOverlay? fileContentOverlay,
- List<String>? librarySummaryPaths,
- PerformanceLog? performanceLog,
- bool retainDataForTesting = false,
- AnalysisDriverScheduler? scheduler,
- String? sdkPath,
- String? sdkSummaryPath}) {
+ AnalysisContext createContext({
+ ByteStore? byteStore,
+ required ContextRoot contextRoot,
+ DeclaredVariables? declaredVariables,
+ bool drainStreams = true,
+ bool enableIndex = false,
+ FileContentOverlay? fileContentOverlay,
+ List<String>? librarySummaryPaths,
+ PerformanceLog? performanceLog,
+ bool retainDataForTesting = false,
+ AnalysisDriverScheduler? scheduler,
+ String? sdkPath,
+ String? sdkSummaryPath,
+ void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
+ }) {
// TODO(scheglov) Remove this, and make `sdkPath` required.
sdkPath ??= getSdkPath();
ArgumentError.checkNotNull(sdkPath, 'sdkPath');
@@ -93,8 +96,11 @@
old.ContextRoot oldContextRoot = old.ContextRoot(
contextRoot.root.path, contextRoot.excludedPaths.toList(),
pathContext: resourceProvider.pathContext);
- AnalysisDriver driver =
- builder.buildDriver(oldContextRoot, contextRoot.workspace);
+ AnalysisDriver driver = builder.buildDriver(
+ oldContextRoot,
+ contextRoot.workspace,
+ updateAnalysisOptions: updateAnalysisOptions,
+ );
// AnalysisDriver reports results into streams.
// We need to drain these streams to avoid memory leak.
diff --git a/pkg/analyzer/test/src/command_line/arguments_test.dart b/pkg/analyzer/test/src/command_line/arguments_test.dart
index 83b2bda..139dcda5 100644
--- a/pkg/analyzer/test/src/command_line/arguments_test.dart
+++ b/pkg/analyzer/test/src/command_line/arguments_test.dart
@@ -83,7 +83,7 @@
void test_defineAnalysisArguments() {
ArgParser parser = ArgParser();
defineAnalysisArguments(parser);
- expect(parser.options, hasLength(11));
+ expect(parser.options, hasLength(12));
}
void test_extractDefinedVariables() {
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index 5869b63..709a567 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -1293,13 +1293,15 @@
_assertAnalyzedFiles(root, pathList);
}
- void _assertBasicWorkspace(Workspace _workspace, String root) {
+ void _assertBasicWorkspace(Workspace _workspace, String posixRoot) {
var workspace = _workspace as BasicWorkspace;
+ var root = convertPath(posixRoot);
expect(workspace.root, root);
}
- void _assertBazelWorkspace(Workspace _workspace, String root) {
+ void _assertBazelWorkspace(Workspace _workspace, String posixRoot) {
var workspace = _workspace as BazelWorkspace;
+ var root = convertPath(posixRoot);
expect(workspace.root, root);
}
@@ -1310,8 +1312,9 @@
}
}
- void _assertPubWorkspace(Workspace _workspace, String root) {
+ void _assertPubWorkspace(Workspace _workspace, String posixRoot) {
var workspace = _workspace as PubWorkspace;
+ var root = convertPath(posixRoot);
expect(workspace.root, root);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
index 3ba688b..90eb23e 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
@@ -61,7 +61,7 @@
var root = _createContextRoot(rootPath);
root.included.add(includedFile);
- _addGlob(root, '$rootPath/lib/a*.dart');
+ _addGlob(root, 'lib/a*.dart');
// Explicitly included, so analyzed even if excluded by a glob.
expect(root.isAnalyzed(includedFile.path), isTrue);
@@ -91,8 +91,8 @@
var root = _createContextRoot(rootPath);
root.included.add(includedFolder);
- _addGlob(root, '$rootPath/lib/src/**');
- _addGlob(root, '$rootPath/lib/**.g.dart');
+ _addGlob(root, 'lib/src/**');
+ _addGlob(root, 'lib/**.g.dart');
// Explicitly included, so analyzed even if excluded by a glob.
expect(root.isAnalyzed(includedFolder.path), isTrue);
@@ -198,8 +198,13 @@
expect(contextRoot.isAnalyzed(folderPath), isTrue);
}
- void _addGlob(ContextRootImpl root, String pattern) {
- var glob = Glob(pattern, context: resourceProvider.pathContext);
+ void _addGlob(ContextRootImpl root, String posixPattern) {
+ var pathContext = root.resourceProvider.pathContext;
+ var pattern = posix.joinAll([
+ ...pathContext.split(root.root.path),
+ ...posix.split(posixPattern),
+ ]);
+ var glob = Glob(pattern, context: pathContext);
root.excludedGlobs.add(glob);
}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index a98502e..dde233c 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -11,13 +11,15 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/command_line/arguments.dart'
+ show applyAnalysisOptionFlags;
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/results.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/interner.dart';
import 'package:analyzer/src/generated/java_engine.dart';
@@ -573,13 +575,9 @@
packagesFile: _commandLineOptions.packageConfigPath,
resourceProvider: _resourceProvider,
sdkPath: _commandLineOptions.dartSdkPath,
+ updateAnalysisOptions: _updateAnalysisOptions,
);
- for (var _analysisContext in _collection.contexts) {
- var analysisContext = _analysisContext as DriverBasedAnalysisContext;
- _configureAnalysisOptionsFromCommandLineOptions(analysisContext);
- }
-
_setContextForPath(path);
_folderContexts[parentFolder] = _analysisContext;
}
@@ -597,36 +595,22 @@
_pathList = pathList;
}
- /// TODO(scheglov) Patch options before we create the driver.
- void _configureAnalysisOptionsFromCommandLineOptions(
- DriverBasedAnalysisContext analysisContext,
- ) {
- var analysisDriver = analysisContext.driver;
- var optionsImpl = analysisDriver.analysisOptions as AnalysisOptionsImpl;
-
- if (_commandLineOptions.enabledExperiments != null) {
- optionsImpl.contextFeatures = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.currentVersion,
- flags: _commandLineOptions.enabledExperiments,
- );
- }
-
- if (_commandLineOptions.defaultLanguageVersion != null) {
- var nonPackageLanguageVersion = Version.parse(
- _commandLineOptions.defaultLanguageVersion + '.0',
- );
- optionsImpl.nonPackageLanguageVersion = nonPackageLanguageVersion;
- optionsImpl.nonPackageFeatureSet = FeatureSet.latestLanguageVersion()
- .restrictToVersion(nonPackageLanguageVersion);
- }
-
- analysisDriver.configure(
- analysisOptions: optionsImpl,
- );
- }
-
void _setContextForPath(String path) {
var analysisContext = _collection.contextFor(path);
_analysisContext = analysisContext as DriverBasedAnalysisContext;
}
+
+ void _updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
+ var args = _commandLineOptions.contextBuilderOptions.argResults;
+ applyAnalysisOptionFlags(analysisOptions, args);
+
+ var defaultLanguageVersion = _commandLineOptions.defaultLanguageVersion;
+ if (defaultLanguageVersion != null) {
+ var nonPackageLanguageVersion =
+ Version.parse('$defaultLanguageVersion.0');
+ analysisOptions.nonPackageLanguageVersion = nonPackageLanguageVersion;
+ analysisOptions.nonPackageFeatureSet = FeatureSet.latestLanguageVersion()
+ .restrictToVersion(nonPackageLanguageVersion);
+ }
+ }
}
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index fc2ad75..faba081 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -308,11 +308,6 @@
help: 'Print the analyzer version.',
defaultsTo: false,
negatable: false)
- ..addMultiOption('enable-experiment',
- help:
- 'Enable one or more experimental features. If multiple features '
- 'are being added, they should be comma separated.',
- splitCommas: true)
..addFlag('no-hints',
help: 'Do not show hint results.',
defaultsTo: false,
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index 9ae49f6..dd07c76 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -76,10 +76,18 @@
void VirtualMemory::Init() {
#if defined(DART_COMPRESSED_POINTERS)
if (VirtualMemoryCompressedHeap::GetRegion() == nullptr) {
- VirtualMemoryCompressedHeap::Init(GenericMapAligned(
+ void* address = GenericMapAligned(
PROT_READ | PROT_WRITE, kCompressedHeapSize, kCompressedHeapAlignment,
kCompressedHeapSize + kCompressedHeapAlignment,
- MAP_PRIVATE | MAP_ANONYMOUS));
+ MAP_PRIVATE | MAP_ANONYMOUS);
+ if (address == nullptr) {
+ int error = errno;
+ const int kBufferSize = 1024;
+ char error_buf[kBufferSize];
+ FATAL2("Failed to reserve region for compressed heap: %d (%s)", error,
+ Utils::StrError(error, error_buf, kBufferSize));
+ }
+ VirtualMemoryCompressedHeap::Init(address);
}
#endif // defined(DART_COMPRESSED_POINTERS)
@@ -328,7 +336,7 @@
#endif // defined(HOST_OS_MACOS)
void* address =
GenericMapAligned(prot, size, alignment, allocated_size, map_flags);
- if (address == MAP_FAILED) {
+ if (address == nullptr) {
return nullptr;
}
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index f7322fb..994833d 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -55,9 +55,20 @@
page_size_ = CalculatePageSize();
#if defined(DART_COMPRESSED_POINTERS)
- VirtualMemoryCompressedHeap::Init(AllocateAlignedImpl(
- kCompressedHeapSize, kCompressedHeapAlignment,
- kCompressedHeapSize + kCompressedHeapAlignment, PAGE_READWRITE, nullptr));
+ if (VirtualMemoryCompressedHeap::GetRegion() == nullptr) {
+ void* address =
+ AllocateAlignedImpl(kCompressedHeapSize, kCompressedHeapAlignment,
+ kCompressedHeapSize + kCompressedHeapAlignment,
+ PAGE_READWRITE, nullptr);
+ if (address == nullptr) {
+ int error = GetLastError();
+ const int kBufferSize = 1024;
+ char error_buf[kBufferSize];
+ FATAL2("Failed to reserve region for compressed heap: %d (%s)", error,
+ Utils::StrError(error, error_buf, kBufferSize));
+ }
+ VirtualMemoryCompressedHeap::Init(address);
+ }
#endif // defined(DART_COMPRESSED_POINTERS)
}
diff --git a/tools/VERSION b/tools/VERSION
index 3a05acd..1a5366c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 104
+PRERELEASE 105
PRERELEASE_PATCH 0
\ No newline at end of file