| // Copyright (c) 2019, 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_generated.dart' |
| show DartFix, EditDartfixParams; |
| import 'package:analysis_server/src/edit/edit_dartfix.dart'; |
| import 'package:analysis_server/src/edit/fix/dartfix_listener.dart'; |
| import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart'; |
| import 'package:analysis_server/src/edit/fix/fix_error_task.dart'; |
| import 'package:analysis_server/src/edit/fix/fix_lint_task.dart'; |
| import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart'; |
| import 'package:analysis_server/src/services/correction/fix.dart'; |
| import 'package:analyzer/src/lint/registry.dart'; |
| import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; |
| |
| final allFixes = <DartFixInfo>[ |
| // |
| // Error and warning fixes. |
| // |
| DartFixInfo( |
| 'wrong_number_of_type_arguments_constructor', |
| 'Move named constructor type arguments from the name to the type.', |
| FixErrorTask.fixNamedConstructorTypeArgs, |
| ), |
| // |
| // Assist fixes. |
| // |
| DartFixInfo( |
| 'convert_class_to_mixin', |
| 'Convert classes used as a mixin to the new mixin syntax.', |
| PreferMixinFix.task, |
| ), |
| // |
| // Lint fixes. |
| // |
| // TODO(brianwilkerson) The commented out fixes below involve potentially |
| // non-local changes, so they can't currently be applied together. I have an |
| // idea for how to update FixProcessor to support these fixes. |
| // LintFixInfo.alwaysDeclareReturnTypes, |
| // LintFixInfo.alwaysRequireNonNullNamedParameters |
| // LintFixInfo.alwaysSpecifyTypes, |
| LintFixInfo.annotateOverrides, |
| LintFixInfo.avoidAnnotatingWithDynamic, |
| LintFixInfo.avoidEmptyElse, |
| LintFixInfo.avoidInitToNull, |
| LintFixInfo.avoidRedundantArgumentValues, |
| LintFixInfo.avoidRelativeLibImports, |
| LintFixInfo.avoidReturnTypesOnSetters, |
| LintFixInfo.avoidTypesOnClosureParameters, |
| LintFixInfo.awaitOnlyFutures, |
| LintFixInfo.curlyBracesInFlowControlStructures, |
| LintFixInfo.diagnosticDescribeAllProperties, |
| LintFixInfo.emptyCatches, |
| LintFixInfo.emptyConstructorBodies, |
| LintFixInfo.emptyStatements, |
| LintFixInfo.hashAndEquals, |
| LintFixInfo.noDuplicateCaseValues, |
| LintFixInfo.nonConstantIdentifierNames, |
| LintFixInfo.nullClosures, |
| LintFixInfo.omitLocalVariableTypes, |
| LintFixInfo.preferAdjacentStringConcatenation, |
| LintFixInfo.preferCollectionLiterals, |
| LintFixInfo.preferConditionalAssignment, |
| LintFixInfo.preferConstConstructors, |
| LintFixInfo.preferConstConstructorsInImmutables, |
| LintFixInfo.preferConstDeclarations, |
| LintFixInfo.preferContains, |
| LintFixInfo.preferEqualForDefaultValues, |
| LintFixInfo.preferFinalFields, |
| LintFixInfo.preferFinalLocals, |
| LintFixInfo.preferForElementsToMapFromIterable, |
| LintFixInfo.preferGenericFunctionTypeAliases, |
| LintFixInfo.preferIfElementsToConditionalExpressions, |
| LintFixInfo.preferIfNullOperators, |
| LintFixInfo.preferInlinedAdds, |
| LintFixInfo.preferIntLiterals, |
| LintFixInfo.preferIsEmpty, |
| LintFixInfo.preferIsNotEmpty, |
| LintFixInfo.preferIterableWhereType, |
| LintFixInfo.preferNullAwareOperators, |
| LintFixInfo.preferRelativeImports, |
| LintFixInfo.preferSingleQuotes, |
| LintFixInfo.preferSpreadCollections, |
| LintFixInfo.slashForDocComments, |
| LintFixInfo.sortChildPropertiesLast, |
| // LintFixInfo.typeAnnotatePublicApis, |
| LintFixInfo.typeInitFormals, |
| LintFixInfo.unawaitedFutures, |
| LintFixInfo.unnecessaryBraceInStringInterps, |
| LintFixInfo.unnecessaryConst, |
| LintFixInfo.unnecessaryLambdas, |
| LintFixInfo.unnecessaryNew, |
| LintFixInfo.unnecessaryOverrides, |
| LintFixInfo.unnecessaryThis, |
| LintFixInfo.useFunctionTypeSyntaxForParameters, |
| LintFixInfo.useRethrowWhenPossible, |
| ]; |
| |
| /// [DartFixInfo] represents a fix that can be applied by [EditDartFix]. |
| class DartFixInfo { |
| /// The key provided on the command line via the `--fix` option to refer to |
| /// this fix. |
| final String key; |
| |
| /// A description of the fix, printed by the `--help` option. |
| final String description; |
| |
| /// A flag indicating whether this fix is related to the lints in the pedantic |
| /// lint set. |
| final bool isPedantic; |
| |
| final void Function(DartFixRegistrar registrar, DartFixListener listener, |
| EditDartfixParams params) _setup; |
| |
| const DartFixInfo( |
| this.key, |
| this.description, |
| this._setup, { |
| this.isPedantic = false, |
| }); |
| |
| /// Return a newly created fix generated from this fix info. |
| DartFix asDartFix() => DartFix(key, description: description); |
| |
| /// Register this fix with the [registrar] and report progress to the |
| /// [listener]. |
| void setup(DartFixRegistrar registrar, DartFixListener listener, |
| EditDartfixParams params) { |
| _setup(registrar, listener, params); |
| } |
| } |
| |
| /// Information about a fix that applies to a lint. |
| class LintFixInfo extends DartFixInfo { |
| // TODO(brianwilkerson) Add fixes in FixProcessor for the following pedantic |
| // lints: |
| // avoid_null_checks_in_equality_operators |
| // avoid_shadowing_type_parameters |
| // avoid_types_as_parameter_names |
| // camel_case_extensions |
| // library_names |
| // prefer_contains |
| // recursive_getters |
| // unrelated_type_equality_checks |
| // valid_regexps |
| |
| static final alwaysDeclareReturnTypes = LintFixInfo( |
| 'always_declare_return_types', |
| DartFixKind.ADD_RETURN_TYPE, |
| 'Add a return type where possible.', |
| isPedantic: true, |
| ); |
| |
| static final alwaysRequireNonNullNamedParameters = LintFixInfo( |
| 'always_require_non_null_named_parameters', |
| DartFixKind.ADD_REQUIRED, |
| 'Add an @required annotation.', |
| isPedantic: true, |
| ); |
| |
| static final alwaysSpecifyTypes = LintFixInfo( |
| 'always_specify_types', |
| DartFixKind.ADD_TYPE_ANNOTATION, |
| 'Add a type annotation.', |
| ); |
| |
| static final annotateOverrides = LintFixInfo( |
| 'annotate_overrides', |
| DartFixKind.ADD_OVERRIDE, |
| 'Add an @override annotation.', |
| isPedantic: true, |
| ); |
| |
| static final avoidAnnotatingWithDynamic = LintFixInfo( |
| 'avoid_annotating_with_dynamic', |
| DartFixKind.REMOVE_TYPE_ANNOTATION, |
| 'Remove the type annotation.', |
| ); |
| |
| static final avoidEmptyElse = LintFixInfo( |
| 'avoid_empty_else', |
| DartFixKind.REMOVE_EMPTY_ELSE, |
| 'Remove the empty else.', |
| isPedantic: true, |
| ); |
| |
| static final avoidInitToNull = LintFixInfo( |
| 'avoid_init_to_null', |
| DartFixKind.REMOVE_INITIALIZER, |
| 'Remove the initializer.', |
| isPedantic: true, |
| ); |
| |
| static final avoidRedundantArgumentValues = LintFixInfo( |
| 'avoid_redundant_argument_values', |
| DartFixKind.REMOVE_ARGUMENT, |
| 'Remove the redundant argument.', |
| ); |
| |
| static final avoidRelativeLibImports = LintFixInfo( |
| 'avoid_relative_lib_imports', |
| DartFixKind.CONVERT_TO_PACKAGE_IMPORT, |
| 'Convert the import to a package: import.', |
| isPedantic: true, |
| ); |
| |
| static final avoidReturnTypesOnSetters = LintFixInfo( |
| 'avoid_return_types_on_setters', |
| DartFixKind.REMOVE_TYPE_ANNOTATION, |
| 'Remove the return type.', |
| isPedantic: true, |
| ); |
| |
| static final avoidTypesOnClosureParameters = LintFixInfo( |
| 'avoid_types_on_closure_parameters', |
| // Also sometimes fixed by DartFixKind.REPLACE_WITH_IDENTIFIER |
| DartFixKind.REMOVE_TYPE_ANNOTATION, |
| 'Remove the type annotation.', |
| ); |
| |
| static final awaitOnlyFutures = LintFixInfo( |
| 'await_only_futures', |
| DartFixKind.REMOVE_AWAIT, |
| "Remove the 'await'.", |
| ); |
| |
| static final curlyBracesInFlowControlStructures = LintFixInfo( |
| 'curly_braces_in_flow_control_structures', |
| DartFixKind.ADD_CURLY_BRACES, |
| 'Add curly braces.', |
| isPedantic: true, |
| ); |
| |
| static final diagnosticDescribeAllProperties = LintFixInfo( |
| 'diagnostic_describe_all_properties', |
| DartFixKind.ADD_DIAGNOSTIC_PROPERTY_REFERENCE, |
| 'Add a debug reference to this property.', |
| ); |
| |
| static final emptyCatches = LintFixInfo( |
| 'empty_catches', |
| DartFixKind.REMOVE_EMPTY_CATCH, |
| 'Remove the empty catch clause.', |
| isPedantic: true, |
| ); |
| |
| static final emptyConstructorBodies = LintFixInfo( |
| 'empty_constructor_bodies', |
| DartFixKind.REMOVE_EMPTY_CONSTRUCTOR_BODY, |
| 'Remove the empoty catch clause.', |
| isPedantic: true, |
| ); |
| |
| static final emptyStatements = LintFixInfo( |
| 'empty_statements', |
| // Also sometimes fixed by DartFixKind.REPLACE_WITH_BRACKETS |
| DartFixKind.REMOVE_EMPTY_STATEMENT, |
| 'Remove the empty statement.', |
| ); |
| |
| static final hashAndEquals = LintFixInfo( |
| 'hash_and_equals', |
| DartFixKind.CREATE_METHOD, |
| 'Create the missing method.', |
| ); |
| |
| static final noDuplicateCaseValues = LintFixInfo( |
| 'no_duplicate_case_values', |
| DartFixKind.REMOVE_DUPLICATE_CASE, |
| 'Remove the duplicate case clause.', |
| isPedantic: true, |
| ); |
| |
| static final nonConstantIdentifierNames = LintFixInfo( |
| 'non_constant_identifier_names', |
| DartFixKind.RENAME_TO_CAMEL_CASE, |
| 'Change the name to be camelCase.', |
| ); |
| |
| static final nullClosures = LintFixInfo( |
| 'null_closures', |
| DartFixKind.REPLACE_NULL_WITH_CLOSURE, |
| 'Convert nulls to closures that return null where expected.', |
| isPedantic: true, |
| ); |
| |
| static final omitLocalVariableTypes = LintFixInfo( |
| 'omit_local_variable_types', |
| DartFixKind.REPLACE_WITH_VAR, |
| "Replace the type annotation with 'var'", |
| isPedantic: true, |
| ); |
| |
| static final preferAdjacentStringConcatenation = LintFixInfo( |
| 'prefer_adjacent_string_concatenation', |
| DartFixKind.REMOVE_OPERATOR, |
| "Remove the '+' operator.", |
| isPedantic: true, |
| ); |
| |
| static final preferCollectionLiterals = LintFixInfo( |
| 'prefer_collection_literals', |
| DartFixKind.CONVERT_TO_LIST_LITERAL, |
| 'Replace with a collection literal.', |
| isPedantic: true, |
| ); |
| |
| static final preferConditionalAssignment = LintFixInfo( |
| 'prefer_conditional_assignment', |
| DartFixKind.REPLACE_WITH_CONDITIONAL_ASSIGNMENT, |
| 'Replace with a conditional assignment.', |
| isPedantic: true, |
| ); |
| |
| static final preferConstConstructors = LintFixInfo( |
| 'prefer_const_constructors', |
| DartFixKind.ADD_CONST, |
| 'Make the instantiation const.', |
| ); |
| |
| static final preferConstConstructorsInImmutables = LintFixInfo( |
| 'prefer_const_constructors_in_immutables', |
| DartFixKind.ADD_CONST, |
| 'Make the constructor const.', |
| ); |
| |
| static final preferConstDeclarations = LintFixInfo( |
| 'prefer_const_declarations', |
| DartFixKind.REPLACE_FINAL_WITH_CONST, |
| 'Make the declaration const.', |
| ); |
| |
| static final preferContains = LintFixInfo( |
| 'prefer_contains', |
| DartFixKind.CONVERT_TO_CONTAINS, |
| "Convert to using 'contains'.", |
| isPedantic: true, |
| ); |
| |
| static final preferEqualForDefaultValues = LintFixInfo( |
| 'prefer_equal_for_default_values', |
| DartFixKind.REPLACE_COLON_WITH_EQUALS, |
| 'Convert declarations to use = to separate a named parameter from its default value.', |
| isPedantic: true, |
| ); |
| |
| static final preferFinalFields = LintFixInfo( |
| 'prefer_final_fields', |
| DartFixKind.MAKE_FINAL, |
| 'Make the field final.', |
| isPedantic: true, |
| ); |
| |
| static final preferFinalLocals = LintFixInfo( |
| 'prefer_final_locals', |
| DartFixKind.MAKE_FINAL, |
| "Make the variable 'final'.", |
| ); |
| |
| static final preferForElementsToMapFromIterable = LintFixInfo( |
| 'prefer_for_elements_to_map_fromIterable', |
| DartFixKind.CONVERT_TO_FOR_ELEMENT, |
| 'Convert to a for element.', |
| isPedantic: true, |
| ); |
| |
| static final preferGenericFunctionTypeAliases = LintFixInfo( |
| 'prefer_generic_function_type_aliases', |
| DartFixKind.CONVERT_TO_GENERIC_FUNCTION_SYNTAX, |
| "Convert into 'Function' syntax", |
| isPedantic: true, |
| ); |
| |
| static final preferIfElementsToConditionalExpressions = LintFixInfo( |
| 'prefer_if_elements_to_conditional_expressions', |
| DartFixKind.CONVERT_TO_IF_ELEMENT, |
| "Convert to an 'if' element."); |
| |
| static final preferIfNullOperators = LintFixInfo( |
| 'prefer_if_null_operators', |
| DartFixKind.CONVERT_TO_IF_NULL, |
| "Convert to use '??'.", |
| isPedantic: true, |
| ); |
| |
| static final preferInlinedAdds = LintFixInfo( |
| 'prefer_inlined_adds', |
| DartFixKind.INLINE_INVOCATION, |
| 'Inline the invocation.', |
| ); |
| |
| static final preferIntLiterals = LintFixInfo( |
| 'prefer_int_literals', |
| DartFixKind.CONVERT_TO_INT_LITERAL, |
| 'Convert to an int literal', |
| ); |
| |
| static final preferIsEmpty = LintFixInfo( |
| 'prefer_is_empty', |
| DartFixKind.REPLACE_WITH_IS_EMPTY, |
| "Convert to using 'isEmpty' when checking if a collection or iterable is empty.", |
| isPedantic: true, |
| ); |
| |
| static final preferIsNotEmpty = LintFixInfo( |
| 'prefer_is_not_empty', |
| DartFixKind.REPLACE_WITH_IS_NOT_EMPTY, |
| "Convert to using 'isNotEmpty' when checking if a collection or iterable is not empty.", |
| isPedantic: true, |
| ); |
| |
| static final preferIterableWhereType = LintFixInfo( |
| 'prefer_iterable_whereType', |
| DartFixKind.CONVERT_TO_WHERE_TYPE, |
| 'Add a return type where possible.', |
| isPedantic: true, |
| ); |
| |
| static final preferNullAwareOperators = LintFixInfo( |
| 'prefer_null_aware_operators', |
| DartFixKind.CONVERT_TO_NULL_AWARE, |
| "Convert to use '?.'.", |
| ); |
| |
| static final preferRelativeImports = LintFixInfo( |
| 'prefer_relative_imports', |
| DartFixKind.CONVERT_TO_RELATIVE_IMPORT, |
| 'Convert to a relative import.', |
| ); |
| |
| static final preferSingleQuotes = LintFixInfo( |
| 'prefer_single_quotes', |
| DartFixKind.CONVERT_TO_SINGLE_QUOTED_STRING, |
| 'Convert strings using a double quote to use a single quote.', |
| isPedantic: true, |
| ); |
| |
| static final preferSpreadCollections = LintFixInfo( |
| 'prefer_spread_collections', |
| // TODO(brianwilkerson) There are two possible fixes here, but not under |
| // user control. |
| DartFixKind.CONVERT_TO_SPREAD, |
| 'Convert to a spread operator.', |
| |
| isPedantic: true, |
| ); |
| |
| static final slashForDocComments = LintFixInfo( |
| 'slash_for_doc_comments', |
| DartFixKind.CONVERT_TO_LINE_COMMENT, |
| 'Convert to a line comment.', |
| isPedantic: true, |
| ); |
| |
| static final sortChildPropertiesLast = LintFixInfo( |
| 'sort_child_properties_last', |
| DartFixKind.SORT_CHILD_PROPERTY_LAST, |
| "Move the 'child' argument to the end of the argument list.", |
| ); |
| |
| static final typeAnnotatePublicApis = LintFixInfo( |
| 'type_annotate_public_apis', |
| DartFixKind.ADD_TYPE_ANNOTATION, |
| 'Add a type annotation.', |
| ); |
| |
| static final typeInitFormals = LintFixInfo( |
| 'type_init_formals', |
| DartFixKind.REMOVE_TYPE_ANNOTATION, |
| 'Remove the type annotation.', |
| isPedantic: true, |
| ); |
| |
| static final unawaitedFutures = LintFixInfo( |
| 'unawaited_futures', |
| DartFixKind.ADD_AWAIT, |
| 'Add await.', |
| isPedantic: true, |
| ); |
| |
| static final unnecessaryBraceInStringInterps = LintFixInfo( |
| 'unnecessary_brace_in_string_interps', |
| DartFixKind.REMOVE_INTERPOLATION_BRACES, |
| 'Remove the unnecessary interpolation braces.', |
| ); |
| |
| static final unnecessaryConst = LintFixInfo( |
| 'unnecessary_const', |
| DartFixKind.REMOVE_UNNECESSARY_CONST, |
| "Remove unnecessary 'const'' keywords.", |
| isPedantic: true, |
| ); |
| |
| static final unnecessaryLambdas = LintFixInfo( |
| 'unnecessary_lambdas', |
| DartFixKind.REPLACE_WITH_TEAR_OFF, |
| 'Replace the function literal with a tear-off.', |
| ); |
| |
| static final unnecessaryNew = LintFixInfo( |
| 'unnecessary_new', |
| DartFixKind.REMOVE_UNNECESSARY_NEW, |
| "Remove unnecessary 'new' keywords.", |
| isPedantic: true, |
| ); |
| |
| static final unnecessaryNullInIfNullOperators = LintFixInfo( |
| 'unnecessary_null_in_if_null_operators', |
| DartFixKind.REMOVE_IF_NULL_OPERATOR, |
| "Remove the '??' operator.", |
| isPedantic: true, |
| ); |
| |
| static final unnecessaryOverrides = LintFixInfo( |
| 'unnecessary_overrides', |
| DartFixKind.REMOVE_METHOD_DECLARATION, |
| 'Remove the unnecessary override.', |
| ); |
| |
| static final unnecessaryThis = LintFixInfo( |
| 'unnecessary_this', |
| DartFixKind.REMOVE_THIS_EXPRESSION, |
| 'Remove this.', |
| isPedantic: true, |
| ); |
| |
| static final useFunctionTypeSyntaxForParameters = LintFixInfo( |
| 'use_function_type_syntax_for_parameters', |
| DartFixKind.CONVERT_TO_GENERIC_FUNCTION_SYNTAX, |
| "Convert into 'Function' syntax", |
| isPedantic: true, |
| ); |
| |
| static final useRethrowWhenPossible = LintFixInfo( |
| 'use_rethrow_when_possible', |
| DartFixKind.USE_RETHROW, |
| 'Replace with rethrow.', |
| isPedantic: true, |
| ); |
| |
| /// The name of the lint to be fixed. |
| final String lintName; |
| |
| /// The kind of fix to be applied. |
| final FixKind fixKind; |
| |
| /// Initialize a newly created set of fix information. |
| LintFixInfo( |
| this.lintName, |
| this.fixKind, |
| String description, { |
| bool isPedantic = false, |
| }) : super(lintName, description, (_, __, ___) {}, isPedantic: isPedantic); |
| |
| @override |
| void setup(DartFixRegistrar registrar, DartFixListener listener, |
| EditDartfixParams params) { |
| registrar.registerLintTask( |
| Registry.ruleRegistry[lintName]!, FixLintTask(listener)); |
| } |
| } |