Skip to content

Commit

Permalink
bulk fix protocol
Browse files Browse the repository at this point in the history
Change-Id: Id8505d5ad6f0f3d1c5289ab12d4932c6174f72e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153623
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
  • Loading branch information
pq authored and commit-bot@chromium.org committed Jul 10, 2020
1 parent 7a1d6a9 commit 3d5df93
Show file tree
Hide file tree
Showing 14 changed files with 536 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/analysis_server/doc/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -2083,6 +2083,7 @@ <h2 class="domain"><a name="domain_edit">edit domain</a></h2>




<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"
Expand Down
3 changes: 3 additions & 0 deletions pkg/analysis_server/lib/protocol/protocol_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,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_BULK_FIXES = 'edit.bulkFixes';
const String EDIT_REQUEST_BULK_FIXES_INCLUDED = 'included';
const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
const String EDIT_REQUEST_DARTFIX_EXCLUDED_FIXES = 'excludedFixes';
const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
Expand Down Expand Up @@ -220,6 +222,7 @@ 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_BULK_FIXES_EDITS = 'edits';
const String EDIT_RESPONSE_DARTFIX_DETAILS = 'details';
const String EDIT_RESPONSE_DARTFIX_EDITS = 'edits';
const String EDIT_RESPONSE_DARTFIX_HAS_ERRORS = 'hasErrors';
Expand Down
174 changes: 174 additions & 0 deletions pkg/analysis_server/lib/protocol/protocol_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7115,6 +7115,180 @@ class DiagnosticGetServerPortResult implements ResponseResult {
}
}

/// edit.bulkFixes params
///
/// {
/// "included": List<FilePath>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditBulkFixesParams implements RequestParams {
List<String> _included;

/// A list of the files and directories for which edits should be suggested.
///
/// If a request is made with a path that is invalid, e.g. is not absolute
/// and normalized, an error of type INVALID_FILE_PATH_FORMAT will be
/// generated. 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 FILE_NOT_ANALYZED 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 with a path that is invalid, e.g. is not absolute
/// and normalized, an error of type INVALID_FILE_PATH_FORMAT will be
/// generated. 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 FILE_NOT_ANALYZED will be generated.
set included(List<String> value) {
assert(value != null);
_included = value;
}

EditBulkFixesParams(List<String> included) {
this.included = included;
}

factory EditBulkFixesParams.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
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 EditBulkFixesParams(included);
} else {
throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes params', json);
}
}

factory EditBulkFixesParams.fromRequest(Request request) {
return EditBulkFixesParams.fromJson(
RequestDecoder(request), 'params', request.params);
}

@override
Map<String, dynamic> toJson() {
var result = <String, dynamic>{};
result['included'] = included;
return result;
}

@override
Request toRequest(String id) {
return Request(id, 'edit.bulkFixes', toJson());
}

@override
String toString() => json.encode(toJson());

@override
bool operator ==(other) {
if (other is EditBulkFixesParams) {
return listEqual(
included, other.included, (String a, String b) => a == b);
}
return false;
}

@override
int get hashCode {
var hash = 0;
hash = JenkinsSmiHash.combine(hash, included.hashCode);
return JenkinsSmiHash.finish(hash);
}
}

/// edit.bulkFixes result
///
/// {
/// "edits": List<SourceFileEdit>
/// }
///
/// Clients may not extend, implement or mix-in this class.
class EditBulkFixesResult implements ResponseResult {
List<SourceFileEdit> _edits;

/// A list of source edits to apply the recommended changes.
List<SourceFileEdit> get edits => _edits;

/// A list of source edits to apply the recommended changes.
set edits(List<SourceFileEdit> value) {
assert(value != null);
_edits = value;
}

EditBulkFixesResult(List<SourceFileEdit> edits) {
this.edits = edits;
}

factory EditBulkFixesResult.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object json) {
json ??= {};
if (json is Map) {
List<SourceFileEdit> edits;
if (json.containsKey('edits')) {
edits = jsonDecoder.decodeList(
jsonPath + '.edits',
json['edits'],
(String jsonPath, Object json) =>
SourceFileEdit.fromJson(jsonDecoder, jsonPath, json));
} else {
throw jsonDecoder.mismatch(jsonPath, 'edits');
}
return EditBulkFixesResult(edits);
} else {
throw jsonDecoder.mismatch(jsonPath, 'edit.bulkFixes result', json);
}
}

factory EditBulkFixesResult.fromResponse(Response response) {
return EditBulkFixesResult.fromJson(
ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
'result',
response.result);
}

@override
Map<String, dynamic> toJson() {
var result = <String, dynamic>{};
result['edits'] =
edits.map((SourceFileEdit value) => value.toJson()).toList();
return result;
}

@override
Response toResponse(String id) {
return Response(id, result: toJson());
}

@override
String toString() => json.encode(toJson());

@override
bool operator ==(other) {
if (other is EditBulkFixesResult) {
return listEqual(
edits, other.edits, (SourceFileEdit a, SourceFileEdit b) => a == b);
}
return false;
}

@override
int get hashCode {
var hash = 0;
hash = JenkinsSmiHash.combine(hash, edits.hashCode);
return JenkinsSmiHash.finish(hash);
}
}

/// edit.dartfix params
///
/// {
Expand Down
19 changes: 19 additions & 0 deletions pkg/analysis_server/lib/src/edit/edit_bulk_fixes.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';

class EditBulkFixes {
final AnalysisServer server;
final Request request;

EditBulkFixes(this.server, this.request);

Future<Response> compute() async {
// todo (pq): implemennt
return EditBulkFixesResult([]).toResponse(request.id);
}
}
20 changes: 20 additions & 0 deletions pkg/analysis_server/lib/src/edit/edit_domain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import 'package:analysis_server/src/collections.dart';
import 'package:analyzer/src/exception/exception.dart';
import 'package:analysis_server/src/computer/import_elements_computer.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/edit/edit_bulk_fixes.dart'
show EditBulkFixes;
import 'package:analysis_server/src/edit/edit_dartfix.dart' show EditDartFix;
import 'package:analysis_server/src/edit/fix/dartfix_info.dart' show allFixes;
import 'package:analysis_server/src/plugin/plugin_manager.dart';
Expand Down Expand Up @@ -92,6 +94,21 @@ class EditDomainHandler extends AbstractRequestHandler {
_newRefactoringManager();
}

Future bulkFixes(Request request) async {
//
// Compute fixes
//
try {
var bulkFix = EditBulkFixes(server, request);
var response = await bulkFix.compute();

server.sendResponse(response);
} catch (exception, stackTrace) {
server.sendServerErrorNotification('Exception while getting bulk fixes',
CaughtException(exception, stackTrace), stackTrace);
}
}

Future dartfix(Request request) async {
// TODO(danrubel): Add support for dartfix plugins

Expand Down Expand Up @@ -356,6 +373,9 @@ class EditDomainHandler extends AbstractRequestHandler {
return Response.DELAYED_RESPONSE;
} else if (requestName == EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS) {
return _getAvailableRefactorings(request);
} else if (requestName == EDIT_REQUEST_BULK_FIXES) {
bulkFixes(request);
return Response.DELAYED_RESPONSE;
} else if (requestName == EDIT_REQUEST_GET_DARTFIX_INFO) {
return getDartfixInfo(request);
} else if (requestName == EDIT_REQUEST_GET_FIXES) {
Expand Down
1 change: 1 addition & 0 deletions pkg/analysis_server/test/integration/coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ server calls. This file is validated by `coverage_test.dart`.
- [x] diagnostic.getServerPort

## edit domain
- [x] edit.bulkFixes
- [x] edit.dartfix
- [x] edit.format
- [x] edit.getAssists
Expand Down
37 changes: 37 additions & 0 deletions pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../support/integration_tests.dart';

void main() {
defineReflectiveSuite(() {
defineReflectiveTests(BulkFixesTest);
});
}

@reflectiveTest
class BulkFixesTest extends AbstractAnalysisServerIntegrationTest {
void setupTarget() {
writeFile(sourcePath('test.dart'), '''
class A {
void f() {}
}
class B extends A {
void f() { }
}
''');
standardAnalysisSetup();
}

@failingTest
Future<void> test_bulk_fix_override() async {
setupTarget();

var result = await sendEditBulkFixes([sourceDirectory.path]);
expect(result.edits.length, 1);
}
}
2 changes: 2 additions & 0 deletions pkg/analysis_server/test/integration/edit/test_all.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'bulk_fixes_test.dart' as bulk_fixes_test;
import 'dartfix_test.dart' as dartfix_test;
import 'format_test.dart' as format_test;
import 'get_assists_test.dart' as get_assists_test;
Expand All @@ -24,6 +25,7 @@ import 'sort_members_test.dart' as sort_members_test;

void main() {
defineReflectiveSuite(() {
bulk_fixes_test.main();
dartfix_test.main();
format_test.main();
get_assists_test.main();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,38 @@ abstract class IntegrationTestMixin {
return EditGetDartfixInfoResult.fromJson(decoder, 'result', result);
}

/// Analyze the specified sources for fixes that can be applied in bulk 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 with a path that is invalid, e.g. is not absolute
/// and normalized, an error of type INVALID_FILE_PATH_FORMAT will be
/// generated. 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 FILE_NOT_ANALYZED will be
/// generated.
///
/// Returns
///
/// edits: List<SourceFileEdit>
///
/// A list of source edits to apply the recommended changes.
Future<EditBulkFixesResult> sendEditBulkFixes(List<String> included) async {
var params = EditBulkFixesParams(included).toJson();
var result = await server.send('edit.bulkFixes', params);
var decoder = ResponseDecoder(null);
return EditBulkFixesResult.fromJson(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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,22 @@ final Matcher isDiagnosticGetServerPortParams = isNull;
final Matcher isDiagnosticGetServerPortResult = LazyMatcher(() =>
MatchesJsonObject('diagnostic.getServerPort result', {'port': isInt}));

/// edit.bulkFixes params
///
/// {
/// "included": List<FilePath>
/// }
final Matcher isEditBulkFixesParams = LazyMatcher(() => MatchesJsonObject(
'edit.bulkFixes params', {'included': isListOf(isFilePath)}));

/// edit.bulkFixes result
///
/// {
/// "edits": List<SourceFileEdit>
/// }
final Matcher isEditBulkFixesResult = LazyMatcher(() => MatchesJsonObject(
'edit.bulkFixes result', {'edits': isListOf(isSourceFileEdit)}));

/// edit.dartfix params
///
/// {
Expand Down
Loading

0 comments on commit 3d5df93

Please sign in to comment.