Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(825)

Unified Diff: pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart

Issue 2664213003: Add the generator and the generated files (Closed)
Patch Set: add missed files Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
diff --git a/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
new file mode 100644
index 0000000000000000000000000000000000000000..7033784e106e21dfa2162f63a514838214be904a
--- /dev/null
+++ b/pkg/analyzer_plugin/lib/src/protocol/protocol_internal.dart
@@ -0,0 +1,514 @@
+// Copyright (c) 2017, 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 'dart:collection';
+import 'dart:convert' hide JsonDecoder;
+
+import 'package:analyzer_plugin/protocol/generated_protocol.dart';
+import 'package:analyzer_plugin/protocol/protocol.dart';
+
+final Map<String, RefactoringKind> REQUEST_ID_REFACTORING_KINDS =
+ new HashMap<String, RefactoringKind>();
+
+/**
+ * Adds the given [sourceEdits] to the list in [sourceFileEdit].
+ */
+void addAllEditsForSource(
+ SourceFileEdit sourceFileEdit, Iterable<SourceEdit> edits) {
+ edits.forEach(sourceFileEdit.add);
+}
+
+/**
+ * Adds the given [sourceEdit] to the list in [sourceFileEdit].
+ */
+void addEditForSource(SourceFileEdit sourceFileEdit, SourceEdit sourceEdit) {
+ List<SourceEdit> edits = sourceFileEdit.edits;
+ int index = 0;
+ while (index < edits.length && edits[index].offset > sourceEdit.offset) {
+ index++;
+ }
+ edits.insert(index, sourceEdit);
+}
+
+/**
+ * Adds [edit] to the [FileEdit] for the given [file].
+ */
+void addEditToSourceChange(
+ SourceChange change, String file, int fileStamp, SourceEdit edit) {
+ SourceFileEdit fileEdit = change.getFileEdit(file);
+ if (fileEdit == null) {
+ fileEdit = new SourceFileEdit(file, fileStamp);
+ change.addFileEdit(fileEdit);
+ }
+ fileEdit.add(edit);
+}
+
+/**
+ * Get the result of applying the edit to the given [code]. Access via
+ * SourceEdit.apply().
+ */
+String applyEdit(String code, SourceEdit edit) {
+ if (edit.length < 0) {
+ throw new RangeError('length is negative');
+ }
+ return code.replaceRange(edit.offset, edit.end, edit.replacement);
+}
+
+/**
+ * Get the result of applying a set of [edits] to the given [code]. Edits
+ * are applied in the order they appear in [edits]. Access via
+ * SourceEdit.applySequence().
+ */
+String applySequenceOfEdits(String code, Iterable<SourceEdit> edits) {
+ edits.forEach((SourceEdit edit) {
+ code = edit.apply(code);
+ });
+ return code;
+}
+
+/**
+ * Returns the [FileEdit] for the given [file], maybe `null`.
+ */
+SourceFileEdit getChangeFileEdit(SourceChange change, String file) {
+ for (SourceFileEdit fileEdit in change.edits) {
+ if (fileEdit.file == file) {
+ return fileEdit;
+ }
+ }
+ return null;
+}
+
+/**
+ * Compare the lists [listA] and [listB], using [itemEqual] to compare
+ * list elements.
+ */
+bool listEqual(List listA, List listB, bool itemEqual(a, b)) {
+ if (listA == null) {
+ return listB == null;
+ }
+ if (listB == null) {
+ return false;
+ }
+ if (listA.length != listB.length) {
+ return false;
+ }
+ for (int i = 0; i < listA.length; i++) {
+ if (!itemEqual(listA[i], listB[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Compare the maps [mapA] and [mapB], using [valueEqual] to compare map
+ * values.
+ */
+bool mapEqual(Map mapA, Map mapB, bool valueEqual(a, b)) {
+ if (mapA == null) {
+ return mapB == null;
+ }
+ if (mapB == null) {
+ return false;
+ }
+ 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])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * 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,
+ {dynamic/*=KR*/ keyCallback(/*<KP>*/ key),
+ dynamic/*=VR*/ valueCallback(/*<VP>*/ value)}) {
+ Map/*<KR, VR>*/ result = new HashMap/*<KR, VR>*/();
+ map.forEach((key, value) {
+ Object/*=KR*/ resultKey;
+ Object/*=VR*/ resultValue;
+ if (keyCallback != null) {
+ resultKey = keyCallback(key);
+ } else {
+ resultKey = key as Object/*=KR*/;
+ }
+ if (valueCallback != null) {
+ resultValue = valueCallback(value);
+ } else {
+ resultValue = value as Object/*=VR*/;
+ }
+ result[resultKey] = resultValue;
+ });
+ return result;
+}
+
+RefactoringProblemSeverity maxRefactoringProblemSeverity(
+ RefactoringProblemSeverity a, RefactoringProblemSeverity b) {
+ if (b == null) {
+ return a;
+ }
+ if (a == null) {
+ return b;
+ } else if (a == RefactoringProblemSeverity.INFO) {
+ return b;
+ } else if (a == RefactoringProblemSeverity.WARNING) {
+ if (b == RefactoringProblemSeverity.ERROR ||
+ b == RefactoringProblemSeverity.FATAL) {
+ return b;
+ }
+ } else if (a == RefactoringProblemSeverity.ERROR) {
+ if (b == RefactoringProblemSeverity.FATAL) {
+ return b;
+ }
+ }
+ return a;
+}
+
+/**
+ * Create a [RefactoringFeedback] corresponding the given [kind].
+ */
+RefactoringFeedback refactoringFeedbackFromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
+ RefactoringKind kind = jsonDecoder.refactoringKind;
+ if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
+ return new ExtractLocalVariableFeedback.fromJson(
+ jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.EXTRACT_METHOD) {
+ return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
+ return new InlineLocalVariableFeedback.fromJson(
+ jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.INLINE_METHOD) {
+ return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.RENAME) {
+ return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json);
+ }
+ return null;
+}
+
+/**
+ * Create a [RefactoringOptions] corresponding the given [kind].
+ */
+RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
+ String jsonPath, Object json, RefactoringKind kind) {
+ if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
+ return new ExtractLocalVariableOptions.fromJson(
+ jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.EXTRACT_METHOD) {
+ return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.INLINE_METHOD) {
+ return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.MOVE_FILE) {
+ return new MoveFileOptions.fromJson(jsonDecoder, jsonPath, json);
+ }
+ if (kind == RefactoringKind.RENAME) {
+ return new RenameOptions.fromJson(jsonDecoder, jsonPath, json);
+ }
+ return null;
+}
+
+///**
+// * Create a [RefactoringFeedback] corresponding the given [kind].
+// */
+//RefactoringFeedback refactoringFeedbackFromJson(
+// JsonDecoder jsonDecoder, String jsonPath, Object json, Map feedbackJson) {
+// RefactoringKind kind = jsonDecoder.refactoringKind;
+// if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
+// return new ExtractLocalVariableFeedback.fromJson(
+// jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.EXTRACT_METHOD) {
+// return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
+// return new InlineLocalVariableFeedback.fromJson(
+// jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.INLINE_METHOD) {
+// return new InlineMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.RENAME) {
+// return new RenameFeedback.fromJson(jsonDecoder, jsonPath, json);
+// }
+// return null;
+//}
+//
+///**
+// * Create a [RefactoringOptions] corresponding the given [kind].
+// */
+//RefactoringOptions refactoringOptionsFromJson(JsonDecoder jsonDecoder,
+// String jsonPath, Object json, RefactoringKind kind) {
+// if (kind == RefactoringKind.EXTRACT_LOCAL_VARIABLE) {
+// return new ExtractLocalVariableOptions.fromJson(
+// jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.EXTRACT_METHOD) {
+// return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.INLINE_METHOD) {
+// return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.MOVE_FILE) {
+// return new MoveFileOptions.fromJson(jsonDecoder, jsonPath, json);
+// }
+// if (kind == RefactoringKind.RENAME) {
+// return new RenameOptions.fromJson(jsonDecoder, jsonPath, json);
+// }
+// return null;
+//}
+
+/**
+ * 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 E JsonDecoderCallback<E>(String jsonPath, Object value);
+
+/**
+ * Instances of the class [HasToJson] implement [toJson] method that returns
+ * a JSON presentation.
+ */
+abstract class HasToJson {
+ /**
+ * Returns a JSON presentation of the object.
+ */
+ Map<String, Object> toJson();
+}
+
+/**
+ * Base class for decoding JSON objects. The derived class must implement
+ * error reporting logic.
+ */
+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;
+
+ /**
+ * Decode a JSON object that is expected to be a boolean. The strings "true"
+ * and "false" are also accepted.
+ */
+ bool decodeBool(String jsonPath, Object json) {
+ if (json is bool) {
+ return json;
+ } else if (json == 'true') {
+ return true;
+ } else if (json == 'false') {
+ return false;
+ }
+ throw mismatch(jsonPath, 'bool', json);
+ }
+
+ /**
+ * 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) {
+ if (json is int) {
+ return json;
+ } else if (json is String) {
+ return int.parse(json, onError: (String value) {
+ throw mismatch(jsonPath, 'int', json);
+ });
+ }
+ throw mismatch(jsonPath, 'int', json);
+ }
+
+ /**
+ * Decode a JSON object that is expected to be a List. The [decoder] is used
+ * 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]) {
+ if (json == null) {
+ return/*<E>*/ [];
+ } else if (json is List) {
+ List/*<E>*/ result = /*<E>*/ [];
+ for (int i = 0; i < json.length; i++) {
+ result.add(decoder('$jsonPath[$i]', json[i]));
+ }
+ return result;
+ } else {
+ throw mismatch(jsonPath, 'List', json);
+ }
+ }
+
+ /**
+ * 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 json,
+ {JsonDecoderCallback/*<K>*/ keyDecoder,
+ JsonDecoderCallback/*<V>*/ valueDecoder}) {
+ if (json == null) {
+ return {};
+ } else if (json is Map) {
+ Map/*<K, V>*/ result = /*<K, V>*/ {};
+ json.forEach((String key, value) {
+ Object/*=K*/ decodedKey;
+ if (keyDecoder != null) {
+ decodedKey = keyDecoder('$jsonPath.key', key);
+ } else {
+ decodedKey = key as Object/*=K*/;
+ }
+ if (valueDecoder != null) {
+ value = valueDecoder('$jsonPath[${JSON.encode(key)}]', value);
+ }
+ result[decodedKey] = value as Object/*=V*/;
+ });
+ return result;
+ } else {
+ throw mismatch(jsonPath, 'Map', json);
+ }
+ }
+
+ /**
+ * Decode a JSON object that is expected to be a string.
+ */
+ String decodeString(String jsonPath, Object json) {
+ if (json is String) {
+ return json;
+ } else {
+ throw mismatch(jsonPath, 'String', json);
+ }
+ }
+
+ /**
+ * Decode a JSON object that is expected to be one of several choices,
+ * 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 json, String field,
+ Map<String, JsonDecoderCallback> decoders) {
+ if (json is Map) {
+ if (!json.containsKey(field)) {
+ throw missingKey(jsonPath, field);
+ }
+ var disambiguatorPath = '$jsonPath[${JSON.encode(field)}]';
+ String disambiguator = decodeString(disambiguatorPath, json[field]);
+ if (!decoders.containsKey(disambiguator)) {
+ throw mismatch(
+ disambiguatorPath, 'One of: ${decoders.keys.toList()}', json);
+ }
+ return decoders[disambiguator](jsonPath, json);
+ } else {
+ throw mismatch(jsonPath, 'Map', json);
+ }
+ }
+
+ /**
+ * 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]);
+
+ /**
+ * Create an exception to throw if the JSON object at [jsonPath] is missing
+ * the key [key].
+ */
+ dynamic missingKey(String jsonPath, String key);
+}
+
+/**
+ * JsonDecoder for decoding requests. Errors are reporting by throwing a
+ * [RequestFailure].
+ */
+class RequestDecoder extends JsonDecoder {
+ /**
+ * The request being deserialized.
+ */
+ final Request _request;
+
+ RequestDecoder(this._request);
+
+ @override
+ RefactoringKind get refactoringKind {
+ // Refactoring feedback objects should never appear in requests.
+ return null;
+ }
+
+ @override
+ dynamic mismatch(String jsonPath, String expected, [Object actual]) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('Expected to be ');
+ buffer.write(expected);
+ if (actual != null) {
+ buffer.write('; found "');
+ buffer.write(JSON.encode(actual));
+ buffer.write('"');
+ }
+ return new RequestFailure(RequestErrorFactory.invalidParameter(
+ _request, jsonPath, buffer.toString()));
+ }
+
+ @override
+ dynamic missingKey(String jsonPath, String key) {
+ return new RequestFailure(RequestErrorFactory.invalidParameter(
+ _request, jsonPath, 'Expected to contain key ${JSON.encode(key)}'));
+ }
+}
+
+/**
+ * JsonDecoder for decoding responses from the server. This is intended to be
+ * used only for testing. Errors are reported using bare [Exception] objects.
+ */
+class ResponseDecoder extends JsonDecoder {
+ @override
+ final RefactoringKind refactoringKind;
+
+ ResponseDecoder(this.refactoringKind);
+
+ @override
+ dynamic mismatch(String jsonPath, String expected, [Object actual]) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write('Expected ');
+ buffer.write(expected);
+ if (actual != null) {
+ buffer.write(' found "');
+ buffer.write(JSON.encode(actual));
+ buffer.write('"');
+ }
+ buffer.write(' at ');
+ buffer.write(jsonPath);
+ return new Exception(buffer.toString());
+ }
+
+ @override
+ dynamic missingKey(String jsonPath, String key) {
+ return new Exception('Missing key $key at $jsonPath');
+ }
+}
+
+/**
+ * The result data associated with a response.
+ */
+abstract class ResponseResult implements HasToJson {
+ /**
+ * Return a response whose result data is this object for the request with the
+ * given [id].
+ */
+ Response toResponse(String id);
+}

Powered by Google App Engine
This is Rietveld 408576698