First cut dartfix protocol

and address comments in https://dart-review.googlesource.com/c/sdk/+/76320

Change-Id: I5c7ab40810d4116b1d36de90b7234d0a932bae82
Reviewed-on: https://dart-review.googlesource.com/76400
Commit-Queue: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Dan Rubel 2018-09-25 16:56:48 +00:00 committed by commit-bot@chromium.org
parent 4cf2d3990b
commit c624f8b0a9
11 changed files with 336 additions and 0 deletions

View file

@ -1851,6 +1851,7 @@ a:focus, a:hover {
<h3>Requests</h3><dl><dt class="request"><a name="request_edit.format">edit.format</a></dt><dd><div class="box"><pre>request: {
"id": String
"method": "edit.format"

View file

@ -125,6 +125,8 @@ const String DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
const String DIAGNOSTIC_REQUEST_GET_SERVER_PORT = 'diagnostic.getServerPort';
const String DIAGNOSTIC_RESPONSE_GET_DIAGNOSTICS_CONTEXTS = 'contexts';
const String DIAGNOSTIC_RESPONSE_GET_SERVER_PORT_PORT = 'port';
const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
const String EDIT_REQUEST_FORMAT = 'edit.format';
const String EDIT_REQUEST_FORMAT_FILE = 'file';
const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
@ -171,6 +173,8 @@ const String EDIT_REQUEST_ORGANIZE_DIRECTIVES = 'edit.organizeDirectives';
const String EDIT_REQUEST_ORGANIZE_DIRECTIVES_FILE = 'file';
const String EDIT_REQUEST_SORT_MEMBERS = 'edit.sortMembers';
const String EDIT_REQUEST_SORT_MEMBERS_FILE = 'file';
const String EDIT_RESPONSE_DARTFIX_DESCRIPTION = 'description';
const String EDIT_RESPONSE_DARTFIX_FIXES = 'fixes';
const String EDIT_RESPONSE_FORMAT_EDITS = 'edits';
const String EDIT_RESPONSE_FORMAT_SELECTION_LENGTH = 'selectionLength';
const String EDIT_RESPONSE_FORMAT_SELECTION_OFFSET = 'selectionOffset';

View file

@ -6165,6 +6165,218 @@ class DiagnosticGetServerPortResult implements ResponseResult {
}
}
/**
* edit.dartfix params
*
* {
* "included": List<FilePath>
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class EditDartfixParams implements RequestParams {
List<String> _included;
/**
* A list of the files and directories for which edits should be suggested.
* If a request is made for a file which does not exist, or which is not
* currently subject to analysis (e.g. because it is not associated with any
* analysis root specified to analysis.setAnalysisRoots), an error of type
* FORMAT_INVALID_FILE will be generated.
*/
List<String> get included => _included;
/**
* A list of the files and directories for which edits should be suggested.
* If a request is made for a file which does not exist, or which is not
* currently subject to analysis (e.g. because it is not associated with any
* analysis root specified to analysis.setAnalysisRoots), an error of type
* FORMAT_INVALID_FILE will be generated.
*/
void set included(List<String> value) {
assert(value != null);
this._included = value;
}
EditDartfixParams(List<String> included) {
this.included = included;
}
factory EditDartfixParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
List<String> included;
if (json.containsKey("included")) {
included = jsonDecoder.decodeList(
jsonPath + ".included", json["included"], jsonDecoder.decodeString);
} else {
throw jsonDecoder.mismatch(jsonPath, "included");
}
return new EditDartfixParams(included);
} else {
throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
}
}
factory EditDartfixParams.fromRequest(Request request) {
return new EditDartfixParams.fromJson(
new RequestDecoder(request), "params", request.params);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["included"] = included;
return result;
}
@override
Request toRequest(String id) {
return new Request(id, "edit.dartfix", toJson());
}
@override
String toString() => json.encode(toJson());
@override
bool operator ==(other) {
if (other is EditDartfixParams) {
return listEqual(
included, other.included, (String a, String b) => a == b);
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, included.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* edit.dartfix result
*
* {
* "description": List<String>
* "fixes": List<SourceFileEdit>
* }
*
* Clients may not extend, implement or mix-in this class.
*/
class EditDartfixResult implements ResponseResult {
List<String> _description;
List<SourceFileEdit> _fixes;
/**
* A list of human readable changes made by applying the fixes.
*/
List<String> get description => _description;
/**
* A list of human readable changes made by applying the fixes.
*/
void set description(List<String> value) {
assert(value != null);
this._description = value;
}
/**
* The suggested fixes.
*/
List<SourceFileEdit> get fixes => _fixes;
/**
* The suggested fixes.
*/
void set fixes(List<SourceFileEdit> value) {
assert(value != null);
this._fixes = value;
}
EditDartfixResult(List<String> description, List<SourceFileEdit> fixes) {
this.description = description;
this.fixes = fixes;
}
factory EditDartfixResult.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
if (json == null) {
json = {};
}
if (json is Map) {
List<String> description;
if (json.containsKey("description")) {
description = jsonDecoder.decodeList(jsonPath + ".description",
json["description"], jsonDecoder.decodeString);
} else {
throw jsonDecoder.mismatch(jsonPath, "description");
}
List<SourceFileEdit> fixes;
if (json.containsKey("fixes")) {
fixes = jsonDecoder.decodeList(
jsonPath + ".fixes",
json["fixes"],
(String jsonPath, Object json) =>
new SourceFileEdit.fromJson(jsonDecoder, jsonPath, json));
} else {
throw jsonDecoder.mismatch(jsonPath, "fixes");
}
return new EditDartfixResult(description, fixes);
} else {
throw jsonDecoder.mismatch(jsonPath, "edit.dartfix result", json);
}
}
factory EditDartfixResult.fromResponse(Response response) {
return new EditDartfixResult.fromJson(
new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
"result",
response.result);
}
@override
Map<String, dynamic> toJson() {
Map<String, dynamic> result = {};
result["description"] = description;
result["fixes"] =
fixes.map((SourceFileEdit value) => value.toJson()).toList();
return result;
}
@override
Response toResponse(String id) {
return new Response(id, result: toJson());
}
@override
String toString() => json.encode(toJson());
@override
bool operator ==(other) {
if (other is EditDartfixResult) {
return listEqual(
description, other.description, (String a, String b) => a == b) &&
listEqual(fixes, other.fixes,
(SourceFileEdit a, SourceFileEdit b) => a == b);
}
return false;
}
@override
int get hashCode {
int hash = 0;
hash = JenkinsSmiHash.combine(hash, description.hashCode);
hash = JenkinsSmiHash.combine(hash, fixes.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
/**
* edit.format params
*

View file

@ -38,6 +38,7 @@ server calls. This file is validated by `coverage_test.dart`.
- [x] diagnostic.getServerPort
## edit domain
- [ ] edit.dartfix
- [x] edit.format
- [x] edit.getAssists
- [x] edit.getAvailableRefactorings

View file

@ -1494,6 +1494,39 @@ abstract class IntegrationTestMixin {
decoder, 'result', result);
}
/**
* Analyze the specified sources for recommended changes and return a set of
* suggested edits for those sources. These edits may include changes to
* sources outside the set of specified sources if a change in a specified
* source requires it.
*
* Parameters
*
* included: List<FilePath>
*
* A list of the files and directories for which edits should be suggested.
* If a request is made for a file which does not exist, or which is not
* currently subject to analysis (e.g. because it is not associated with
* any analysis root specified to analysis.setAnalysisRoots), an error of
* type FORMAT_INVALID_FILE will be generated.
*
* Returns
*
* description: List<String>
*
* A list of human readable changes made by applying the fixes.
*
* fixes: List<SourceFileEdit>
*
* The suggested fixes.
*/
Future<EditDartfixResult> sendEditDartfix(List<String> included) async {
var params = new EditDartfixParams(included).toJson();
var result = await server.send("edit.dartfix", params);
ResponseDecoder decoder = new ResponseDecoder(null);
return new EditDartfixResult.fromJson(decoder, 'result', result);
}
/**
* Return the set of fixes that are available for the errors at a given
* offset in a given file.

View file

@ -2121,6 +2121,28 @@ final Matcher isDiagnosticGetServerPortParams = isNull;
final Matcher isDiagnosticGetServerPortResult = new LazyMatcher(() =>
new MatchesJsonObject("diagnostic.getServerPort result", {"port": isInt}));
/**
* edit.dartfix params
*
* {
* "included": List<FilePath>
* }
*/
final Matcher isEditDartfixParams = new LazyMatcher(() => new MatchesJsonObject(
"edit.dartfix params", {"included": isListOf(isFilePath)}));
/**
* edit.dartfix result
*
* {
* "description": List<String>
* "fixes": List<SourceFileEdit>
* }
*/
final Matcher isEditDartfixResult = new LazyMatcher(() => new MatchesJsonObject(
"edit.dartfix result",
{"description": isListOf(isString), "fixes": isListOf(isSourceFileEdit)}));
/**
* edit.format params
*

View file

@ -405,6 +405,20 @@ public interface AnalysisServer {
*/
public void diagnostic_getServerPort(GetServerPortConsumer consumer);
/**
* {@code edit.dartfix}
*
* Analyze the specified sources for recommended changes and return a set of suggested edits for
* those sources. These edits may include changes to sources outside the set of specified sources
* if a change in a specified source requires it.
*
* @param included A list of the files and directories for which edits should be suggested. If a
* request is made for a file which does not exist, or which is not currently subject to
* analysis (e.g. because it is not associated with any analysis root specified to
* analysis.setAnalysisRoots), an error of type FORMAT_INVALID_FILE will be generated.
*/
public void edit_dartfix(List<String> included, DartfixConsumer consumer);
/**
* {@code edit.format}
*

View file

@ -1933,6 +1933,46 @@
</field>
</result>
</request>
<request method="dartfix" experimental="true">
<p>
Analyze the specified sources for recommended changes
and return a set of suggested edits for those sources.
These edits may include changes to sources outside the set
of specified sources if a change in a specified source requires it.
</p>
<params>
<field name="included">
<list>
<ref>FilePath</ref>
</list>
<p>
A list of the files and directories for which edits should be suggested.
If a request is made for a file which does not exist, or which is not
currently subject to analysis (e.g. because it is not associated with
any analysis root specified to analysis.setAnalysisRoots), an error of
type <tt>FORMAT_INVALID_FILE</tt> will be generated.
</p>
</field>
</params>
<result>
<field name="description">
<list>
<ref>String</ref>
</list>
<p>
A list of human readable changes made by applying the fixes.
</p>
</field>
<field name="fixes">
<list>
<ref>SourceFileEdit</ref>
</list>
<p>
The suggested fixes.
</p>
</field>
</result>
</request>
<request method="getFixes">
<p>
Return the set of fixes that are available for the errors at

View file

@ -1,3 +1,6 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'package:analyzer_cli/src/fix/options.dart';

View file

@ -1,3 +1,6 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:analyzer/src/util/sdk.dart';

View file

@ -1,3 +1,6 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:io';