mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Add support code to make fixes easier in plugins
R=scheglov@google.com Review-Url: https://codereview.chromium.org/2962903002 .
This commit is contained in:
parent
563720617c
commit
6248e7cab2
6 changed files with 111 additions and 38 deletions
|
@ -9,6 +9,7 @@ import 'package:analyzer/file_system/file_system.dart';
|
|||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer_plugin/protocol/protocol_common.dart'
|
||||
show SourceChange;
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
|
||||
/**
|
||||
* A description of a single proposed fix for some problem.
|
||||
|
@ -27,7 +28,7 @@ class Fix {
|
|||
*/
|
||||
static final Comparator<Fix> SORT_BY_RELEVANCE =
|
||||
(Fix firstFix, Fix secondFix) =>
|
||||
firstFix.kind.relevance - secondFix.kind.relevance;
|
||||
firstFix.kind.priority - secondFix.kind.priority;
|
||||
|
||||
/**
|
||||
* A description of the fix being proposed.
|
||||
|
@ -85,40 +86,3 @@ abstract class FixContributor {
|
|||
*/
|
||||
Future<List<Fix>> computeFixes(FixContext context);
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of a class of fixes. Instances are intended to hold the
|
||||
* information that is common across a number of fixes and to be shared by those
|
||||
* fixes. For example, if an unnecessary cast is found then one of the suggested
|
||||
* fixes will be to remove the cast. If there are multiple unnecessary casts in
|
||||
* a single file, then there will be multiple fixes, one per occurrence, but
|
||||
* they will all share the same kind.
|
||||
*
|
||||
* Clients may not extend, implement or mix-in this class.
|
||||
*/
|
||||
class FixKind {
|
||||
/**
|
||||
* The name of this kind of fix, used for debugging.
|
||||
*/
|
||||
final String name;
|
||||
|
||||
/**
|
||||
* The relevance of this kind of fix for the kind of error being addressed.
|
||||
*/
|
||||
final int relevance;
|
||||
|
||||
/**
|
||||
* A human-readable description of the changes that will be applied by this
|
||||
* kind of fix.
|
||||
*/
|
||||
final String message;
|
||||
|
||||
/**
|
||||
* Initialize a newly created kind of fix to have the given [name],
|
||||
* [relevance] and [message].
|
||||
*/
|
||||
const FixKind(this.name, this.relevance, this.message);
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:analyzer/file_system/file_system.dart';
|
|||
import 'package:analyzer/src/dart/analysis/driver.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:analyzer/src/generated/parser.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
|
||||
/**
|
||||
* Return true if this [errorCode] is likely to have a fix associated with it.
|
||||
|
|
|
@ -44,6 +44,7 @@ import 'package:analyzer_plugin/protocol/protocol_common.dart'
|
|||
hide AnalysisError, Element, ElementKind;
|
||||
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart' hide FixContributor;
|
||||
import 'package:analyzer_plugin/utilities/range_factory.dart';
|
||||
import 'package:path/path.dart';
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import 'package:analyzer/src/generated/parser.dart';
|
|||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:analyzer_plugin/protocol/protocol_common.dart'
|
||||
hide AnalysisError;
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// 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 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:analyzer_plugin/protocol/protocol_common.dart'
|
||||
hide AnalysisError;
|
||||
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
|
||||
|
||||
/**
|
||||
* A partial implementation of a [FixContributor] that iterates over the list of
|
||||
* errors and provides a utility method to make it easier to add fixes.
|
||||
*
|
||||
* Clients may not extend or implement this class, but are allowed to use it as
|
||||
* a mix-in when creating a subclass of [FixContributor].
|
||||
*/
|
||||
abstract class FixContributorMixin implements FixContributor {
|
||||
/**
|
||||
* The request that specifies the fixes that are to be built.
|
||||
*/
|
||||
DartFixesRequest request;
|
||||
|
||||
/**
|
||||
* The collector to which fixes should be added.
|
||||
*/
|
||||
FixCollector collector;
|
||||
|
||||
/**
|
||||
* Add a fix for the given [error]. Use the [kind] of the fix to get the
|
||||
* message and priority, and use the change [builder] to get the edits that
|
||||
* comprise the fix. If the message has parameters, then use the list of
|
||||
* [args] to populate the message.
|
||||
*/
|
||||
void addFix(AnalysisError error, FixKind kind, ChangeBuilder builder,
|
||||
{List<Object> args: null}) {
|
||||
SourceChange change = builder.sourceChange;
|
||||
if (change.edits.isEmpty) {
|
||||
return;
|
||||
}
|
||||
change.message = formatList(kind.message, args);
|
||||
collector.addFix(error,
|
||||
new PrioritizedSourceChange(kind.priority, builder.sourceChange));
|
||||
}
|
||||
|
||||
@override
|
||||
void computeFixes(DartFixesRequest request, FixCollector collector) {
|
||||
this.request = request;
|
||||
this.collector = collector;
|
||||
try {
|
||||
for (AnalysisError error in request.errorsToFix) {
|
||||
computeFixesForError(error);
|
||||
}
|
||||
} finally {
|
||||
this.request = null;
|
||||
this.collector = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the fixes that are appropriate for the given [error] and add them
|
||||
* to the fix [collector].
|
||||
*/
|
||||
void computeFixesForError(AnalysisError error);
|
||||
}
|
|
@ -108,3 +108,42 @@ class FixGenerator {
|
|||
return new GeneratorResult(result, notifications);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A description of a class of fixes. Instances are intended to hold the
|
||||
* information that is common across a number of fixes and to be shared by those
|
||||
* fixes. For example, if an unnecessary cast is found then one of the suggested
|
||||
* fixes will be to remove the cast. If there are multiple unnecessary casts in
|
||||
* a single file, then there will be multiple fixes, one per occurrence, but
|
||||
* they will all share the same kind.
|
||||
*
|
||||
* Clients may not extend, implement or mix-in this class.
|
||||
*/
|
||||
class FixKind {
|
||||
/**
|
||||
* The name of this kind of fix, used for debugging.
|
||||
*/
|
||||
final String name;
|
||||
|
||||
/**
|
||||
* The priority of this kind of fix for the kind of error being addressed.
|
||||
*/
|
||||
final int priority;
|
||||
|
||||
/**
|
||||
* A human-readable description of the changes that will be applied by this
|
||||
* kind of fix. The message can contain parameters, where each parameter is
|
||||
* represented by a zero-based index inside curly braces. For example, the
|
||||
* message `"Create a component named '{0}' in '{1}'"` contains two parameters.
|
||||
*/
|
||||
final String message;
|
||||
|
||||
/**
|
||||
* Initialize a newly created kind of fix to have the given [name],
|
||||
* [priority] and [message].
|
||||
*/
|
||||
const FixKind(this.name, this.priority, this.message);
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue