Migrate analysis_server and analysis_server_client protocol.

Change-Id: Ie0912627733f0481de0d3239647a4978e5327f12
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193641
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-04-02 06:46:41 +00:00 committed by commit-bot@chromium.org
parent db6f65e661
commit c2d660d161
28 changed files with 3914 additions and 12473 deletions

View file

@ -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
/// Support for client code that needs to interact with the requests, responses
/// and notifications that are part of the analysis server's wire protocol.
import 'dart:convert' hide JsonDecoder;
@ -30,7 +28,7 @@ class Notification {
/// A table mapping the names of notification parameters to their values, or
/// `null` if there are no notification parameters.
final Map<String, Object> params;
final Map<String, Object>? params;
/// Initialize a newly created [Notification] to have the given [event] name.
/// If [params] is provided, it will be used as the params; otherwise no
@ -40,7 +38,7 @@ class Notification {
/// Initialize a newly created instance based on the given JSON data.
factory Notification.fromJson(Map json) {
return Notification(json[Notification.EVENT],
json[Notification.PARAMS] as Map<String, Object>);
json[Notification.PARAMS] as Map<String, Object>?);
}
/// Return a table representing the structure of the Json object that will be
@ -48,6 +46,7 @@ class Notification {
Map<String, Object> toJson() {
var jsonObject = <String, Object>{};
jsonObject[EVENT] = event;
var params = this.params;
if (params != null) {
jsonObject[PARAMS] = params;
}
@ -79,84 +78,18 @@ class Request {
final String method;
/// A table mapping the names of request parameters to their values.
final Map<String, Object> params;
final Map<String, Object?> params;
/// The time (milliseconds since epoch) at which the client made the request
/// or `null` if this information is not provided by the client.
final int clientRequestTime;
final int? clientRequestTime;
/// Initialize a newly created [Request] to have the given [id] and [method]
/// name. If [params] is supplied, it is used as the "params" map for the
/// request. Otherwise an empty "params" map is allocated.
Request(this.id, this.method,
[Map<String, Object> params, this.clientRequestTime])
: params = params ?? <String, Object>{};
/// Return a request parsed from the given json, or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
factory Request.fromJson(Map<String, Object> result) {
var id = result[Request.ID];
var method = result[Request.METHOD];
if (id is! String || method is! String) {
return null;
}
var time = result[Request.CLIENT_REQUEST_TIME];
if (time != null && time is! int) {
return null;
}
var params = result[Request.PARAMS];
if (params is Map || params == null) {
return Request(id, method, params as Map<String, Object>, time);
} else {
return null;
}
}
/// Return a request parsed from the given [data], or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
factory Request.fromString(String data) {
try {
var result = json.decode(data);
if (result is Map) {
return Request.fromJson(result as Map<String, dynamic>);
}
return null;
} catch (exception) {
return null;
}
}
[Map<String, Object?>? params, this.clientRequestTime])
: params = params ?? <String, Object?>{};
@override
int get hashCode {
@ -181,13 +114,14 @@ class Request {
if (params.isNotEmpty) {
jsonObject[PARAMS] = params;
}
var clientRequestTime = this.clientRequestTime;
if (clientRequestTime != null) {
jsonObject[CLIENT_REQUEST_TIME] = clientRequestTime;
}
return jsonObject;
}
bool _equalLists(List first, List second) {
bool _equalLists(List? first, List? second) {
if (first == null) {
return second == null;
}
@ -206,7 +140,7 @@ class Request {
return true;
}
bool _equalMaps(Map first, Map second) {
bool _equalMaps(Map? first, Map? second) {
if (first == null) {
return second == null;
}
@ -227,7 +161,7 @@ class Request {
return true;
}
bool _equalObjects(Object first, Object second) {
bool _equalObjects(Object? first, Object? second) {
if (first == null) {
return second == null;
}
@ -248,6 +182,72 @@ class Request {
}
return first == second;
}
/// Return a request parsed from the given json, or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
static Request? fromJson(Map<String, Object?> result) {
var id = result[Request.ID];
var method = result[Request.METHOD];
if (id is! String || method is! String) {
return null;
}
var time = result[Request.CLIENT_REQUEST_TIME];
if (time is! int?) {
return null;
}
var params = result[Request.PARAMS];
if (params is Map<String, Object?>?) {
return Request(id, method, params, time);
} else {
return null;
}
}
/// Return a request parsed from the given [data], or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
static Request? fromString(String data) {
try {
var result = json.decode(data);
if (result is Map<String, Object?>) {
return Request.fromJson(result);
}
return null;
} catch (exception) {
return null;
}
}
}
/// An exception that occurred during the handling of a request that requires
@ -297,11 +297,11 @@ class Response {
/// The error that was caused by attempting to handle the request, or `null`
/// if there was no error.
final RequestError error;
final RequestError? error;
/// A table mapping the names of result fields to their values. Should be
/// `null` if there is no result to send.
Map<String, Object> result;
Map<String, Object?>? result;
/// Initialize a newly created instance to represent a response to a request
/// with the given [id]. If [_result] is provided, it will be used as the
@ -336,30 +336,6 @@ class Response {
error: RequestError(RequestErrorCode.FORMAT_WITH_ERRORS,
'Error during `edit.format`: source contains syntax errors.'));
/// Initialize a newly created instance based on the given JSON data.
factory Response.fromJson(Map json) {
try {
Object id = json[Response.ID];
if (id is! String) {
return null;
}
Object error = json[Response.ERROR];
RequestError decodedError;
if (error is Map) {
decodedError =
RequestError.fromJson(ResponseDecoder(null), '.error', error);
}
Object result = json[Response.RESULT];
Map<String, Object> decodedResult;
if (result is Map) {
decodedResult = result as Map<String, Object>;
}
return Response(id, error: decodedError, result: decodedResult);
} catch (exception) {
return null;
}
}
/// Initialize a newly created instance to represent the
/// GET_ERRORS_INVALID_FILE error condition.
Response.getErrorsInvalidFile(Request request)
@ -529,12 +505,41 @@ class Response {
Map<String, Object> toJson() {
var jsonObject = <String, Object>{};
jsonObject[ID] = id;
var error = this.error;
if (error != null) {
jsonObject[ERROR] = error.toJson();
}
var result = this.result;
if (result != null) {
jsonObject[RESULT] = result;
}
return jsonObject;
}
/// Initialize a newly created instance based on the given JSON data.
static Response? fromJson(Map<String, Object?> json) {
try {
var id = json[Response.ID];
if (id is! String) {
return null;
}
RequestError? decodedError;
var error = json[Response.ERROR];
if (error is Map) {
decodedError =
RequestError.fromJson(ResponseDecoder(null), '.error', error);
}
Map<String, Object?>? decodedResult;
var result = json[Response.RESULT];
if (result is Map<String, Object?>) {
decodedResult = result;
}
return Response(id, error: decodedError, result: decodedResult);
} catch (exception) {
return null;
}
}
}

View file

@ -6,8 +6,6 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
// @dart = 2.9
const String PROTOCOL_VERSION = '1.32.5';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';

File diff suppressed because it is too large Load diff

View file

@ -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:collection';
import 'dart:convert' hide JsonDecoder;
@ -31,8 +29,8 @@ String applySequenceOfEdits(String code, Iterable<SourceEdit> edits) {
/// Compare the lists [listA] and [listB], using [itemEqual] to compare
/// list elements.
bool listEqual<T1, T2>(
List<T1> listA, List<T2> listB, bool Function(T1 a, T2 b) itemEqual) {
bool listEqual<T>(
List<T>? listA, List<T>? listB, bool Function(T a, T b) itemEqual) {
if (listA == null) {
return listB == null;
}
@ -53,7 +51,7 @@ bool listEqual<T1, T2>(
/// Compare the maps [mapA] and [mapB], using [valueEqual] to compare map
/// values.
bool mapEqual<K, V>(
Map<K, V> mapA, Map<K, V> mapB, bool Function(V a, V b) valueEqual) {
Map<K, V>? mapA, Map<K, V>? mapB, bool Function(V a, V b) valueEqual) {
if (mapA == null) {
return mapB == null;
}
@ -63,11 +61,11 @@ bool mapEqual<K, V>(
if (mapA.length != mapB.length) {
return false;
}
for (var key in mapA.keys) {
if (!mapB.containsKey(key)) {
return false;
}
if (!valueEqual(mapA[key], mapB[key])) {
for (var entryA in mapA.entries) {
var key = entryA.key;
var valueA = entryA.value;
var valueB = mapB[key];
if (valueB == null || !valueEqual(valueA, valueB)) {
return false;
}
}
@ -77,7 +75,7 @@ bool mapEqual<K, V>(
/// Translate the input [map], applying [keyCallback] to all its keys, and
/// [valueCallback] to all its values.
Map<KR, VR> mapMap<KP, VP, KR, VR>(Map<KP, VP> map,
{KR Function(KP key) keyCallback, VR Function(VP value) valueCallback}) {
{KR Function(KP key)? keyCallback, VR Function(VP value)? valueCallback}) {
Map<KR, VR> result = HashMap<KR, VR>();
map.forEach((key, value) {
KR resultKey;
@ -98,8 +96,8 @@ Map<KR, VR> mapMap<KP, VP, KR, VR>(Map<KP, VP> map,
}
/// Create a [RefactoringFeedback] corresponding the given [kind].
RefactoringFeedback refactoringFeedbackFromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
RefactoringFeedback? refactoringFeedbackFromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json, Map feedbackJson) {
var kind = jsonDecoder.refactoringKind;
if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
return ExtractLocalVariableFeedback.fromJson(jsonDecoder, jsonPath, json);
@ -123,8 +121,8 @@ RefactoringFeedback refactoringFeedbackFromJson(
}
/// Create a [RefactoringOptions] corresponding the given [kind].
RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
String jsonPath, Object json, RefactoringKind kind) {
RefactoringOptions? refactoringOptionsFromJson(JsonDecoder jsonDecoder,
String jsonPath, Object? json, RefactoringKind kind) {
if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
return ExtractLocalVariableOptions.fromJson(jsonDecoder, jsonPath, json);
}
@ -162,13 +160,13 @@ class RequestDecoder extends JsonDecoder {
RequestDecoder(this._request);
@override
RefactoringKind get refactoringKind {
RefactoringKind? get refactoringKind {
// Refactoring feedback objects should never appear in requests.
return null;
}
@override
dynamic mismatch(String jsonPath, String expected, [Object actual]) {
Object mismatch(String jsonPath, String expected, [Object? actual]) {
var buffer = StringBuffer();
buffer.write('Expected to be ');
buffer.write(expected);
@ -182,7 +180,7 @@ class RequestDecoder extends JsonDecoder {
}
@override
dynamic missingKey(String jsonPath, String key) {
Object missingKey(String jsonPath, String key) {
return RequestFailure(Response.invalidParameter(
_request, jsonPath, 'Expected to contain key ${json.encode(key)}'));
}
@ -198,12 +196,12 @@ abstract class RequestParams implements HasToJson {
/// used only for testing. Errors are reported using bare [Exception] objects.
class ResponseDecoder extends JsonDecoder {
@override
final RefactoringKind refactoringKind;
final RefactoringKind? refactoringKind;
ResponseDecoder(this.refactoringKind);
@override
dynamic mismatch(String jsonPath, String expected, [Object actual]) {
Object mismatch(String jsonPath, String expected, [Object? actual]) {
var buffer = StringBuffer();
buffer.write('Expected ');
buffer.write(expected);
@ -218,7 +216,7 @@ class ResponseDecoder extends JsonDecoder {
}
@override
dynamic missingKey(String jsonPath, String key) {
Object missingKey(String jsonPath, String key) {
return Exception('Missing key $key at $jsonPath');
}
}

View file

@ -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
const String CODE = 'code';
const String COMPLETION_RESULTS = 'completion.results';
const String CONTEXT_MESSAGES = 'contextMessages';

View file

@ -6,8 +6,6 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
// @dart = 2.9
/// Convenience methods for running integration tests.
import 'dart:async';
@ -81,10 +79,10 @@ abstract class IntegrationTestMixin {
/// pid: int
///
/// The process id of the analysis server process.
Stream<ServerConnectedParams> onServerConnected;
late Stream<ServerConnectedParams> onServerConnected;
/// Stream controller for [onServerConnected].
StreamController<ServerConnectedParams> _onServerConnected;
late StreamController<ServerConnectedParams> _onServerConnected;
/// Reports that an unexpected error has occurred while executing the server.
/// This notification is not used for problems with specific requests (which
@ -109,20 +107,20 @@ abstract class IntegrationTestMixin {
///
/// The stack trace associated with the generation of the error, used for
/// debugging the server.
Stream<ServerErrorParams> onServerError;
late Stream<ServerErrorParams> onServerError;
/// Stream controller for [onServerError].
StreamController<ServerErrorParams> _onServerError;
late StreamController<ServerErrorParams> _onServerError;
/// The stream of entries describing events happened in the server.
///
/// Parameters
///
/// entry: ServerLogEntry
Stream<ServerLogParams> onServerLog;
late Stream<ServerLogParams> onServerLog;
/// Stream controller for [onServerLog].
StreamController<ServerLogParams> _onServerLog;
late StreamController<ServerLogParams> _onServerLog;
/// Reports the current status of the server. Parameters are omitted if there
/// has been no change in the status represented by that parameter.
@ -145,10 +143,10 @@ abstract class IntegrationTestMixin {
///
/// Note: this status type is deprecated, and is no longer sent by the
/// server.
Stream<ServerStatusParams> onServerStatus;
late Stream<ServerStatusParams> onServerStatus;
/// Stream controller for [onServerStatus].
StreamController<ServerStatusParams> _onServerStatus;
late StreamController<ServerStatusParams> _onServerStatus;
/// Return the errors associated with the given file. If the errors for the
/// given file have not yet been computed, or the most recently computed
@ -492,7 +490,7 @@ abstract class IntegrationTestMixin {
/// that the normal pubspec.yaml mechanism should always be used.
Future sendAnalysisSetAnalysisRoots(
List<String> included, List<String> excluded,
{Map<String, String> packageRoots}) async {
{Map<String, String>? packageRoots}) async {
var params = AnalysisSetAnalysisRootsParams(included, excluded,
packageRoots: packageRoots)
.toJson();
@ -646,10 +644,10 @@ abstract class IntegrationTestMixin {
/// directories: List<FilePath>
///
/// A list of the paths of the files that are being analyzed.
Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles;
late Stream<AnalysisAnalyzedFilesParams> onAnalysisAnalyzedFiles;
/// Stream controller for [onAnalysisAnalyzedFiles].
StreamController<AnalysisAnalyzedFilesParams> _onAnalysisAnalyzedFiles;
late StreamController<AnalysisAnalyzedFilesParams> _onAnalysisAnalyzedFiles;
/// Reports closing labels relevant to a given file.
///
@ -672,10 +670,10 @@ abstract class IntegrationTestMixin {
/// constructor/method calls and List arguments that span multiple lines.
/// Note that the ranges that are returned can overlap each other because
/// they may be associated with constructs that can be nested.
Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels;
late Stream<AnalysisClosingLabelsParams> onAnalysisClosingLabels;
/// Stream controller for [onAnalysisClosingLabels].
StreamController<AnalysisClosingLabelsParams> _onAnalysisClosingLabels;
late StreamController<AnalysisClosingLabelsParams> _onAnalysisClosingLabels;
/// Reports the errors associated with a given file. The set of errors
/// included in the notification is always a complete list that supersedes
@ -690,10 +688,10 @@ abstract class IntegrationTestMixin {
/// errors: List<AnalysisError>
///
/// The errors contained in the file.
Stream<AnalysisErrorsParams> onAnalysisErrors;
late Stream<AnalysisErrorsParams> onAnalysisErrors;
/// Stream controller for [onAnalysisErrors].
StreamController<AnalysisErrorsParams> _onAnalysisErrors;
late StreamController<AnalysisErrorsParams> _onAnalysisErrors;
/// Reports that any analysis results that were previously associated with
/// the given files should be considered to be invalid because those files
@ -713,10 +711,10 @@ abstract class IntegrationTestMixin {
/// files: List<FilePath>
///
/// The files that are no longer being analyzed.
Stream<AnalysisFlushResultsParams> onAnalysisFlushResults;
late Stream<AnalysisFlushResultsParams> onAnalysisFlushResults;
/// Stream controller for [onAnalysisFlushResults].
StreamController<AnalysisFlushResultsParams> _onAnalysisFlushResults;
late StreamController<AnalysisFlushResultsParams> _onAnalysisFlushResults;
/// Reports the folding regions associated with a given file. Folding regions
/// can be nested, but will not be overlapping. Nesting occurs when a
@ -736,10 +734,10 @@ abstract class IntegrationTestMixin {
/// regions: List<FoldingRegion>
///
/// The folding regions contained in the file.
Stream<AnalysisFoldingParams> onAnalysisFolding;
late Stream<AnalysisFoldingParams> onAnalysisFolding;
/// Stream controller for [onAnalysisFolding].
StreamController<AnalysisFoldingParams> _onAnalysisFolding;
late StreamController<AnalysisFoldingParams> _onAnalysisFolding;
/// Reports the highlight regions associated with a given file.
///
@ -760,10 +758,10 @@ abstract class IntegrationTestMixin {
/// some range. Note that the highlight regions that are returned can
/// overlap other highlight regions if there is more than one meaning
/// associated with a particular region.
Stream<AnalysisHighlightsParams> onAnalysisHighlights;
late Stream<AnalysisHighlightsParams> onAnalysisHighlights;
/// Stream controller for [onAnalysisHighlights].
StreamController<AnalysisHighlightsParams> _onAnalysisHighlights;
late StreamController<AnalysisHighlightsParams> _onAnalysisHighlights;
/// Reports the classes that are implemented or extended and class members
/// that are implemented or overridden in a file.
@ -785,10 +783,10 @@ abstract class IntegrationTestMixin {
/// members: List<ImplementedMember>
///
/// The member defined in the file that are implemented or overridden.
Stream<AnalysisImplementedParams> onAnalysisImplemented;
late Stream<AnalysisImplementedParams> onAnalysisImplemented;
/// Stream controller for [onAnalysisImplemented].
StreamController<AnalysisImplementedParams> _onAnalysisImplemented;
late StreamController<AnalysisImplementedParams> _onAnalysisImplemented;
/// Reports that the navigation information associated with a region of a
/// single file has become invalid and should be re-requested.
@ -816,10 +814,10 @@ abstract class IntegrationTestMixin {
/// The delta to be applied to the offsets in information that follows the
/// invalidated region in order to update it so that it doesn't need to be
/// re-requested.
Stream<AnalysisInvalidateParams> onAnalysisInvalidate;
late Stream<AnalysisInvalidateParams> onAnalysisInvalidate;
/// Stream controller for [onAnalysisInvalidate].
StreamController<AnalysisInvalidateParams> _onAnalysisInvalidate;
late StreamController<AnalysisInvalidateParams> _onAnalysisInvalidate;
/// Reports the navigation targets associated with a given file.
///
@ -852,10 +850,10 @@ abstract class IntegrationTestMixin {
///
/// The files containing navigation targets referenced in the file. They
/// are referenced by NavigationTargets by their index in this array.
Stream<AnalysisNavigationParams> onAnalysisNavigation;
late Stream<AnalysisNavigationParams> onAnalysisNavigation;
/// Stream controller for [onAnalysisNavigation].
StreamController<AnalysisNavigationParams> _onAnalysisNavigation;
late StreamController<AnalysisNavigationParams> _onAnalysisNavigation;
/// Reports the occurrences of references to elements within a single file.
///
@ -872,10 +870,10 @@ abstract class IntegrationTestMixin {
/// occurrences: List<Occurrences>
///
/// The occurrences of references to elements within the file.
Stream<AnalysisOccurrencesParams> onAnalysisOccurrences;
late Stream<AnalysisOccurrencesParams> onAnalysisOccurrences;
/// Stream controller for [onAnalysisOccurrences].
StreamController<AnalysisOccurrencesParams> _onAnalysisOccurrences;
late StreamController<AnalysisOccurrencesParams> _onAnalysisOccurrences;
/// Reports the outline associated with a single file.
///
@ -904,10 +902,10 @@ abstract class IntegrationTestMixin {
/// outline: Outline
///
/// The outline associated with the file.
Stream<AnalysisOutlineParams> onAnalysisOutline;
late Stream<AnalysisOutlineParams> onAnalysisOutline;
/// Stream controller for [onAnalysisOutline].
StreamController<AnalysisOutlineParams> _onAnalysisOutline;
late StreamController<AnalysisOutlineParams> _onAnalysisOutline;
/// Reports the overriding members in a file.
///
@ -924,10 +922,10 @@ abstract class IntegrationTestMixin {
/// overrides: List<Override>
///
/// The overrides associated with the file.
Stream<AnalysisOverridesParams> onAnalysisOverrides;
late Stream<AnalysisOverridesParams> onAnalysisOverrides;
/// Stream controller for [onAnalysisOverrides].
StreamController<AnalysisOverridesParams> _onAnalysisOverrides;
late StreamController<AnalysisOverridesParams> _onAnalysisOverrides;
/// Request that completion suggestions for the given offset in the given
/// file be returned.
@ -1117,10 +1115,10 @@ abstract class IntegrationTestMixin {
///
/// If an AvailableSuggestion has relevance tags that match more than one
/// IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
Stream<CompletionResultsParams> onCompletionResults;
late Stream<CompletionResultsParams> onCompletionResults;
/// Stream controller for [onCompletionResults].
StreamController<CompletionResultsParams> _onCompletionResults;
late StreamController<CompletionResultsParams> _onCompletionResults;
/// Reports the pre-computed, candidate completions from symbols defined in a
/// corresponding library. This notification may be sent multiple times. When
@ -1140,10 +1138,11 @@ abstract class IntegrationTestMixin {
/// removedLibraries: List<int> (optional)
///
/// A list of library ids that no longer apply.
Stream<CompletionAvailableSuggestionsParams> onCompletionAvailableSuggestions;
late Stream<CompletionAvailableSuggestionsParams>
onCompletionAvailableSuggestions;
/// Stream controller for [onCompletionAvailableSuggestions].
StreamController<CompletionAvailableSuggestionsParams>
late StreamController<CompletionAvailableSuggestionsParams>
_onCompletionAvailableSuggestions;
/// Reports existing imports in a library. This notification may be sent
@ -1159,10 +1158,10 @@ abstract class IntegrationTestMixin {
/// imports: ExistingImports
///
/// The existing imports in the library.
Stream<CompletionExistingImportsParams> onCompletionExistingImports;
late Stream<CompletionExistingImportsParams> onCompletionExistingImports;
/// Stream controller for [onCompletionExistingImports].
StreamController<CompletionExistingImportsParams>
late StreamController<CompletionExistingImportsParams>
_onCompletionExistingImports;
/// Perform a search for references to the element defined or referenced at
@ -1325,7 +1324,7 @@ abstract class IntegrationTestMixin {
///
/// The list of the paths of files with declarations.
Future<SearchGetElementDeclarationsResult> sendSearchGetElementDeclarations(
{String file, String pattern, int maxResults}) async {
{String? file, String? pattern, int? maxResults}) async {
var params = SearchGetElementDeclarationsParams(
file: file, pattern: pattern, maxResults: maxResults)
.toJson();
@ -1369,7 +1368,7 @@ abstract class IntegrationTestMixin {
/// to allow a type hierarchy to be produced.
Future<SearchGetTypeHierarchyResult> sendSearchGetTypeHierarchy(
String file, int offset,
{bool superOnly}) async {
{bool? superOnly}) async {
var params =
SearchGetTypeHierarchyParams(file, offset, superOnly: superOnly)
.toJson();
@ -1397,10 +1396,10 @@ abstract class IntegrationTestMixin {
///
/// True if this is that last set of results that will be returned for the
/// indicated search.
Stream<SearchResultsParams> onSearchResults;
late Stream<SearchResultsParams> onSearchResults;
/// Stream controller for [onSearchResults].
StreamController<SearchResultsParams> _onSearchResults;
late StreamController<SearchResultsParams> _onSearchResults;
/// Format the contents of a single file. The currently selected region of
/// text is passed in so that the selection can be preserved across the
@ -1450,7 +1449,7 @@ abstract class IntegrationTestMixin {
/// The length of the selection after formatting the code.
Future<EditFormatResult> sendEditFormat(
String file, int selectionOffset, int selectionLength,
{int lineLength}) async {
{int? lineLength}) async {
var params = EditFormatParams(file, selectionOffset, selectionLength,
lineLength: lineLength)
.toJson();
@ -1580,7 +1579,7 @@ abstract class IntegrationTestMixin {
/// Details that summarize the fixes associated with the recommended
/// changes.
Future<EditBulkFixesResult> sendEditBulkFixes(List<String> included,
{bool inTestMode}) async {
{bool? inTestMode}) async {
var params = EditBulkFixesParams(included, inTestMode: inTestMode).toJson();
var result = await server.send('edit.bulkFixes', params);
var decoder = ResponseDecoder(null);
@ -1681,11 +1680,11 @@ abstract class IntegrationTestMixin {
/// proposed changes. There is one URL for each of the included file paths.
/// The field is omitted if a preview was not requested.
Future<EditDartfixResult> sendEditDartfix(List<String> included,
{List<String> includedFixes,
bool includePedanticFixes,
List<String> excludedFixes,
int port,
String outputDir}) async {
{List<String>? includedFixes,
bool? includePedanticFixes,
List<String>? excludedFixes,
int? port,
String? outputDir}) async {
var params = EditDartfixParams(included,
includedFixes: includedFixes,
includePedanticFixes: includePedanticFixes,
@ -1841,7 +1840,7 @@ abstract class IntegrationTestMixin {
/// the refactoring.
Future<EditGetRefactoringResult> sendEditGetRefactoring(RefactoringKind kind,
String file, int offset, int length, bool validateOnly,
{RefactoringOptions options}) async {
{RefactoringOptions? options}) async {
var params = EditGetRefactoringParams(
kind, file, offset, length, validateOnly,
options: options)
@ -1975,7 +1974,7 @@ abstract class IntegrationTestMixin {
/// that need to be applied.
Future<EditImportElementsResult> sendEditImportElements(
String file, List<ImportedElements> elements,
{int offset}) async {
{int? offset}) async {
var params =
EditImportElementsParams(file, elements, offset: offset).toJson();
var result = await server.send('edit.importElements', params);
@ -2164,7 +2163,7 @@ abstract class IntegrationTestMixin {
String contextFile,
int contextOffset,
List<RuntimeCompletionVariable> variables,
{List<RuntimeCompletionExpression> expressions}) async {
{List<RuntimeCompletionExpression>? expressions}) async {
var params = ExecutionGetSuggestionsParams(
code, offset, contextFile, contextOffset, variables,
expressions: expressions)
@ -2221,7 +2220,7 @@ abstract class IntegrationTestMixin {
/// The URI to which the file path was mapped. This field is omitted if the
/// file field was not given in the request.
Future<ExecutionMapUriResult> sendExecutionMapUri(String id,
{String file, String uri}) async {
{String? file, String? uri}) async {
var params = ExecutionMapUriParams(id, file: file, uri: uri).toJson();
var result = await server.send('execution.mapUri', params);
var decoder = ResponseDecoder(null);
@ -2273,10 +2272,10 @@ abstract class IntegrationTestMixin {
///
/// A list of the Dart files that are referenced by the file. This field is
/// omitted if the file is not an HTML file.
Stream<ExecutionLaunchDataParams> onExecutionLaunchData;
late Stream<ExecutionLaunchDataParams> onExecutionLaunchData;
/// Stream controller for [onExecutionLaunchData].
StreamController<ExecutionLaunchDataParams> _onExecutionLaunchData;
late StreamController<ExecutionLaunchDataParams> _onExecutionLaunchData;
/// Return server diagnostics.
///
@ -2512,7 +2511,7 @@ abstract class IntegrationTestMixin {
/// The change that should be applied.
Future<FlutterSetWidgetPropertyValueResult> sendFlutterSetWidgetPropertyValue(
int id,
{FlutterWidgetPropertyValue value}) async {
{FlutterWidgetPropertyValue? value}) async {
var params = FlutterSetWidgetPropertyValueParams(id, value: value).toJson();
var result = await server.send('flutter.setWidgetPropertyValue', params);
var decoder = ResponseDecoder(null);
@ -2573,10 +2572,10 @@ abstract class IntegrationTestMixin {
/// outline: FlutterOutline
///
/// The outline associated with the file.
Stream<FlutterOutlineParams> onFlutterOutline;
late Stream<FlutterOutlineParams> onFlutterOutline;
/// Stream controller for [onFlutterOutline].
StreamController<FlutterOutlineParams> _onFlutterOutline;
late StreamController<FlutterOutlineParams> _onFlutterOutline;
/// Initialize the fields in InttestMixin, and ensure that notifications will
/// be handled.
@ -2762,7 +2761,6 @@ abstract class IntegrationTestMixin {
break;
default:
fail('Unexpected notification: $event');
break;
}
}
}

View file

@ -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:collection';
import 'dart:convert';
@ -42,7 +40,7 @@ Matcher isOneOf(List<Matcher> choiceMatchers) => _OneOf(choiceMatchers);
/// Assert that [actual] matches [matcher].
void outOfTestExpect(actual, Matcher matcher,
{String reason, skip, bool verbose = false}) {
{String? reason, skip, bool verbose = false}) {
var matchState = {};
try {
if (matcher.matches(actual, matchState)) return;
@ -53,7 +51,7 @@ void outOfTestExpect(actual, Matcher matcher,
}
String _defaultFailFormatter(
actual, Matcher matcher, String reason, Map matchState, bool verbose) {
actual, Matcher matcher, String? reason, Map matchState, bool verbose) {
var description = StringDescription();
description.add('Expected: ').addDescriptionOf(matcher).add('\n');
description.add(' Actual: ').addDescriptionOf(actual).add('\n');
@ -90,7 +88,7 @@ abstract class AbstractAnalysisServerIntegrationTest
final Server server = Server();
/// Temporary directory in which source files can be stored.
Directory sourceDirectory;
late Directory sourceDirectory;
/// Map from file path to the list of analysis errors which have most recently
/// been received for the file.
@ -98,7 +96,7 @@ abstract class AbstractAnalysisServerIntegrationTest
HashMap<String, List<AnalysisError>>();
/// The last list of analyzed files received.
List<String> lastAnalyzedFiles;
late List<String> lastAnalyzedFiles;
/// True if the teardown process should skip sending a "server.shutdown"
/// request (e.g. because the server is known to have already shutdown).
@ -121,12 +119,13 @@ abstract class AbstractAnalysisServerIntegrationTest
/// analysis to finish.
Future<ServerStatusParams> get analysisFinished {
var completer = Completer<ServerStatusParams>();
StreamSubscription<ServerStatusParams> subscription;
late StreamSubscription<ServerStatusParams> subscription;
// This will only work if the caller has already subscribed to
// SERVER_STATUS (e.g. using sendServerSetSubscriptions(['STATUS']))
outOfTestExpect(_subscribedToServerStatus, isTrue);
subscription = onServerStatus.listen((ServerStatusParams params) {
if (params.analysis != null && !params.analysis.isAnalyzing) {
var analysisStatus = params.analysis;
if (analysisStatus != null && !analysisStatus.isAnalyzing) {
completer.complete(params);
subscription.cancel();
}
@ -140,7 +139,7 @@ abstract class AbstractAnalysisServerIntegrationTest
server.debugStdio();
}
List<AnalysisError> getErrors(String pathname) =>
List<AnalysisError>? getErrors(String pathname) =>
currentAnalysisErrors[pathname];
/// Read a source file with the given absolute [pathname].
@ -219,8 +218,8 @@ abstract class AbstractAnalysisServerIntegrationTest
/// Start [server].
Future startServer({
int diagnosticPort,
int servicesPort,
int? diagnosticPort,
int? servicesPort,
}) {
return server.start(
diagnosticPort: diagnosticPort, servicesPort: servicesPort);
@ -259,33 +258,30 @@ class LazyMatcher implements Matcher {
/// The matcher returned by [_creator], if it has already been called.
/// Otherwise null.
Matcher _wrappedMatcher;
Matcher? _wrappedMatcher;
LazyMatcher(this._creator);
/// Create the wrapped matcher object, if it hasn't been created already.
Matcher get _matcher {
return _wrappedMatcher ??= _creator();
}
@override
Description describe(Description description) {
_createMatcher();
return _wrappedMatcher.describe(description);
return _matcher.describe(description);
}
@override
Description describeMismatch(
item, Description mismatchDescription, Map matchState, bool verbose) {
_createMatcher();
return _wrappedMatcher.describeMismatch(
return _matcher.describeMismatch(
item, mismatchDescription, matchState, verbose);
}
@override
bool matches(item, Map matchState) {
_createMatcher();
return _wrappedMatcher.matches(item, matchState);
}
/// Create the wrapped matcher object, if it hasn't been created already.
void _createMatcher() {
_wrappedMatcher ??= _creator();
return _matcher.matches(item, matchState);
}
}
@ -317,11 +313,11 @@ class MatchesJsonObject extends _RecursiveMatcher {
/// Fields that are required to be in the JSON object, and [Matcher]s
/// describing their expected types.
final Map<String, Matcher> requiredFields;
final Map<String, Matcher>? requiredFields;
/// Fields that are optional in the JSON object, and [Matcher]s describing
/// their expected types.
final Map<String, Matcher> optionalFields;
final Map<String, Matcher>? optionalFields;
const MatchesJsonObject(this.description, this.requiredFields,
{this.optionalFields});
@ -336,9 +332,11 @@ class MatchesJsonObject extends _RecursiveMatcher {
mismatches.add(simpleDescription('is not a map'));
return;
}
var requiredFields = this.requiredFields;
var optionalFields = this.optionalFields;
if (requiredFields != null) {
requiredFields.forEach((String key, Matcher valueMatcher) {
if (!(item as Map).containsKey(key)) {
if (!item.containsKey(key)) {
mismatches.add((Description mismatchDescription) =>
mismatchDescription
.add('is missing field ')
@ -354,13 +352,18 @@ class MatchesJsonObject extends _RecursiveMatcher {
item.forEach((key, value) {
if (requiredFields != null && requiredFields.containsKey(key)) {
// Already checked this field
} else if (optionalFields != null && optionalFields.containsKey(key)) {
_checkField(key, value, optionalFields[key], mismatches);
} else {
mismatches.add((Description mismatchDescription) => mismatchDescription
.add('has unexpected field ')
.addDescriptionOf(key));
return;
}
if (optionalFields != null) {
var optionalValue = optionalFields[key];
if (optionalValue != null) {
_checkField(key, value, optionalValue, mismatches);
return;
}
}
mismatches.add((Description mismatchDescription) => mismatchDescription
.add('has unexpected field ')
.addDescriptionOf(key));
});
}
@ -382,7 +385,7 @@ class MatchesJsonObject extends _RecursiveMatcher {
/// facilitate communication to and from the server.
class Server {
/// Server process object, or null if server hasn't been started yet.
Process _process;
late final Process _process;
/// Commands that have been sent to the server but not yet acknowledged, and
/// the [Completer] objects which should be completed when acknowledgement is
@ -411,7 +414,7 @@ class Server {
/// The [currentElapseTime] at which the last communication was received from
/// the server or `null` if no communication has been received.
double lastCommunicationTime;
double? lastCommunicationTime;
/// The current elapse time (seconds) since the server was started.
double get currentElapseTime => _time.elapsedTicks / _time.frequency;
@ -536,7 +539,7 @@ class Server {
/// 'result' field from the response. If the server acknowledges the command
/// with an error response, the future will be completed with an error.
Future<Map<String, dynamic>> send(
String method, Map<String, dynamic> params) {
String method, Map<String, dynamic>? params) {
var id = '${_nextId++}';
var command = <String, dynamic>{'id': id, 'method': method};
if (params != null) {
@ -554,16 +557,13 @@ class Server {
/// with "--observe" and "--pause-isolates-on-exit", allowing the observatory
/// to be used.
Future start({
int diagnosticPort,
String instrumentationLogFile,
int? diagnosticPort,
String? instrumentationLogFile,
bool profileServer = false,
String sdkPath,
int servicesPort,
String? sdkPath,
int? servicesPort,
bool useAnalysisHighlight2 = false,
}) async {
if (_process != null) {
throw Exception('Process already started');
}
_time.start();
var dartBinary = Platform.executable;
@ -833,7 +833,7 @@ abstract class _RecursiveMatcher extends Matcher {
@override
Description describeMismatch(
item, Description mismatchDescription, Map matchState, bool verbose) {
var mismatches = matchState['mismatches'] as List<MismatchDescriber>;
var mismatches = matchState['mismatches'] as List<MismatchDescriber>?;
if (mismatches != null) {
for (var i = 0; i < mismatches.length; i++) {
var mismatch = mismatches[i];

View file

@ -6,8 +6,6 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
// @dart = 2.9
/// Matchers for data types defined in the analysis server API.
import 'package:test/test.dart';

View file

@ -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:convert';
import 'package:analysis_server/protocol/protocol.dart';
@ -92,34 +90,34 @@ class RequestErrorTest {
@reflectiveTest
class RequestTest {
void test_fromJson() {
void test_fromString() {
var original = Request('one', 'aMethod');
var jsonData = json.encode(original.toJson());
var request = Request.fromString(jsonData);
var request = Request.fromString(jsonData)!;
expect(request.id, equals('one'));
expect(request.method, equals('aMethod'));
expect(request.clientRequestTime, isNull);
}
void test_fromJson_invalidId() {
void test_fromString_invalidId_notString() {
var json = '{"id":{"one":"two"},"method":"aMethod","params":{"foo":"bar"}}';
var request = Request.fromString(json);
expect(request, isNull);
}
void test_fromJson_invalidMethod() {
void test_fromString_invalidMethod_notString() {
var json = '{"id":"one","method":{"boo":"aMethod"},"params":{"foo":"bar"}}';
var request = Request.fromString(json);
expect(request, isNull);
}
void test_fromJson_invalidParams() {
void test_fromString_invalidParams_notMap() {
var json = '{"id":"one","method":"aMethod","params":"foobar"}';
var request = Request.fromString(json);
expect(request, isNull);
}
void test_fromJson_withBadClientTime() {
void test_fromString_withBadClientTime() {
var original = Request('one', 'aMethod', null, 347);
var map = original.toJson();
// Insert bad value - should be int but client sent string instead
@ -129,19 +127,19 @@ class RequestTest {
expect(request, isNull);
}
void test_fromJson_withClientTime() {
void test_fromString_withClientTime() {
var original = Request('one', 'aMethod', null, 347);
var jsonData = json.encode(original.toJson());
var request = Request.fromString(jsonData);
var request = Request.fromString(jsonData)!;
expect(request.id, equals('one'));
expect(request.method, equals('aMethod'));
expect(request.clientRequestTime, 347);
}
void test_fromJson_withParams() {
void test_fromString_withParams() {
var original = Request('one', 'aMethod', {'foo': 'bar'});
var jsonData = json.encode(original.toJson());
var request = Request.fromString(jsonData);
var request = Request.fromString(jsonData)!;
expect(request.id, equals('one'));
expect(request.method, equals('aMethod'));
expect(request.toJson()['params'], equals({'foo': 'bar'}));
@ -199,25 +197,25 @@ class ResponseTest {
void test_fromJson() {
var original = Response('myId');
var response = Response.fromJson(original.toJson());
var response = Response.fromJson(original.toJson())!;
expect(response.id, equals('myId'));
}
void test_fromJson_withError() {
var original = Response.invalidRequestFormat();
var response = Response.fromJson(original.toJson());
var response = Response.fromJson(original.toJson())!;
expect(response.id, equals(''));
expect(response.error, isNotNull);
var error = response.error;
var error = response.error!;
expect(error.code, equals(RequestErrorCode.INVALID_REQUEST));
expect(error.message, equals('Invalid request'));
}
void test_fromJson_withResult() {
var original = Response('myId', result: {'foo': 'bar'});
var response = Response.fromJson(original.toJson());
var response = Response.fromJson(original.toJson())!;
expect(response.id, equals('myId'));
var result = response.toJson()['result'] as Map<String, Object>;
var result = response.toJson()['result'] as Map<String, Object?>;
expect(result.length, equals(1));
expect(result['foo'], equals('bar'));
}

View file

@ -246,8 +246,9 @@ void main() {
''');
var property = await getWidgetProperty('Text(', 'overflow');
var json = property.toJson().cast<String, dynamic>();
expect(
property.toJson()['editor']['enumItems'][0]['documentation'],
json['editor']['enumItems'][0]['documentation'],
startsWith('Clip the overflowing'),
);

View file

@ -42,4 +42,10 @@ class DartCodegenVisitor extends HierarchicalApiVisitor {
throw Exception("Can't convert to a dart type");
}
}
/// Return the Dart type for [field], nullable if the field is optional.
String fieldDartType(TypeObjectField field) {
var typeStr = dartType(field.type);
return field.optional ? '$typeStr?' : typeStr;
}
}

View file

@ -112,8 +112,6 @@ mixin NotificationHandler {
void visitApi() {
outputHeader(year: '2018');
writeln();
writeln('// @dart = 2.9');
writeln();
emitImports();
emitNotificationHandler();
}

View file

@ -259,7 +259,7 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
/// Emit the toJson() code for an empty class.
void emitEmptyToJsonMember() {
writeln('@override');
writeln('Map<String, dynamic> toJson() => <String, dynamic>{};');
writeln('Map<String, Object> toJson() => <String, Object>{};');
}
/// Emit a class to encapsulate an enum.
@ -358,7 +358,7 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
void emitEnumFromJsonConstructor(
String className, TypeEnum type, ImpliedType impliedType) {
writeln(
'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {');
'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object? json) {');
indent(() {
writeln('if (json is String) {');
indent(() {
@ -435,13 +435,6 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
if (emitSpecialStaticMembers(className)) {
writeln();
}
for (var field in type.fields) {
if (field.value != null) {
continue;
}
writeln('${dartType(field.type)} _${field.name};');
writeln();
}
for (var field in type.fields) {
if (field.value != null) {
continue;
@ -449,19 +442,7 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.translateHtml(field.html);
}));
writeln('${dartType(field.type)} get ${field.name} => _${field.name};');
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.translateHtml(field.html);
}));
writeln('set ${field.name}(${dartType(field.type)} value) {');
indent(() {
if (!field.optional) {
writeln('assert(value != null);');
}
writeln('_${field.name} = value;');
});
writeln('}');
writeln('${fieldDartType(field)} ${field.name};');
writeln();
}
emitObjectConstructor(type, className);
@ -505,61 +486,39 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
void emitObjectConstructor(TypeObject type, String className) {
var args = <String>[];
var optionalArgs = <String>[];
var extraInitCode = <CodegenCallback>[];
var initializers = <String>[];
for (var field in type.fields) {
if (field.value != null) {
continue;
}
var arg = '${dartType(field.type)} ${field.name}';
var setValueFromArg = 'this.${field.name} = ${field.name};';
if (isOptionalConstructorArg(className, field)) {
optionalArgs.add(arg);
if (!field.optional) {
// Optional constructor arg, but non-optional field. If no arg is
optionalArgs.add('${dartType(field.type)}? ${field.name}');
// Optional constructor arg, but non-optional field. If no arg is
// given, the constructor should populate with the empty list.
var fieldType = field.type;
if (fieldType is TypeList) {
extraInitCode.add(() {
writeln('if (${field.name} == null) {');
indent(() {
writeln(
'this.${field.name} = <${dartType(fieldType.itemType)}>[];');
});
writeln('} else {');
indent(() {
writeln(setValueFromArg);
});
writeln('}');
});
var defaultValue = '<${dartType(fieldType.itemType)}>[]';
initializers.add('${field.name} = ${field.name} ?? $defaultValue');
} else {
throw Exception("Don't know how to create default field value.");
}
} else {
extraInitCode.add(() {
writeln(setValueFromArg);
});
optionalArgs.add('this.${field.name}');
}
} else {
args.add(arg);
extraInitCode.add(() {
writeln(setValueFromArg);
});
args.add('this.${field.name}');
}
}
if (optionalArgs.isNotEmpty) {
args.add('{${optionalArgs.join(', ')}}');
}
write('$className(${args.join(', ')})');
if (extraInitCode.isEmpty) {
if (initializers.isEmpty) {
writeln(';');
} else {
writeln(' {');
indent(() {
for (var callback in extraInitCode) {
callback();
}
});
writeln('}');
writeln(' : ${initializers.join(', ')}');
writeln(';');
}
}
@ -598,8 +557,8 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
String className, TypeObject type, ImpliedType impliedType) {
var humanReadableNameString = literalString(impliedType.humanReadableName);
if (className == 'RefactoringFeedback') {
writeln('factory RefactoringFeedback.fromJson(JsonDecoder jsonDecoder, '
'String jsonPath, Object json, Map responseJson) {');
writeln('static RefactoringFeedback? fromJson(JsonDecoder jsonDecoder, '
'String jsonPath, Object? json, Map responseJson) {');
indent(() {
writeln('return refactoringFeedbackFromJson(jsonDecoder, jsonPath, '
'json, responseJson);');
@ -608,8 +567,8 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
return;
}
if (className == 'RefactoringOptions') {
writeln('factory RefactoringOptions.fromJson(JsonDecoder jsonDecoder, '
'String jsonPath, Object json, RefactoringKind kind) {');
writeln('static RefactoringOptions? fromJson(JsonDecoder jsonDecoder, '
'String jsonPath, Object? json, RefactoringKind kind) {');
indent(() {
writeln('return refactoringOptionsFromJson(jsonDecoder, jsonPath, '
'json, kind);');
@ -618,7 +577,7 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
return;
}
writeln(
'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object json) {');
'factory $className.fromJson(JsonDecoder jsonDecoder, String jsonPath, Object? json) {');
indent(() {
writeln('json ??= {};');
writeln('if (json is Map) {');
@ -629,12 +588,13 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
var fieldNameString = literalString(field.name);
var fieldAccessor = 'json[$fieldNameString]';
var jsonPath = 'jsonPath + ${literalString('.${field.name}')}';
if (field.value != null) {
var valueString = literalString(field.value);
var fieldValue = field.value;
if (fieldValue is String) {
var valueString = literalString(fieldValue);
writeln('if ($fieldAccessor != $valueString) {');
indent(() {
writeln(
"throw jsonDecoder.mismatch(jsonPath, 'equal ${field.value}', json);");
"throw jsonDecoder.mismatch(jsonPath, 'equal $fieldValue', json);");
});
writeln('}');
continue;
@ -644,11 +604,11 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
} else {
args.add(field.name);
}
var fieldType = field.type;
var fieldDartType = dartType(fieldType);
writeln('$fieldDartType ${field.name};');
var typeStr = fieldDartType(field);
writeln('$typeStr ${field.name};');
writeln('if (json.containsKey($fieldNameString)) {');
indent(() {
var fieldType = field.type;
var fromJson =
fromJsonCode(fieldType).asSnippet(jsonPath, fieldAccessor);
writeln('${field.name} = $fromJson;');
@ -852,19 +812,23 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
/// Emit the toJson() code for an object class.
void emitToJsonMember(TypeObject type) {
writeln('@override');
writeln('Map<String, dynamic> toJson() {');
writeln('Map<String, Object> toJson() {');
indent(() {
writeln('var result = <String, dynamic>{};');
writeln('var result = <String, Object>{};');
for (var field in type.fields) {
var fieldNameString = literalString(field.name);
if (field.value != null) {
writeln('result[$fieldNameString] = ${literalString(field.value)};');
var fieldValue = field.value;
if (fieldValue is String) {
var valueString = literalString(fieldValue);
writeln('result[$fieldNameString] = $valueString;');
continue;
}
var fieldToJson = toJsonCode(field.type).asSnippet(field.name);
var populateField = 'result[$fieldNameString] = $fieldToJson;';
if (field.optional) {
writeln('if (${field.name} != null) {');
var name = field.name;
writeln('var $name = this.$name;');
writeln('if ($name != null) {');
indent(() {
writeln(populateField);
});
@ -1122,8 +1086,6 @@ class CodegenProtocolVisitor extends DartCodegenVisitor with CodeGenerator {
void visitApi() {
outputHeader(year: '2017');
writeln();
writeln('// @dart = 2.9');
writeln();
emitImports();
emitClasses(getClassesToEmit());
}
@ -1177,7 +1139,7 @@ class FromJsonSnippet extends FromJsonCode {
@override
String get asClosure =>
'(String jsonPath, Object json) => ${callback('jsonPath', 'json')}';
'(String jsonPath, Object? json) => ${callback('jsonPath', 'json')}';
@override
bool get isIdentity => false;

View file

@ -49,7 +49,7 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
/// Generate a function argument for the given parameter field.
String formatArgument(TypeObjectField field) =>
'${dartType(field.type)} ${field.name}';
'${fieldDartType(field)} ${field.name}';
/// Figure out the appropriate Dart type for data having the given API
/// protocol [type].
@ -86,8 +86,6 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
void visitApi() {
outputHeader(year: '2017');
writeln();
writeln('// @dart = 2.9');
writeln();
writeln('/// Convenience methods for running integration tests.');
writeln("import 'dart:async';");
writeln();
@ -134,7 +132,6 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
writeln('default:');
indent(() {
writeln("fail('Unexpected notification: \$event');");
writeln('break;');
});
});
writeln('}');
@ -156,12 +153,12 @@ class CodegenInttestMethodsVisitor extends DartCodegenVisitor
toHtmlVisitor.translateHtml(notification.html);
toHtmlVisitor.describePayload(notification.params, 'Parameters');
}));
writeln('Stream<$className> $streamName;');
writeln('late Stream<$className> $streamName;');
writeln();
docComment(toHtmlVisitor.collectHtml(() {
toHtmlVisitor.write('Stream controller for [$streamName].');
}));
writeln('StreamController<$className> _$streamName;');
writeln('late StreamController<$className> _$streamName;');
fieldInitializationCode.add(collectCode(() {
writeln('_$streamName = StreamController<$className>(sync: true);');
writeln('$streamName = _$streamName.stream.asBroadcastStream();');

View file

@ -91,8 +91,6 @@ class CodegenMatchersVisitor extends HierarchicalApiVisitor with CodeGenerator {
void visitApi() {
outputHeader(year: '2017');
writeln();
writeln('// @dart = 2.9');
writeln();
writeln('/// Matchers for data types defined in the analysis server API.');
writeln("import 'package:test/test.dart';");
writeln();

View file

@ -90,8 +90,6 @@ class CodegenVisitor extends DartCodegenVisitor with CodeGenerator {
void visitApi() {
outputHeader(year: '2017');
writeln();
writeln('// @dart = 2.9');
writeln();
generateConstants();
}
}

View file

@ -6,8 +6,6 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
// @dart = 2.9
import 'package:analysis_server_client/protocol.dart';
/// [NotificationHandler] processes analysis server notifications

View file

@ -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
export 'package:analysis_server_client/src/protocol/protocol_base.dart';
export 'package:analysis_server_client/src/protocol/protocol_common.dart';
export 'package:analysis_server_client/src/protocol/protocol_constants.dart';

View file

@ -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
/// Support for client code that needs to interact with the requests, responses
/// and notifications that are part of the analysis server's wire protocol.
import 'dart:convert' hide JsonDecoder;
@ -36,7 +34,7 @@ class Notification {
/// A table mapping the names of notification parameters to their values, or
/// `null` if there are no notification parameters.
final Map<String, Object> params;
final Map<String, Object>? params;
/// Initialize a newly created [Notification] to have the given [event] name.
/// If [params] is provided, it will be used as the params; otherwise no
@ -54,6 +52,7 @@ class Notification {
Map<String, Object> toJson() {
var jsonObject = <String, Object>{};
jsonObject[EVENT] = event;
var params = this.params;
if (params != null) {
jsonObject[PARAMS] = params;
}
@ -85,84 +84,18 @@ class Request {
final String method;
/// A table mapping the names of request parameters to their values.
final Map<String, Object> params;
final Map<String, Object?> params;
/// The time (milliseconds since epoch) at which the client made the request
/// or `null` if this information is not provided by the client.
final int clientRequestTime;
final int? clientRequestTime;
/// Initialize a newly created [Request] to have the given [id] and [method]
/// name. If [params] is supplied, it is used as the "params" map for the
/// request. Otherwise an empty "params" map is allocated.
Request(this.id, this.method,
[Map<String, Object> params, this.clientRequestTime])
: params = params ?? <String, Object>{};
/// Return a request parsed from the given json, or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
factory Request.fromJson(Map<String, Object> result) {
var id = result[Request.ID];
var method = result[Request.METHOD];
if (id is! String || method is! String) {
return null;
}
var time = result[Request.CLIENT_REQUEST_TIME];
if (time != null && time is! int) {
return null;
}
var params = result[Request.PARAMS];
if (params is Map || params == null) {
return Request(id, method, params as Map<String, Object>, time);
} else {
return null;
}
}
/// Return a request parsed from the given [data], or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
factory Request.fromString(String data) {
try {
var result = json.decode(data);
if (result is Map) {
return Request.fromJson(result as Map<String, dynamic>);
}
return null;
} catch (exception) {
return null;
}
}
[Map<String, Object?>? params, this.clientRequestTime])
: params = params ?? <String, Object?>{};
@override
int get hashCode {
@ -187,13 +120,14 @@ class Request {
if (params.isNotEmpty) {
jsonObject[PARAMS] = params;
}
var clientRequestTime = this.clientRequestTime;
if (clientRequestTime != null) {
jsonObject[CLIENT_REQUEST_TIME] = clientRequestTime;
}
return jsonObject;
}
bool _equalLists(List first, List second) {
bool _equalLists(List? first, List? second) {
if (first == null) {
return second == null;
}
@ -212,7 +146,7 @@ class Request {
return true;
}
bool _equalMaps(Map first, Map second) {
bool _equalMaps(Map? first, Map? second) {
if (first == null) {
return second == null;
}
@ -233,7 +167,7 @@ class Request {
return true;
}
bool _equalObjects(Object first, Object second) {
bool _equalObjects(Object? first, Object? second) {
if (first == null) {
return second == null;
}
@ -254,6 +188,72 @@ class Request {
}
return first == second;
}
/// Return a request parsed from the given json, or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
static Request? fromJson(Map<String, Object?> result) {
var id = result[Request.ID];
var method = result[Request.METHOD];
if (id is! String || method is! String) {
return null;
}
var time = result[Request.CLIENT_REQUEST_TIME];
if (time is! int?) {
return null;
}
var params = result[Request.PARAMS];
if (params is Map<String, Object?>?) {
return Request(id, method, params, time);
} else {
return null;
}
}
/// Return a request parsed from the given [data], or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
/// have the following format:
///
/// {
/// 'clientRequestTime': millisecondsSinceEpoch
/// 'id': String,
/// 'method': methodName,
/// 'params': {
/// paramter_name: value
/// }
/// }
///
/// where both the parameters and clientRequestTime are optional.
///
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
static Request? fromString(String data) {
try {
var result = json.decode(data);
if (result is Map<String, Object?>) {
return Request.fromJson(result);
}
return null;
} catch (exception) {
return null;
}
}
}
/// An exception that occurred during the handling of a request that requires
@ -303,17 +303,17 @@ class Response {
/// The error that was caused by attempting to handle the request, or `null` if
/// there was no error.
final RequestError error;
final RequestError? error;
/// A table mapping the names of result fields to their values. Should be
/// `null` if there is no result to send.
Map<String, Object> result;
Map<String, Object?>? result;
/// Initialize a newly created instance to represent a response to a request
/// with the given [id]. If [_result] is provided, it will be used as the
/// with the given [id]. If [result] is provided, it will be used as the
/// result; otherwise an empty result will be used. If an [error] is provided
/// then the response will represent an error condition.
Response(this.id, {Map<String, Object> result, this.error}) : result = result;
Response(this.id, {this.result, this.error});
/// Create and return the `DEBUG_PORT_COULD_NOT_BE_OPENED` error response.
Response.debugPortCouldNotBeOpened(Request request, dynamic error)
@ -342,30 +342,6 @@ class Response {
error: RequestError(RequestErrorCode.FORMAT_WITH_ERRORS,
'Error during `edit.format`: source contains syntax errors.'));
/// Initialize a newly created instance based on the given JSON data.
factory Response.fromJson(Map json) {
try {
Object id = json[Response.ID];
if (id is! String) {
return null;
}
Object error = json[Response.ERROR];
RequestError decodedError;
if (error is Map) {
decodedError =
RequestError.fromJson(ResponseDecoder(null), '.error', error);
}
Object result = json[Response.RESULT];
Map<String, Object> decodedResult;
if (result is Map) {
decodedResult = result as Map<String, Object>;
}
return Response(id, error: decodedError, result: decodedResult);
} catch (exception) {
return null;
}
}
/// Initialize a newly created instance to represent the
/// GET_ERRORS_INVALID_FILE error condition.
Response.getErrorsInvalidFile(Request request)
@ -528,12 +504,41 @@ class Response {
Map<String, Object> toJson() {
var jsonObject = <String, Object>{};
jsonObject[ID] = id;
var error = this.error;
if (error != null) {
jsonObject[ERROR] = error.toJson();
}
var result = this.result;
if (result != null) {
jsonObject[RESULT] = result;
}
return jsonObject;
}
/// Initialize a newly created instance based on the given JSON data.
static Response? fromJson(Map<String, Object?> json) {
try {
var id = json[Response.ID];
if (id is! String) {
return null;
}
RequestError? decodedError;
var error = json[Response.ERROR];
if (error is Map) {
decodedError =
RequestError.fromJson(ResponseDecoder(null), '.error', error);
}
Map<String, Object?>? decodedResult;
var result = json[Response.RESULT];
if (result is Map<String, Object?>) {
decodedResult = result;
}
return Response(id, error: decodedError, result: decodedResult);
} catch (exception) {
return null;
}
}
}

View file

@ -6,8 +6,6 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
// @dart = 2.9
const String PROTOCOL_VERSION = '1.32.5';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';

View file

@ -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:collection';
import 'dart:convert' hide JsonDecoder;
@ -61,7 +59,7 @@ String applySequenceOfEdits(String code, Iterable<SourceEdit> edits) {
}
/// Returns the [FileEdit] for the given [file], maybe `null`.
SourceFileEdit getChangeFileEdit(SourceChange change, String file) {
SourceFileEdit? getChangeFileEdit(SourceChange change, String file) {
for (var fileEdit in change.edits) {
if (fileEdit.file == file) {
return fileEdit;
@ -72,8 +70,8 @@ SourceFileEdit getChangeFileEdit(SourceChange change, String file) {
/// Compare the lists [listA] and [listB], using [itemEqual] to compare
/// list elements.
bool listEqual<T1, T2>(
List<T1> listA, List<T2> listB, bool Function(T1 a, T2 b) itemEqual) {
bool listEqual<T>(
List<T>? listA, List<T>? listB, bool Function(T a, T b) itemEqual) {
if (listA == null) {
return listB == null;
}
@ -94,7 +92,7 @@ bool listEqual<T1, T2>(
/// Compare the maps [mapA] and [mapB], using [valueEqual] to compare map
/// values.
bool mapEqual<K, V>(
Map<K, V> mapA, Map<K, V> mapB, bool Function(V a, V b) valueEqual) {
Map<K, V>? mapA, Map<K, V>? mapB, bool Function(V a, V b) valueEqual) {
if (mapA == null) {
return mapB == null;
}
@ -104,11 +102,11 @@ bool mapEqual<K, V>(
if (mapA.length != mapB.length) {
return false;
}
for (var key in mapA.keys) {
if (!mapB.containsKey(key)) {
return false;
}
if (!valueEqual(mapA[key], mapB[key])) {
for (var entryA in mapA.entries) {
var key = entryA.key;
var valueA = entryA.value;
var valueB = mapB[key];
if (valueB == null || !valueEqual(valueA, valueB)) {
return false;
}
}
@ -118,7 +116,7 @@ bool mapEqual<K, V>(
/// Translate the input [map], applying [keyCallback] to all its keys, and
/// [valueCallback] to all its values.
Map<KR, VR> mapMap<KP, VP, KR, VR>(Map<KP, VP> map,
{KR Function(KP key) keyCallback, VR Function(VP value) valueCallback}) {
{KR Function(KP key)? keyCallback, VR Function(VP value)? valueCallback}) {
Map<KR, VR> result = HashMap<KR, VR>();
map.forEach((key, value) {
KR resultKey;
@ -138,8 +136,8 @@ Map<KR, VR> mapMap<KP, VP, KR, VR>(Map<KP, VP> map,
return result;
}
RefactoringProblemSeverity maxRefactoringProblemSeverity(
RefactoringProblemSeverity a, RefactoringProblemSeverity b) {
RefactoringProblemSeverity? maxRefactoringProblemSeverity(
RefactoringProblemSeverity? a, RefactoringProblemSeverity? b) {
if (b == null) {
return a;
}
@ -161,8 +159,8 @@ RefactoringProblemSeverity maxRefactoringProblemSeverity(
}
/// Create a [RefactoringFeedback] corresponding the given [kind].
RefactoringFeedback refactoringFeedbackFromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
RefactoringFeedback? refactoringFeedbackFromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json, Map feedbackJson) {
var kind = jsonDecoder.refactoringKind;
if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
return ExtractLocalVariableFeedback.fromJson(jsonDecoder, jsonPath, json);
@ -186,8 +184,8 @@ RefactoringFeedback refactoringFeedbackFromJson(
}
/// Create a [RefactoringOptions] corresponding the given [kind].
RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
String jsonPath, Object json, RefactoringKind kind) {
RefactoringOptions? refactoringOptionsFromJson(JsonDecoder jsonDecoder,
String jsonPath, Object? json, RefactoringKind kind) {
if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
return ExtractLocalVariableOptions.fromJson(jsonDecoder, jsonPath, json);
}
@ -212,7 +210,8 @@ RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
/// Type of callbacks used to decode parts of JSON objects. [jsonPath] is a
/// string describing the part of the JSON object being decoded, and [value] is
/// the part to decode.
typedef JsonDecoderCallback<E> = E Function(String jsonPath, Object value);
typedef JsonDecoderCallback<E extends Object> = E Function(
String jsonPath, Object? value);
/// Instances of the class [HasToJson] implement [toJson] method that returns
/// a JSON presentation.
@ -227,7 +226,7 @@ abstract class JsonDecoder {
/// Retrieve the RefactoringKind that should be assumed when decoding
/// refactoring feedback objects, or null if no refactoring feedback object is
/// expected to be encountered.
RefactoringKind get refactoringKind;
RefactoringKind? get refactoringKind;
/// Decode a JSON object that is expected to be a boolean. The strings "true"
/// and "false" are also accepted.
@ -261,7 +260,7 @@ abstract class JsonDecoder {
/// Decode a JSON object that is expected to be an integer. A string
/// representation of an integer is also accepted.
int decodeInt(String jsonPath, Object json) {
int decodeInt(String jsonPath, Object? json) {
if (json is int) {
return json;
} else if (json is String) {
@ -278,8 +277,8 @@ abstract class JsonDecoder {
/// to decode the items in the list.
///
/// The type parameter [E] is the expected type of the elements in the list.
List<E> decodeList<E>(String jsonPath, Object json,
[JsonDecoderCallback<E> decoder]) {
List<E> decodeList<E extends Object>(
String jsonPath, Object? json, JsonDecoderCallback<E> decoder) {
if (json == null) {
return <E>[];
} else if (json is List) {
@ -295,9 +294,10 @@ abstract class JsonDecoder {
/// Decode a JSON object that is expected to be a Map. [keyDecoder] is used
/// to decode the keys, and [valueDecoder] is used to decode the values.
Map<K, V> decodeMap<K, V>(String jsonPath, Object jsonData,
{JsonDecoderCallback<K> keyDecoder,
JsonDecoderCallback<V> valueDecoder}) {
Map<K, V> decodeMap<K extends Object, V extends Object>(
String jsonPath, Object? jsonData,
{JsonDecoderCallback<K>? keyDecoder,
JsonDecoderCallback<V>? valueDecoder}) {
if (jsonData == null) {
return {};
} else if (jsonData is Map) {
@ -321,7 +321,7 @@ abstract class JsonDecoder {
}
/// Decode a JSON object that is expected to be a string.
String decodeString(String jsonPath, Object json) {
String decodeString(String jsonPath, Object? json) {
if (json is String) {
return json;
} else {
@ -333,7 +333,7 @@ abstract class JsonDecoder {
/// where the choices are disambiguated by the contents of the field [field].
/// [decoders] is a map from each possible string in the field to the decoder
/// that should be used to decode the JSON object.
Object decodeUnion(String jsonPath, Map jsonData, String field,
Object decodeUnion(String jsonPath, Object? jsonData, String field,
Map<String, JsonDecoderCallback> decoders) {
if (jsonData is Map) {
if (!jsonData.containsKey(field)) {
@ -341,11 +341,12 @@ abstract class JsonDecoder {
}
var disambiguatorPath = '$jsonPath[${json.encode(field)}]';
var disambiguator = decodeString(disambiguatorPath, jsonData[field]);
if (!decoders.containsKey(disambiguator)) {
var decoder = decoders[disambiguator];
if (decoder == null) {
throw mismatch(
disambiguatorPath, 'One of: ${decoders.keys.toList()}', jsonData);
}
return decoders[disambiguator](jsonPath, jsonData);
return decoder(jsonPath, jsonData);
} else {
throw mismatch(jsonPath, 'Map', jsonData);
}
@ -353,7 +354,7 @@ abstract class JsonDecoder {
/// Create an exception to throw if the JSON object at [jsonPath] fails to
/// match the API definition of [expected].
dynamic mismatch(String jsonPath, String expected, [Object actual]);
dynamic mismatch(String jsonPath, String expected, [Object? actual]);
/// Create an exception to throw if the JSON object at [jsonPath] is missing
/// the key [key].
@ -369,13 +370,13 @@ class RequestDecoder extends JsonDecoder {
RequestDecoder(this._request);
@override
RefactoringKind get refactoringKind {
RefactoringKind? get refactoringKind {
// Refactoring feedback objects should never appear in requests.
return null;
}
@override
dynamic mismatch(String jsonPath, String expected, [Object actual]) {
dynamic mismatch(String jsonPath, String expected, [Object? actual]) {
var buffer = StringBuffer();
buffer.write('Expected to be ');
buffer.write(expected);
@ -405,12 +406,12 @@ abstract class RequestParams implements HasToJson {
/// used only for testing. Errors are reported using bare [Exception] objects.
class ResponseDecoder extends JsonDecoder {
@override
final RefactoringKind refactoringKind;
final RefactoringKind? refactoringKind;
ResponseDecoder(this.refactoringKind);
@override
dynamic mismatch(String jsonPath, String expected, [Object actual]) {
dynamic mismatch(String jsonPath, String expected, [Object? actual]) {
var buffer = StringBuffer();
buffer.write('Expected ');
buffer.write(expected);

View file

@ -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
/// Jenkins hash function, optimized for small integers.
///
/// Static methods borrowed from sdk/lib/math/jenkins_smi_hash.dart. Non-static

View file

@ -80,7 +80,7 @@ class Request {
final String method;
/// A table mapping the names of request parameters to their values.
final Map<String, Object> params;
final Map<String, Object?> params;
/// The time (milliseconds since epoch) at which the server made the request,
/// or `null` if this information is not provided by the server.
@ -90,8 +90,8 @@ class Request {
/// name. If [params] is supplied, it is used as the "params" map for the
/// request. Otherwise an empty "params" map is allocated.
Request(this.id, this.method,
[Map<String, Object>? params, this.serverRequestTime])
: params = params ?? <String, Object>{};
[Map<String, Object?>? params, this.serverRequestTime])
: params = params ?? <String, Object?>{};
/// Return a request parsed from the given json, or `null` if the [data] is
/// not a valid json representation of a request. The [data] is expected to
@ -111,19 +111,19 @@ class Request {
/// The parameters can contain any number of name/value pairs. The
/// clientRequestTime must be an int representing the time at which the client
/// issued the request (milliseconds since epoch).
factory Request.fromJson(Map<String, Object> result) {
factory Request.fromJson(Map<String, Object?> result) {
var id = result[Request.ID];
var method = result[Request.METHOD];
if (id is! String || method is! String) {
throw StateError('Unexpected type for id or method');
}
var time = result[Request.SERVER_REQUEST_TIME];
if (time != null && time is! int) {
if (time is! int?) {
throw StateError('Unexpected type for server request time');
}
var params = result[Request.PARAMS];
if (params is Map || params == null) {
return Request(id, method, params as Map<String, Object>?, time as int?);
if (params is Map<String, Object?>?) {
return Request(id, method, params, time);
} else {
throw StateError('Unexpected type for params');
}
@ -304,36 +304,39 @@ class Response {
/// A table mapping the names of result fields to their values. Should be
/// `null` if there is no result to send.
Map<String, Object>? result;
Map<String, Object?>? result;
/// Initialize a newly created instance to represent a response to a request
/// with the given [id]. If [_result] is provided, it will be used as the
/// with the given [id]. If [result] is provided, it will be used as the
/// result; otherwise an empty result will be used. If an [error] is provided
/// then the response will represent an error condition.
Response(this.id, this.requestTime, {this.error, Map<String, Object>? result})
: result = result;
Response(this.id, this.requestTime, {this.error, this.result});
/// Initialize a newly created instance based on the given JSON data.
factory Response.fromJson(Map json) {
factory Response.fromJson(Map<String, Object?> json) {
var id = json[ID];
if (id is! String) {
throw StateError('Unexpected type for id');
}
var error = json[ERROR];
RequestError? decodedError;
var error = json[ERROR];
if (error is Map) {
decodedError =
RequestError.fromJson(ResponseDecoder(null), '.error', error);
}
var requestTime = json[REQUEST_TIME];
if (requestTime is! int) {
throw StateError('Unexpected type for requestTime');
}
var result = json[RESULT];
Map<String, Object>? decodedResult;
if (result is Map) {
decodedResult = result as Map<String, Object>;
Map<String, Object?>? decodedResult;
var result = json[Response.RESULT];
if (result is Map<String, Object?>) {
decodedResult = result;
}
return Response(id, requestTime,
error: decodedError, result: decodedResult);
}

View file

@ -223,7 +223,7 @@ abstract class ServerIsolateChannel implements ServerCommunicationChannel {
if (input is SendPort) {
_sendPort = input;
channelReady.complete(null);
} else if (input is Map) {
} else if (input is Map<String, Object?>) {
if (input.containsKey('id')) {
var encodedInput = json.encode(input);
instrumentationService.logPluginResponse(pluginId, encodedInput);

View file

@ -136,11 +136,11 @@ bool mapEqual<K, V>(
if (mapA.length != mapB.length) {
return false;
}
for (var key in mapA.keys) {
if (!mapB.containsKey(key)) {
return false;
}
if (!valueEqual(mapA[key]!, mapB[key]!)) {
for (var entryA in mapA.entries) {
var key = entryA.key;
var valueA = entryA.value;
var valueB = mapB[key];
if (valueB == null || !valueEqual(valueA, valueB)) {
return false;
}
}
@ -239,7 +239,7 @@ RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
/// string describing the part of the JSON object being decoded, and [value] is
/// the part to decode.
typedef JsonDecoderCallback<E extends Object> = E Function(
String jsonPath, dynamic value);
String jsonPath, Object? value);
/// Instances of the class [HasToJson] implement [toJson] method that returns
/// a JSON presentation.
@ -361,7 +361,7 @@ abstract class JsonDecoder {
/// where the choices are disambiguated by the contents of the field [field].
/// [decoders] is a map from each possible string in the field to the decoder
/// that should be used to decode the JSON object.
Object decodeUnion(String jsonPath, Map jsonData, String field,
Object decodeUnion(String jsonPath, Object? jsonData, String field,
Map<String, JsonDecoderCallback> decoders) {
if (jsonData is Map) {
if (!jsonData.containsKey(field)) {

View file

@ -28,9 +28,7 @@ List<GeneratedContent> get allTargets {
targets.add(codegen_inttest_methods.target);
targets.add(codegen_matchers.target);
targets.add(codegen_protocol_common.pluginTarget(true));
// TODO(scheglov) Migrate analysis_server_client
// https://github.com/dart-lang/sdk/issues/45500
// targets.add(codegen_protocol_common.clientTarget(true));
targets.add(codegen_protocol_common.clientTarget(true));
targets.add(codegen_protocol_constants.target);
targets.add(to_html.target);
return targets;