Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 523e378

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Add support for providing fixes in analysis options files
Change-Id: I6c9a0a0624201538a90608c2eff9cff7b6cdb4b8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98870 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
1 parent b766943 commit 523e378

File tree

7 files changed

+485
-33
lines changed

7 files changed

+485
-33
lines changed

pkg/analysis_server/lib/src/edit/edit_domain.dart

Lines changed: 84 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import 'package:analysis_server/src/services/correction/assist.dart';
2222
import 'package:analysis_server/src/services/correction/assist_internal.dart';
2323
import 'package:analysis_server/src/services/correction/change_workspace.dart';
2424
import 'package:analysis_server/src/services/correction/fix.dart';
25+
import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
2526
import 'package:analysis_server/src/services/correction/fix_internal.dart';
2627
import 'package:analysis_server/src/services/correction/organize_directives.dart';
2728
import 'package:analysis_server/src/services/correction/sort_members.dart';
@@ -33,16 +34,23 @@ import 'package:analyzer/dart/analysis/session.dart';
3334
import 'package:analyzer/dart/ast/ast.dart';
3435
import 'package:analyzer/dart/element/element.dart';
3536
import 'package:analyzer/error/error.dart' as engine;
37+
import 'package:analyzer/file_system/file_system.dart';
38+
// ignore: deprecated_member_use
39+
import 'package:analyzer/source/analysis_options_provider.dart';
40+
import 'package:analyzer/source/line_info.dart';
3641
import 'package:analyzer/src/dart/ast/utilities.dart';
3742
import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
3843
import 'package:analyzer/src/error/codes.dart' as engine;
3944
import 'package:analyzer/src/generated/engine.dart' as engine;
45+
import 'package:analyzer/src/generated/engine.dart';
4046
import 'package:analyzer/src/generated/parser.dart' as engine;
4147
import 'package:analyzer/src/generated/source.dart';
48+
import 'package:analyzer/src/task/options.dart';
4249
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
4350
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
4451
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
4552
import 'package:dart_style/dart_style.dart';
53+
import 'package:yaml/yaml.dart';
4654

4755
int test_resetCount = 0;
4856

@@ -231,17 +239,14 @@ class EditDomainHandler extends AbstractRequestHandler {
231239
new EditGetDartfixInfoResult(allFixes.map((i) => i.asDartFix()).toList())
232240
.toResponse(request.id);
233241

234-
Future getFixes(Request request) async {
235-
// TODO(brianwilkerson) Determine whether this await is necessary.
236-
await null;
242+
Future<void> getFixes(Request request) async {
237243
EditGetFixesParams params = new EditGetFixesParams.fromRequest(request);
238244
String file = params.file;
239245
int offset = params.offset;
240246

241247
if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
242248
return;
243249
}
244-
245250
//
246251
// Allow plugins to start computing fixes.
247252
//
@@ -569,12 +574,49 @@ class EditDomainHandler extends AbstractRequestHandler {
569574
}
570575

571576
/**
572-
* Compute and return the fixes associated with server-generated errors.
577+
* Compute and return the fixes associated with server-generated errors in
578+
* analysis options files.
573579
*/
574-
Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
580+
Future<List<AnalysisErrorFixes>> _computeAnalysisOptionsFixes(
581+
String file, int offset) async {
582+
List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
583+
File optionsFile = server.resourceProvider.getFile(file);
584+
String content = _safelyRead(optionsFile);
585+
if (content == null) {
586+
return errorFixesList;
587+
}
588+
LineInfo lineInfo = new LineInfo.fromContent(content);
589+
SourceFactory sourceFactory = server.getAnalysisDriver(file).sourceFactory;
590+
List<engine.AnalysisError> errors = analyzeAnalysisOptions(
591+
optionsFile.createSource(), content, sourceFactory);
592+
YamlMap options = _getOptions(sourceFactory, content);
593+
if (options == null) {
594+
return errorFixesList;
595+
}
596+
for (engine.AnalysisError error in errors) {
597+
AnalysisOptionsFixGenerator generator =
598+
new AnalysisOptionsFixGenerator(error, content, options);
599+
List<Fix> fixes = await generator.computeFixes();
600+
if (fixes.isNotEmpty) {
601+
fixes.sort(Fix.SORT_BY_RELEVANCE);
602+
AnalysisError serverError =
603+
newAnalysisError_fromEngine(lineInfo, error);
604+
AnalysisErrorFixes errorFixes = new AnalysisErrorFixes(serverError);
605+
errorFixesList.add(errorFixes);
606+
fixes.forEach((fix) {
607+
errorFixes.fixes.add(fix.change);
608+
});
609+
}
610+
}
611+
return errorFixesList;
612+
}
613+
614+
/**
615+
* Compute and return the fixes associated with server-generated errors in
616+
* Dart files.
617+
*/
618+
Future<List<AnalysisErrorFixes>> _computeDartFixes(
575619
String file, int offset) async {
576-
// TODO(brianwilkerson) Determine whether this await is necessary.
577-
await null;
578620
List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
579621
var result = await server.getResolvedUnit(file);
580622
if (result != null) {
@@ -603,6 +645,20 @@ class EditDomainHandler extends AbstractRequestHandler {
603645
return errorFixesList;
604646
}
605647

648+
/**
649+
* Compute and return the fixes associated with server-generated errors.
650+
*/
651+
Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
652+
String file, int offset) async {
653+
if (AnalysisEngine.isDartFileName(file)) {
654+
return _computeDartFixes(file, offset);
655+
} else if (AnalysisEngine.isAnalysisOptionsFileName(
656+
file, server.resourceProvider.pathContext)) {
657+
return _computeAnalysisOptionsFixes(file, offset);
658+
}
659+
return <AnalysisErrorFixes>[];
660+
}
661+
606662
Response _getAvailableRefactorings(Request request) {
607663
_getAvailableRefactoringsImpl(request);
608664
return Response.DELAYED_RESPONSE;
@@ -676,6 +732,16 @@ class EditDomainHandler extends AbstractRequestHandler {
676732
server.sendResponse(result.toResponse(request.id));
677733
}
678734

735+
YamlMap _getOptions(SourceFactory sourceFactory, String content) {
736+
AnalysisOptionsProvider optionsProvider =
737+
new AnalysisOptionsProvider(sourceFactory);
738+
try {
739+
return optionsProvider.getOptionsFromString(content);
740+
} on OptionsFormatException {
741+
return null;
742+
}
743+
}
744+
679745
Response _getRefactoring(Request request) {
680746
if (refactoringManager.hasPendingRequest) {
681747
refactoringManager.cancel();
@@ -692,6 +758,16 @@ class EditDomainHandler extends AbstractRequestHandler {
692758
refactoringManager = new _RefactoringManager(server, refactoringWorkspace);
693759
}
694760

761+
/// Return the contents of the [file], or `null` if the file does not exist or
762+
/// cannot be read.
763+
String _safelyRead(File file) {
764+
try {
765+
return file.readAsStringSync();
766+
} on FileSystemException {
767+
return null;
768+
}
769+
}
770+
695771
static int _getNumberOfScanParseErrors(List<engine.AnalysisError> errors) {
696772
int numScanParseErrors = 0;
697773
for (engine.AnalysisError error in errors) {

pkg/analysis_server/lib/src/services/correction/fix.dart

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import 'package:analyzer/src/generated/parser.dart';
1111
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
1212
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
1313

14-
/**
15-
* Return true if this [errorCode] is likely to have a fix associated with it.
16-
*/
14+
/// Return true if this [errorCode] is likely to have a fix associated with it.
1715
bool hasFix(ErrorCode errorCode) =>
1816
errorCode == StaticWarningCode.UNDEFINED_CLASS_BOOLEAN ||
1917
errorCode == StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER ||
@@ -103,9 +101,14 @@ bool hasFix(ErrorCode errorCode) =>
103101
errorCode.name == LintNames.unnecessary_this ||
104102
errorCode.name == LintNames.use_rethrow_when_possible));
105103

106-
/**
107-
* The implementation of [DartFixContext].
108-
*/
104+
/// An enumeration of quick fix kinds for the errors found in an analysis
105+
/// options file.
106+
class AnalysisOptionsFixKind {
107+
static const REMOVE_SETTING =
108+
const FixKind('REMOVE_SETTING', 50, "Remove '{0}'");
109+
}
110+
111+
/// The implementation of [DartFixContext].
109112
class DartFixContextImpl implements DartFixContext {
110113
@override
111114
final ChangeWorkspace workspace;
@@ -119,9 +122,7 @@ class DartFixContextImpl implements DartFixContext {
119122
DartFixContextImpl(this.workspace, this.resolveResult, this.error);
120123
}
121124

122-
/**
123-
* An enumeration of possible quick fix kinds.
124-
*/
125+
/// An enumeration of quick fix kinds found in a Dart file.
125126
class DartFixKind {
126127
static const ADD_ASYNC =
127128
const FixKind('ADD_ASYNC', 50, "Add 'async' modifier");

0 commit comments

Comments
 (0)