diff --git a/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart b/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart index 7e61a0e715b..752dd51a8cd 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/rename_to_camel_case.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analysis_server/src/services/correction/util.dart'; @@ -16,7 +14,7 @@ import 'package:analyzer_plugin/utilities/range_factory.dart'; class RenameToCamelCase extends CorrectionProducer { /// The camel-case version of the name. - String _newName; + String _newName = ''; @override List get fixArguments => [_newName]; @@ -29,10 +27,10 @@ class RenameToCamelCase extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - if (node is! SimpleIdentifier) { + var identifier = node; + if (identifier is! SimpleIdentifier) { return; } - SimpleIdentifier identifier = node; // Prepare the new name. var words = identifier.name.split('_'); @@ -42,17 +40,21 @@ class RenameToCamelCase extends CorrectionProducer { _newName = words.first + words.skip(1).map((w) => capitalize(w)).join(); // Find references to the identifier. - List references; + List? references; var element = identifier.staticElement; if (element is LocalVariableElement) { - AstNode root = node.thisOrAncestorOfType(); - references = findLocalElementReferences(root, element); + var root = node.thisOrAncestorOfType(); + if (root != null) { + references = findLocalElementReferences(root, element); + } } else if (element is ParameterElement) { if (!element.isNamed) { var root = node.thisOrAncestorMatching((node) => node.parent is ClassOrMixinDeclaration || node.parent is CompilationUnit); - references = findLocalElementReferences(root, element); + if (root != null) { + references = findLocalElementReferences(root, element); + } } } if (references == null) { @@ -60,8 +62,9 @@ class RenameToCamelCase extends CorrectionProducer { } // Compute the change. + var references_final = references; await builder.addDartFileEdit(file, (builder) { - for (var reference in references) { + for (var reference in references_final) { builder.addSimpleReplacement(range.node(reference), _newName); } }); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_boolean_with_bool.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_boolean_with_bool.dart index 5039e9b73fa..c35c13f8b67 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_boolean_with_bool.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_boolean_with_bool.dart @@ -2,10 +2,9 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -19,8 +18,13 @@ class ReplaceBooleanWithBool extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { + final analysisError = diagnostic; + if (analysisError is! AnalysisError) { + return; + } + await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.error(diagnostic), 'bool'); + builder.addSimpleReplacement(range.error(analysisError), 'bool'); }); } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_cascade_with_dot.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_cascade_with_dot.dart index 00d41c36b03..3a7b269c1ea 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_cascade_with_dot.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_cascade_with_dot.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -31,29 +29,35 @@ class ReplaceCascadeWithDot extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - var node = this.node; - if (node is CascadeExpression) { - var sections = node.cascadeSections; - if (sections.length == 1) { - await _replaceFor(builder, sections[0]); - } + final cascadeExpression = node; + if (cascadeExpression is! CascadeExpression) { + return; + } + + var sections = cascadeExpression.cascadeSections; + if (sections.length == 1) { + await _replaceFor(builder, sections[0]); } } - Future _replaceFor(ChangeBuilder builder, Expression section) async { + Future _replaceFor(ChangeBuilder builder, Expression? section) async { if (section is AssignmentExpression) { return _replaceFor(builder, section.leftHandSide); } if (section is IndexExpression) { - if (section.period != null) { - return _replaceToken(builder, section.period, _indexReplacement); + var period = section.period; + if (period != null) { + return _replaceToken(builder, period, _indexReplacement); } return _replaceFor(builder, section.target); } if (section is MethodInvocation) { - return _replaceToken(builder, section.operator, _propertyReplacement); + var operator = section.operator; + if (operator != null) { + return _replaceToken(builder, operator, _propertyReplacement); + } } if (section is PropertyAccess) { diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_colon_with_equals.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_colon_with_equals.dart index 4f9b235753a..f6adef45ff2 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_colon_with_equals.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_colon_with_equals.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,12 +18,19 @@ class ReplaceColonWithEquals extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - if (node is DefaultFormalParameter) { - await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement( - range.token((node as DefaultFormalParameter).separator), ' ='); - }); + final node = this.node; + if (node is! DefaultFormalParameter) { + return; } + + var separator = node.separator; + if (separator == null) { + return; + } + + await builder.addDartFileEdit(file, (builder) { + builder.addSimpleReplacement(range.token(separator), ' ='); + }); } /// Return an instance of this class. Used as a tear-off in `FixProcessor`. diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart index adb16a848e7..7dee07a4f6b 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; @@ -18,58 +16,98 @@ class ReplaceConditionalWithIfElse extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - ConditionalExpression conditional; // may be on Statement with Conditional var statement = node.thisOrAncestorOfType(); if (statement == null) { return; } - // variable declaration - var inVariable = false; - if (statement is VariableDeclarationStatement) { - var variableStatement = statement; - for (var variable in variableStatement.variables.variables) { - if (variable.initializer is ConditionalExpression) { - conditional = variable.initializer as ConditionalExpression; - inVariable = true; - break; - } - } - } - // assignment - var inAssignment = false; - if (statement is ExpressionStatement) { - var exprStmt = statement; - if (exprStmt.expression is AssignmentExpression) { - var assignment = exprStmt.expression as AssignmentExpression; - if (assignment.operator.type == TokenType.EQ && - assignment.rightHandSide is ConditionalExpression) { - conditional = assignment.rightHandSide as ConditionalExpression; - inAssignment = true; - } - } - } - // return - var inReturn = false; - if (statement is ReturnStatement) { - var returnStatement = statement; - if (returnStatement.expression is ConditionalExpression) { - conditional = returnStatement.expression as ConditionalExpression; - inReturn = true; - } - } - // prepare environment - var indent = utils.getIndent(1); - var prefix = utils.getNodePrefix(statement); - if (inVariable || inAssignment || inReturn) { + // Type v = conditional; + if (statement is VariableDeclarationStatement) { + return _variableDeclarationStatement(builder, statement); + } + + // v = conditional; + if (statement is ExpressionStatement) { + var expression = statement.expression; + if (expression is AssignmentExpression) { + return _assignmentExpression(builder, statement, expression); + } + } + + // return conditional; + if (statement is ReturnStatement) { + return _returnStatement(builder, statement); + } + } + + Future _assignmentExpression( + ChangeBuilder builder, + ExpressionStatement statement, + AssignmentExpression assignment, + ) async { + var conditional = assignment.rightHandSide; + if (assignment.operator.type == TokenType.EQ && + conditional is ConditionalExpression) { + var indent = utils.getIndent(1); + var prefix = utils.getNodePrefix(statement); + await builder.addDartFileEdit(file, (builder) { - // Type v = Conditional; - if (inVariable) { + var leftSide = assignment.leftHandSide; + var conditionSrc = utils.getNodeText(conditional.condition); + var thenSrc = utils.getNodeText(conditional.thenExpression); + var elseSrc = utils.getNodeText(conditional.elseExpression); + var name = utils.getNodeText(leftSide); + var src = ''; + src += 'if ($conditionSrc) {' + eol; + src += prefix + indent + '$name = $thenSrc;' + eol; + src += prefix + '} else {' + eol; + src += prefix + indent + '$name = $elseSrc;' + eol; + src += prefix + '}'; + builder.addSimpleReplacement(range.node(statement), src); + }); + } + } + + Future _returnStatement( + ChangeBuilder builder, + ReturnStatement statement, + ) async { + var conditional = statement.expression; + if (conditional is ConditionalExpression) { + var indent = utils.getIndent(1); + var prefix = utils.getNodePrefix(statement); + + await builder.addDartFileEdit(file, (builder) { + var conditionSrc = utils.getNodeText(conditional.condition); + var thenSrc = utils.getNodeText(conditional.thenExpression); + var elseSrc = utils.getNodeText(conditional.elseExpression); + var src = ''; + src += 'if ($conditionSrc) {' + eol; + src += prefix + indent + 'return $thenSrc;' + eol; + src += prefix + '} else {' + eol; + src += prefix + indent + 'return $elseSrc;' + eol; + src += prefix + '}'; + builder.addSimpleReplacement(range.node(statement), src); + }); + } + } + + Future _variableDeclarationStatement( + ChangeBuilder builder, + VariableDeclarationStatement statement, + ) async { + for (var variable in statement.variables.variables) { + var conditional = variable.initializer; + if (conditional is ConditionalExpression) { + var indent = utils.getIndent(1); + var prefix = utils.getNodePrefix(statement); + + await builder.addDartFileEdit(file, (builder) { var variable = conditional.parent as VariableDeclaration; var variableList = variable.parent as VariableDeclarationList; if (variableList.type == null) { - var type = variable.declaredElement.type; + var type = variable.declaredElement!.type; var keyword = variableList.keyword; if (keyword != null && keyword.keyword == Keyword.VAR) { builder.addReplacement(range.token(keyword), (builder) { @@ -94,37 +132,8 @@ class ReplaceConditionalWithIfElse extends CorrectionProducer { src += prefix + indent + '$name = $elseSrc;' + eol; src += prefix + '}'; builder.addSimpleReplacement(range.endLength(statement, 0), src); - } - // v = Conditional; - if (inAssignment) { - var assignment = conditional.parent as AssignmentExpression; - var leftSide = assignment.leftHandSide; - var conditionSrc = utils.getNodeText(conditional.condition); - var thenSrc = utils.getNodeText(conditional.thenExpression); - var elseSrc = utils.getNodeText(conditional.elseExpression); - var name = utils.getNodeText(leftSide); - var src = ''; - src += 'if ($conditionSrc) {' + eol; - src += prefix + indent + '$name = $thenSrc;' + eol; - src += prefix + '} else {' + eol; - src += prefix + indent + '$name = $elseSrc;' + eol; - src += prefix + '}'; - builder.addSimpleReplacement(range.node(statement), src); - } - // return Conditional; - if (inReturn) { - var conditionSrc = utils.getNodeText(conditional.condition); - var thenSrc = utils.getNodeText(conditional.thenExpression); - var elseSrc = utils.getNodeText(conditional.elseExpression); - var src = ''; - src += 'if ($conditionSrc) {' + eol; - src += prefix + indent + 'return $thenSrc;' + eol; - src += prefix + '} else {' + eol; - src += prefix + indent + 'return $elseSrc;' + eol; - src += prefix + '}'; - builder.addSimpleReplacement(range.node(statement), src); - } - }); + }); + } } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_const.dart index 3a77351f735..76b2a8e9aa9 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_const.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_const.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,11 +18,14 @@ class ReplaceFinalWithConst extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { + final node = this.node; if (node is VariableDeclarationList) { - await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement( - range.token((node as VariableDeclarationList).keyword), 'const'); - }); + var keyword = node.keyword; + if (keyword != null) { + await builder.addDartFileEdit(file, (builder) { + builder.addSimpleReplacement(range.token(keyword), 'const'); + }); + } } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_var.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_var.dart index 58a4a763b94..9371a8d3002 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_var.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_final_with_var.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,11 +18,12 @@ class ReplaceFinalWithVar extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - var target = node; - if (target is VariableDeclarationList) { - if (target.type == null) { + final node = this.node; + if (node is VariableDeclarationList) { + var keyword = node.keyword; + if (keyword != null && node.type == null) { await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.token(target.keyword), 'var'); + builder.addSimpleReplacement(range.token(keyword), 'var'); }); } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart index 92249217a82..85e95996ce9 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_new_with_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_new_with_const.dart index 9a9cd772c22..e8db9a39140 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_new_with_const.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_new_with_const.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,7 +18,7 @@ class ReplaceNewWithConst extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - var node = this.node; + AstNode? node = this.node; if (node is ConstructorName) { node = node.parent; } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart index 39aabc28bdc..9da2766f51c 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -22,13 +20,14 @@ class ReplaceNullWithClosure extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - AstNode nodeToFix; + AstNode? nodeToFix; var parameters = const []; + + final coveredNode = this.coveredNode; if (coveredNode is NamedExpression) { - NamedExpression namedExpression = coveredNode; - var expression = namedExpression.expression; + var expression = coveredNode.expression; if (expression is NullLiteral) { - var element = namedExpression.element; + var element = coveredNode.element; if (element is ParameterElement) { var type = element.type; if (type is FunctionType) { @@ -41,14 +40,17 @@ class ReplaceNullWithClosure extends CorrectionProducer { nodeToFix = coveredNode; } - if (nodeToFix != null) { - await builder.addDartFileEdit(file, (builder) { - builder.addReplacement(range.node(nodeToFix), (builder) { - builder.writeParameters(parameters); - builder.write(' => null'); - }); - }); + if (nodeToFix == null) { + return; } + + final nodeToFix_final = nodeToFix; + await builder.addDartFileEdit(file, (builder) { + builder.addReplacement(range.node(nodeToFix_final), (builder) { + builder.writeParameters(parameters); + builder.write(' => null'); + }); + }); } /// Return an instance of this class. Used as a tear-off in `FixProcessor`. diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart index 3d0000a5c3e..c19cf4a0042 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_return_type_future.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -18,7 +16,10 @@ class ReplaceReturnTypeFuture extends CorrectionProducer { Future compute(ChangeBuilder builder) async { // prepare the existing type var typeName = node.thisOrAncestorOfType(); - var typeProvider = this.typeProvider; + if (typeName == null) { + return; + } + await builder.addDartFileEdit(file, (builder) { builder.replaceTypeWithFuture(typeName, typeProvider); }); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_var_with_dynamic.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_var_with_dynamic.dart index 3da975fd5ab..1991391c02a 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_var_with_dynamic.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_var_with_dynamic.dart @@ -2,10 +2,9 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analyzer/error/error.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; @@ -16,9 +15,12 @@ class ReplaceVarWithDynamic extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.error(diagnostic), 'dynamic'); - }); + final diagnostic = this.diagnostic; + if (diagnostic is AnalysisError) { + await builder.addDartFileEdit(file, (builder) { + builder.addSimpleReplacement(range.error(diagnostic), 'dynamic'); + }); + } } /// Return an instance of this class. Used as a tear-off in `FixProcessor`. diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_brackets.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_brackets.dart index 83f4cafb770..eb4fc02a015 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_brackets.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_brackets.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_conditional_assignment.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_conditional_assignment.dart index e7dfbd2eda4..9d69d50d479 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_conditional_assignment.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_conditional_assignment.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -21,20 +19,14 @@ class ReplaceWithConditionalAssignment extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - IfStatement ifStatement = + var node = this.node; + var ifStatement = node is IfStatement ? node : node.thisOrAncestorOfType(); if (ifStatement == null) { return; } - var thenStatement = ifStatement.thenStatement; - Statement uniqueStatement(Statement statement) { - if (statement is Block) { - return uniqueStatement(statement.statements.first); - } - return statement; - } - thenStatement = uniqueStatement(thenStatement); + var thenStatement = _uniqueStatement(ifStatement.thenStatement); if (thenStatement is ExpressionStatement) { final expression = thenStatement.expression.unParenthesized; if (expression is AssignmentExpression) { @@ -53,4 +45,11 @@ class ReplaceWithConditionalAssignment extends CorrectionProducer { /// Return an instance of this class. Used as a tear-off in `FixProcessor`. static ReplaceWithConditionalAssignment newInstance() => ReplaceWithConditionalAssignment(); + + static Statement _uniqueStatement(Statement statement) { + if (statement is Block) { + return _uniqueStatement(statement.statements.first); + } + return statement; + } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart index d0c722960da..ff9e2eb23d8 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -13,7 +11,7 @@ import 'package:analyzer_plugin/utilities/range_factory.dart'; class ReplaceWithEightDigitHex extends CorrectionProducer { /// The replacement text, used as an argument to the fix message. - String _replacement; + String _replacement = ''; @override List get fixArguments => [_replacement]; @@ -33,6 +31,9 @@ class ReplaceWithEightDigitHex extends CorrectionProducer { return; } var value = (node as IntegerLiteral).value; + if (value == null) { + return; + } _replacement = '0x' + value.toRadixString(16).padLeft(8, '0'); // // Build the edit. diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_extension_name.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_extension_name.dart index ed7fa480227..6bac2bdf750 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_extension_name.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_extension_name.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -12,7 +10,7 @@ import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; class ReplaceWithExtensionName extends CorrectionProducer { - String _extensionName; + String _extensionName = ''; @override List get fixArguments => [_extensionName]; @@ -35,7 +33,7 @@ class ReplaceWithExtensionName extends CorrectionProducer { } } - AstNode _getTarget(AstNode invocation) { + AstNode? _getTarget(AstNode? invocation) { if (invocation is MethodInvocation && node == invocation.methodName) { return invocation.target; } else if (invocation is PropertyAccess && diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_filled.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_filled.dart index fc40853fb08..860e6207bb6 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_filled.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_filled.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_identifier.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_identifier.dart index 33d0b66ec34..9b308179c6b 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_identifier.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_identifier.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart index 77aa0272ed2..639f53fbb72 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart @@ -2,16 +2,14 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/token.dart'; +import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; -import 'package:meta/meta.dart'; class ReplaceWithInterpolation extends CorrectionProducer { @override @@ -22,9 +20,9 @@ class ReplaceWithInterpolation extends CorrectionProducer { // // Validate the fix. // - BinaryExpression binary; - var candidate = node; - while (_isStringConcatenation(candidate)) { + BinaryExpression? binary; + AstNode? candidate = node; + while (candidate is BinaryExpression && _isStringConcatenation(candidate)) { binary = candidate; candidate = candidate.parent; } @@ -43,8 +41,9 @@ class ReplaceWithInterpolation extends CorrectionProducer { // // Build the edit. // + final binary_final = binary; await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.node(binary), interpolation); + builder.addSimpleReplacement(range.node(binary_final), interpolation); }); } @@ -82,9 +81,11 @@ class ReplaceWithInterpolation extends CorrectionProducer { return leftStyle; } return leftStyle == rightStyle ? leftStyle : _StringStyle.invalid; - } else if (expression is MethodInvocation && - expression.methodName.name == 'toString') { - return _extractComponentsInto(expression.target, components); + } else if (expression is MethodInvocation) { + var target = expression.target; + if (target != null && expression.methodName.name == 'toString') { + return _extractComponentsInto(target, components); + } } else if (expression is ParenthesizedExpression) { return _extractComponentsInto(expression.expression, components); } @@ -95,8 +96,8 @@ class ReplaceWithInterpolation extends CorrectionProducer { bool _isStringConcatenation(AstNode node) => node is BinaryExpression && node.operator.type == TokenType.PLUS && - node.leftOperand.staticType.isDartCoreString && - node.rightOperand.staticType.isDartCoreString; + node.leftOperand.typeOrThrow.isDartCoreString && + node.rightOperand.typeOrThrow.isDartCoreString; String _mergeComponents(_StringStyle style, List components) { var quotes = style.quotes; @@ -161,10 +162,11 @@ class _StringStyle { final int state; - factory _StringStyle( - {@required bool multiline, - @required bool raw, - @required bool singleQuoted}) { + factory _StringStyle({ + required bool multiline, + required bool raw, + required bool singleQuoted, + }) { return _StringStyle._((multiline ? multilineBit : 0) + (raw ? rawBit : 0) + (singleQuoted ? singleQuotedBit : 0)); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_is_empty.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_is_empty.dart index 9c02fdad4e9..96b25d6aa8f 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_is_empty.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_is_empty.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -14,106 +12,28 @@ import 'package:analyzer_plugin/utilities/range_factory.dart'; class ReplaceWithIsEmpty extends CorrectionProducer { @override - FixKind fixKind; + FixKind fixKind = DartFixKind.REPLACE_WITH_IS_EMPTY; @override - FixKind multiFixKind; + FixKind multiFixKind = DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI; @override Future compute(ChangeBuilder builder) async { - /// Return the value of an integer literal or prefix expression with a - /// minus and then an integer literal. For anything else, returns `null`. - int getIntValue(Expression expressions) { - // Copied from package:linter/src/rules/prefer_is_empty.dart. - if (expressions is IntegerLiteral) { - return expressions.value; - } else if (expressions is PrefixExpression) { - var operand = expressions.operand; - if (expressions.operator.type == TokenType.MINUS && - operand is IntegerLiteral) { - return -operand.value; - } - } - return null; - } - - /// Return the expression producing the object on which `length` is being - /// invoked, or `null` if there is no such expression. - Expression getLengthTarget(Expression expression) { - if (expression is PropertyAccess && - expression.propertyName.name == 'length') { - return expression.target; - } else if (expression is PrefixedIdentifier && - expression.identifier.name == 'length') { - return expression.prefix; - } - return null; - } - var binary = node.thisOrAncestorOfType(); - var operator = binary.operator.type; - String getter; - Expression lengthTarget; - var rightValue = getIntValue(binary.rightOperand); - if (rightValue != null) { - lengthTarget = getLengthTarget(binary.leftOperand); - if (rightValue == 0) { - if (operator == TokenType.EQ_EQ || operator == TokenType.LT_EQ) { - getter = 'isEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI; - } else if (operator == TokenType.GT || operator == TokenType.BANG_EQ) { - getter = 'isNotEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY_MULTI; - } - } else if (rightValue == 1) { - // 'length >= 1' is same as 'isNotEmpty', - // and 'length < 1' is same as 'isEmpty' - if (operator == TokenType.GT_EQ) { - getter = 'isNotEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY_MULTI; - } else if (operator == TokenType.LT) { - getter = 'isEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI; - } - } - } else { - var leftValue = getIntValue(binary.leftOperand); - if (leftValue != null) { - lengthTarget = getLengthTarget(binary.rightOperand); - if (leftValue == 0) { - if (operator == TokenType.EQ_EQ || operator == TokenType.GT_EQ) { - getter = 'isEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI; - } else if (operator == TokenType.LT || - operator == TokenType.BANG_EQ) { - getter = 'isNotEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY_MULTI; - } - } else if (leftValue == 1) { - // '1 <= length' is same as 'isNotEmpty', - // and '1 > length' is same as 'isEmpty' - if (operator == TokenType.LT_EQ) { - getter = 'isNotEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_NOT_EMPTY_MULTI; - } else if (operator == TokenType.GT) { - getter = 'isEmpty'; - fixKind = DartFixKind.REPLACE_WITH_IS_EMPTY; - multiFixKind = DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI; - } - } - } - } - if (lengthTarget == null || getter == null || fixKind == null) { + if (binary == null) { return; } - var target = utils.getNodeText(lengthTarget); + + var replacement = _analyzeBinaryExpression(binary); + if (replacement == null) { + return; + } + + fixKind = replacement.fixKind; + multiFixKind = replacement.multiFixKind; + + var target = utils.getNodeText(replacement.lengthTarget); + var getter = replacement.getter; await builder.addDartFileEdit(file, (builder) { builder.addSimpleReplacement(range.node(binary), '$target.$getter'); }); @@ -121,4 +41,117 @@ class ReplaceWithIsEmpty extends CorrectionProducer { /// Return an instance of this class. Used as a tear-off in `FixProcessor`. static ReplaceWithIsEmpty newInstance() => ReplaceWithIsEmpty(); + + static _Replacement? _analyzeBinaryExpression(BinaryExpression binary) { + var operator = binary.operator.type; + var rightValue = _getIntValue(binary.rightOperand); + if (rightValue != null) { + var lengthTarget = _getLengthTarget(binary.leftOperand); + if (lengthTarget == null) { + return null; + } + if (rightValue == 0) { + if (operator == TokenType.EQ_EQ || operator == TokenType.LT_EQ) { + return _Replacement.isEmpty(lengthTarget); + } else if (operator == TokenType.GT || operator == TokenType.BANG_EQ) { + return _Replacement.isNotEmpty(lengthTarget); + } + } else if (rightValue == 1) { + // 'length >= 1' is same as 'isNotEmpty', + // and 'length < 1' is same as 'isEmpty' + if (operator == TokenType.GT_EQ) { + return _Replacement.isNotEmpty(lengthTarget); + } else if (operator == TokenType.LT) { + return _Replacement.isEmpty(lengthTarget); + } + } + } else { + var leftValue = _getIntValue(binary.leftOperand); + if (leftValue != null) { + var lengthTarget = _getLengthTarget(binary.rightOperand); + if (lengthTarget == null) { + return null; + } + if (leftValue == 0) { + if (operator == TokenType.EQ_EQ || operator == TokenType.GT_EQ) { + return _Replacement.isEmpty(lengthTarget); + } else if (operator == TokenType.LT || + operator == TokenType.BANG_EQ) { + return _Replacement.isNotEmpty(lengthTarget); + } + } else if (leftValue == 1) { + // '1 <= length' is same as 'isNotEmpty', + // and '1 > length' is same as 'isEmpty' + if (operator == TokenType.LT_EQ) { + return _Replacement.isNotEmpty(lengthTarget); + } else if (operator == TokenType.GT) { + return _Replacement.isEmpty(lengthTarget); + } + } + } + } + return null; + } + + /// Return the value of an integer literal or prefix expression with a + /// minus and then an integer literal. For anything else, returns `null`. + static int? _getIntValue(Expression expressions) { + // Copied from package:linter/src/rules/prefer_is_empty.dart. + if (expressions is IntegerLiteral) { + return expressions.value; + } else if (expressions is PrefixExpression) { + var operand = expressions.operand; + if (expressions.operator.type == TokenType.MINUS && + operand is IntegerLiteral) { + var value = operand.value; + if (value != null) { + return -value; + } + } + } + return null; + } + + /// Return the expression producing the object on which `length` is being + /// invoked, or `null` if there is no such expression. + static Expression? _getLengthTarget(Expression expression) { + if (expression is PropertyAccess && + expression.propertyName.name == 'length') { + return expression.target; + } else if (expression is PrefixedIdentifier && + expression.identifier.name == 'length') { + return expression.prefix; + } + return null; + } +} + +class _Replacement { + final FixKind fixKind; + final FixKind multiFixKind; + final String getter; + final Expression lengthTarget; + + _Replacement.isEmpty(Expression lengthTarget) + : this._( + fixKind: DartFixKind.REPLACE_WITH_IS_EMPTY, + multiFixKind: DartFixKind.REPLACE_WITH_IS_EMPTY_MULTI, + getter: 'isEmpty', + lengthTarget: lengthTarget, + ); + + _Replacement.isNotEmpty(Expression lengthTarget) + : this._( + fixKind: DartFixKind.REPLACE_WITH_IS_NOT_EMPTY, + multiFixKind: DartFixKind.REPLACE_WITH_IS_NOT_EMPTY_MULTI, + getter: 'isNotEmpty', + lengthTarget: lengthTarget, + ); + + _Replacement._({ + required this.fixKind, + required this.multiFixKind, + required this.getter, + required this.lengthTarget, + }); } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_not_null_aware.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_not_null_aware.dart index 4cc14c005f1..a46a17eb03c 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_not_null_aware.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_not_null_aware.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -14,7 +12,7 @@ import 'package:analyzer_plugin/utilities/range_factory.dart'; class ReplaceWithNotNullAware extends CorrectionProducer { /// The operator that will replace the existing operator. - String _newOperator; + String _newOperator = ''; @override List get fixArguments => [_newOperator]; @@ -26,11 +24,13 @@ class ReplaceWithNotNullAware extends CorrectionProducer { Future compute(ChangeBuilder builder) async { var node = coveredNode; if (node is MethodInvocation) { - _newOperator = - node.operator.type == TokenType.QUESTION_PERIOD ? '.' : '..'; - await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.token(node.operator), _newOperator); - }); + var operator = node.operator; + if (operator != null) { + _newOperator = operator.type == TokenType.QUESTION_PERIOD ? '.' : '..'; + await builder.addDartFileEdit(file, (builder) { + builder.addSimpleReplacement(range.token(operator), _newOperator); + }); + } } else if (node is PropertyAccess) { _newOperator = node.operator.type == TokenType.QUESTION_PERIOD ? '.' : '..'; @@ -38,15 +38,17 @@ class ReplaceWithNotNullAware extends CorrectionProducer { builder.addSimpleReplacement(range.token(node.operator), _newOperator); }); } else if (node is IndexExpression) { - if (node.period != null) { + var period = node.period; + var question = node.question; + if (period != null) { _newOperator = '..'; await builder.addDartFileEdit(file, (builder) { - builder.addSimpleReplacement(range.token(node.period), '..'); + builder.addSimpleReplacement(range.token(period), '..'); }); - } else if (node.question != null) { + } else if (question != null) { _newOperator = '['; await builder.addDartFileEdit(file, (builder) { - builder.addDeletion(range.token(node.question)); + builder.addDeletion(range.token(question)); }); } } else if (node is SpreadElement) { diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart index 0f36a394e76..c6b7dd1d6be 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -19,18 +17,22 @@ class ReplaceWithNullAware extends CorrectionProducer { Future compute(ChangeBuilder builder) async { var node = coveredNode; if (node is Expression) { + final node_final = node; await builder.addDartFileEdit(file, (builder) { - var parent = node.parent; + var parent = node_final.parent; while (parent != null) { if (parent is MethodInvocation && parent.target == node) { - builder.addSimpleReplacement(range.token(parent.operator), '?.'); + var operator = parent.operator; + if (operator != null) { + builder.addSimpleReplacement(range.token(operator), '?.'); + } } else if (parent is PropertyAccess && parent.target == node) { builder.addSimpleReplacement(range.token(parent.operator), '?.'); } else { break; } node = parent; - parent = node.parent; + parent = node?.parent; } }); } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_tear_off.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_tear_off.dart index 44df3ffd70e..14d77c23870 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_tear_off.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_tear_off.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -24,16 +22,22 @@ class ReplaceWithTearOff extends CorrectionProducer { if (ancestor == null) { return; } - Future addFixOfExpression(InvocationExpression expression) async { - await builder.addDartFileEdit(file, (builder) { - builder.addReplacement(range.node(ancestor), (builder) { - if (expression is MethodInvocation && expression.target != null) { - builder.write(utils.getNodeText(expression.target)); - builder.write('.'); - } - builder.write(utils.getNodeText(expression.function)); + + Future addFixOfExpression(Expression? expression) async { + if (expression is InvocationExpression) { + await builder.addDartFileEdit(file, (builder) { + builder.addReplacement(range.node(ancestor), (builder) { + if (expression is MethodInvocation) { + var target = expression.target; + if (target != null) { + builder.write(utils.getNodeText(target)); + builder.write('.'); + } + } + builder.write(utils.getNodeText(expression.function)); + }); }); - }); + } } final body = ancestor.body; @@ -47,7 +51,7 @@ class ReplaceWithTearOff extends CorrectionProducer { await addFixOfExpression(expression.unParenthesized); } else if (statement is ReturnStatement) { final expression = statement.expression; - await addFixOfExpression(expression.unParenthesized); + await addFixOfExpression(expression?.unParenthesized); } } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart index dcdee93b5e1..1c6da82f864 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_var.dart @@ -2,12 +2,11 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; +import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer_plugin/utilities/assist/assist.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; @@ -44,25 +43,28 @@ class ReplaceWithVar extends CorrectionProducer { return; } var initializer = variables[0].initializer; - String typeArgumentsText; - int typeArgumentsOffset; - if (type is NamedType && type.typeArguments != null) { - if (initializer is CascadeExpression) { - initializer = (initializer as CascadeExpression).target; - } - if (initializer is TypedLiteral) { - if (initializer.typeArguments == null) { - typeArgumentsText = utils.getNodeText(type.typeArguments); - if (initializer is ListLiteral) { - typeArgumentsOffset = initializer.leftBracket.offset; - } else if (initializer is SetOrMapLiteral) { - typeArgumentsOffset = initializer.leftBracket.offset; - } + String? typeArgumentsText; + int? typeArgumentsOffset; + if (type is NamedType) { + var typeArguments = type.typeArguments; + if (typeArguments != null) { + if (initializer is CascadeExpression) { + initializer = initializer.target; } - } else if (initializer is InstanceCreationExpression) { - if (initializer.constructorName.type.typeArguments == null) { - typeArgumentsText = utils.getNodeText(type.typeArguments); - typeArgumentsOffset = initializer.constructorName.type.end; + if (initializer is TypedLiteral) { + if (initializer.typeArguments == null) { + typeArgumentsText = utils.getNodeText(typeArguments); + if (initializer is ListLiteral) { + typeArgumentsOffset = initializer.leftBracket.offset; + } else if (initializer is SetOrMapLiteral) { + typeArgumentsOffset = initializer.leftBracket.offset; + } + } + } else if (initializer is InstanceCreationExpression) { + if (initializer.constructorName.type.typeArguments == null) { + typeArgumentsText = utils.getNodeText(typeArguments); + typeArgumentsOffset = initializer.constructorName.type.end; + } } } } @@ -80,19 +82,22 @@ class ReplaceWithVar extends CorrectionProducer { } else { builder.addSimpleReplacement(range.node(type), 'var'); } - if (typeArgumentsText != null) { + if (typeArgumentsText != null && typeArgumentsOffset != null) { builder.addSimpleInsertion(typeArgumentsOffset, typeArgumentsText); } }); } else if (parent is DeclaredIdentifier && grandparent is ForEachPartsWithDeclaration) { - String typeArgumentsText; - int typeArgumentsOffset; - if (type is NamedType && type.typeArguments != null) { - var iterable = grandparent.iterable; - if (iterable is TypedLiteral && iterable.typeArguments == null) { - typeArgumentsText = utils.getNodeText(type.typeArguments); - typeArgumentsOffset = iterable.offset; + String? typeArgumentsText; + int? typeArgumentsOffset; + if (type is NamedType) { + var typeArguments = type.typeArguments; + if (typeArguments != null) { + var iterable = grandparent.iterable; + if (iterable is TypedLiteral && iterable.typeArguments == null) { + typeArgumentsText = utils.getNodeText(typeArguments); + typeArgumentsOffset = iterable.offset; + } } } await builder.addDartFileEdit(file, (builder) { @@ -101,7 +106,7 @@ class ReplaceWithVar extends CorrectionProducer { } else { builder.addSimpleReplacement(range.node(type), 'var'); } - if (typeArgumentsText != null) { + if (typeArgumentsText != null && typeArgumentsOffset != null) { builder.addSimpleInsertion(typeArgumentsOffset, typeArgumentsText); } }); @@ -110,7 +115,7 @@ class ReplaceWithVar extends CorrectionProducer { /// Return `true` if the type in the [node] can be replaced with `var`. bool _canConvertVariableDeclarationList(VariableDeclarationList node) { - final staticType = node?.type?.type; + final staticType = node.type?.type; if (staticType == null || staticType.isDynamic) { return false; } @@ -137,10 +142,10 @@ class ReplaceWithVar extends CorrectionProducer { if (staticType == null || staticType.isDynamic) { return false; } - final iterableType = parent.iterable.staticType; + final iterableType = parent.iterable.typeOrThrow; var instantiatedType = iterableType.asInstanceOf(typeProvider.iterableElement); - if (instantiatedType?.typeArguments?.first == staticType) { + if (instantiatedType?.typeArguments.first == staticType) { return true; } return false; @@ -152,7 +157,7 @@ class ReplaceWithVar extends CorrectionProducer { /// Using the [node] as a starting point, return the type annotation that is /// to be replaced, or `null` if there is no type annotation. - TypeAnnotation _findType(AstNode node) { + TypeAnnotation? _findType(AstNode node) { if (node is VariableDeclarationList) { return node.type; } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart b/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart index 8f4de40282d..c46f1591f0d 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/shadow_field.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,34 +18,45 @@ class ShadowField extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { + final node = this.node; if (node is! SimpleIdentifier) { return; } - var element = (node as SimpleIdentifier).writeOrReadElement; - if (element is! PropertyAccessorElement) { + + var accessor = node.writeOrReadElement; + if (accessor is! PropertyAccessorElement) { return; } - var accessor = element as PropertyAccessorElement; + if (!accessor.isGetter || accessor.enclosingElement is! ClassElement) { // TODO(brianwilkerson) Should we also require that the getter be synthetic? return; } + var statement = _getStatement(); if (statement == null) { return; } - if (statement.parent is! Block) { + + var enclosingBlock = statement.parent; + if (enclosingBlock is! Block) { // TODO(brianwilkerson) Support adding a block between the statement and // its parent (where the parent will be something like a while or if // statement). Also support the case where the parent is a case clause. return; } - var enclosingBlock = statement.parent as Block; - var finder = _ReferenceFinder(accessor.correspondingSetter); + + var correspondingSetter = accessor.correspondingSetter; + if (correspondingSetter == null) { + return; + } + + var finder = _ReferenceFinder(correspondingSetter); enclosingBlock.accept(finder); if (finder.hasSetterReference) { return; } + var fieldName = accessor.name; var offset = statement.offset; var prefix = utils.getLinePrefix(offset); @@ -74,13 +83,13 @@ class ShadowField extends CorrectionProducer { /// Return the statement immediately enclosing the [node] that would promote /// the type of the field if it were replaced by a local variable. - Statement _getStatement() { + Statement? _getStatement() { var parent = node.parent; - Statement enclosingIf(Expression expression) { + Statement? enclosingIf(Expression expression) { var parent = expression.parent; while (parent is BinaryExpression) { - var opType = (parent as BinaryExpression).operator.type; + var opType = parent.operator.type; if (opType != TokenType.AMPERSAND_AMPERSAND) { break; } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/sort_child_property_last.dart b/pkg/analysis_server/lib/src/services/correction/dart/sort_child_property_last.dart index 6f0d39264ce..e2cc444e61d 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/sort_child_property_last.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/sort_child_property_last.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; @@ -32,13 +30,12 @@ class SortChildPropertyLast extends CorrectionProducer { return; } - var parent = childProp.parent?.parent; - if (parent is! InstanceCreationExpression || - !flutter.isWidgetCreation(parent)) { + var creationExpression = childProp.parent?.parent; + if (creationExpression is! InstanceCreationExpression || + !flutter.isWidgetCreation(creationExpression)) { return; } - InstanceCreationExpression creationExpression = parent; var args = creationExpression.argumentList; var last = args.arguments.last; @@ -48,10 +45,10 @@ class SortChildPropertyLast extends CorrectionProducer { } await builder.addDartFileEdit(file, (fileEditBuilder) { - var hasTrailingComma = last.endToken.next.type == TokenType.COMMA; + var hasTrailingComma = last.endToken.next!.type == TokenType.COMMA; - var childStart = childProp.beginToken.previous.end; - var childEnd = childProp.endToken.next.end; + var childStart = childProp.beginToken.previous!.end; + var childEnd = childProp.endToken.next!.end; var childRange = range.startOffsetEndOffset(childStart, childEnd); var deletionRange = childRange; @@ -69,7 +66,7 @@ class SortChildPropertyLast extends CorrectionProducer { var insertionPoint = last.end; if (hasTrailingComma) { - insertionPoint = last.endToken.next.end; + insertionPoint = last.endToken.next!.end; } else if (childStart == childProp.offset) { childText = ', $childText'; } else { @@ -85,7 +82,7 @@ class SortChildPropertyLast extends CorrectionProducer { /// Using the [node] as the starting point, find the named expression that is /// for either the `child` or `children` parameter. - NamedExpression _findNamedExpression(AstNode node) { + NamedExpression? _findNamedExpression(AstNode node) { if (node is NamedExpression) { var name = node.name.label.name; if (name == 'child' || name == 'children') { diff --git a/pkg/analysis_server/lib/src/services/correction/dart/split_and_condition.dart b/pkg/analysis_server/lib/src/services/correction/dart/split_and_condition.dart index f358b4e817c..028d245feb8 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/split_and_condition.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/split_and_condition.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/util.dart'; @@ -20,10 +18,10 @@ class SplitAndCondition extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { // check that user invokes quick assist on binary expression - if (node is! BinaryExpression) { + var binaryExpression = node; + if (binaryExpression is! BinaryExpression) { return; } - var binaryExpression = node as BinaryExpression; // prepare operator position if (!isOperatorSelected(binaryExpression)) { return; @@ -33,11 +31,10 @@ class SplitAndCondition extends CorrectionProducer { return; } // prepare "if" - var statement = node.thisOrAncestorOfType(); - if (statement is! IfStatement) { + var ifStatement = node.thisOrAncestorOfType(); + if (ifStatement is! IfStatement) { return; } - var ifStatement = statement as IfStatement; // no support "else" if (ifStatement.elseStatement != null) { return; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart index c5b109e4fd9..83073d8ece5 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:_fe_analyzer_shared/src/scanner/token.dart'; import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; @@ -18,16 +16,20 @@ class SplitVariableDeclaration extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - var variableList = node?.thisOrAncestorOfType(); - - // Must be a local variable declaration. - if (variableList?.parent is! VariableDeclarationStatement) { + var variableList = node.thisOrAncestorOfType(); + if (variableList == null) { + return; + } + + // Must be a local variable declaration. + var statement = variableList.parent; + if (statement is! VariableDeclarationStatement) { return; } - VariableDeclarationStatement statement = variableList.parent; // Cannot be `const` or `final`. - var keywordKind = variableList.keyword?.keyword; + var keyword = variableList.keyword; + var keywordKind = keyword?.keyword; if (keywordKind == Keyword.CONST || keywordKind == Keyword.FINAL) { return; } @@ -50,9 +52,9 @@ class SplitVariableDeclaration extends CorrectionProducer { await builder.addDartFileEdit(file, (builder) { if (variableList.type == null) { - final type = variable.declaredElement.type; - if (!type.isDynamic) { - builder.addReplacement(range.token(variableList.keyword), (builder) { + final type = variable.declaredElement!.type; + if (!type.isDynamic && keyword != null) { + builder.addReplacement(range.token(keyword), (builder) { builder.writeType(type); }); } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart index dddf35152ec..4cab9d2539a 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/file_system/file_system.dart'; @@ -25,32 +23,25 @@ class UpdateSdkConstraints extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - var context = resourceProvider.pathContext; - File pubspecFile; - var folder = resourceProvider.getFolder(context.dirname(file)); - while (folder != null) { - pubspecFile = folder.getChildAssumingFile('pubspec.yaml'); - if (pubspecFile.exists) { - break; - } - pubspecFile = null; - folder = folder.parent2; - } + var pubspecFile = _findPubspecFile(); if (pubspecFile == null) { return; } + var extractor = SdkConstraintExtractor(pubspecFile); var text = extractor.constraintText(); var offset = extractor.constraintOffset(); if (text == null || offset < 0) { return; } + var length = text.length; - String newText; var spaceOffset = text.indexOf(' '); if (spaceOffset >= 0) { length = spaceOffset; } + + String? newText; if (text == 'any') { newText = '^$_minimumVersion'; } else if (text.startsWith('^')) { @@ -63,11 +54,23 @@ class UpdateSdkConstraints extends CorrectionProducer { if (newText == null) { return; } + + final newText_final = newText; await builder.addGenericFileEdit(pubspecFile.path, (builder) { - builder.addSimpleReplacement(SourceRange(offset, length), newText); + builder.addSimpleReplacement(SourceRange(offset, length), newText_final); }); } + File? _findPubspecFile() { + var file = resourceProvider.getFile(this.file); + for (var folder in file.parent2.withAncestors) { + var pubspecFile = folder.getChildAssumingFile('pubspec.yaml'); + if (pubspecFile.exists) { + return pubspecFile; + } + } + } + /// Return an instance of this class that will update the SDK constraints to /// '2.1.0'. Used as a tear-off in `FixProcessor`. static UpdateSdkConstraints version_2_1_0() => UpdateSdkConstraints('2.1.0'); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_const.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_const.dart index 1c9d8238bd3..110432e70c1 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_const.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_const.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,12 +18,12 @@ class UseConst extends CorrectionProducer { if (coveredNode is InstanceCreationExpression) { var instanceCreation = coveredNode as InstanceCreationExpression; await builder.addDartFileEdit(file, (builder) { - if (instanceCreation.keyword == null) { + var keyword = instanceCreation.keyword; + if (keyword == null) { builder.addSimpleInsertion( instanceCreation.constructorName.offset, 'const'); } else { - builder.addSimpleReplacement( - range.token(instanceCreation.keyword), 'const'); + builder.addSimpleReplacement(range.token(keyword), 'const'); } }); } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_curly_braces.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_curly_braces.dart index f76e561a7a6..b414e487492 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_curly_braces.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_curly_braces.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/assist.dart'; import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; @@ -37,9 +35,12 @@ class UseCurlyBraces extends CorrectionProducer { } else if (parent is ForStatement) { return _forStatement(builder, parent); } else if (statement is IfStatement) { - if (statement.elseKeyword != null && - range.token(statement.elseKeyword).contains(selectionOffset)) { - return _ifStatement(builder, statement, statement.elseStatement); + var elseKeyword = statement.elseKeyword; + var elseStatement = statement.elseStatement; + if (elseKeyword != null && + elseStatement != null && + range.token(elseKeyword).contains(selectionOffset)) { + return _ifStatement(builder, statement, elseStatement); } else { return _ifStatement(builder, statement, null); } @@ -88,21 +89,22 @@ class UseCurlyBraces extends CorrectionProducer { } Future _ifStatement( - ChangeBuilder builder, IfStatement node, Statement thenOrElse) async { + ChangeBuilder builder, IfStatement node, Statement? thenOrElse) async { var prefix = utils.getLinePrefix(node.offset); var indent = prefix + utils.getIndent(1); await builder.addDartFileEdit(file, (builder) { var thenStatement = node.thenStatement; + var elseKeyword = node.elseKeyword; if (thenStatement is! Block && (thenOrElse == null || thenOrElse == thenStatement)) { builder.addSimpleReplacement( range.endStart(node.rightParenthesis, thenStatement), ' {$eol$indent', ); - if (node.elseKeyword != null) { + if (elseKeyword != null) { builder.addSimpleReplacement( - range.endStart(thenStatement, node.elseKeyword), + range.endStart(thenStatement, elseKeyword), '$eol$prefix} ', ); } else { @@ -111,11 +113,12 @@ class UseCurlyBraces extends CorrectionProducer { } var elseStatement = node.elseStatement; - if (elseStatement != null && + if (elseKeyword != null && + elseStatement != null && elseStatement is! Block && (thenOrElse == null || thenOrElse == elseStatement)) { builder.addSimpleReplacement( - range.endStart(node.elseKeyword, elseStatement), + range.endStart(elseKeyword, elseStatement), ' {$eol$indent', ); builder.addSimpleInsertion(elseStatement.end, '$eol$prefix}'); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart index babab166357..5a0839dfef4 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_effective_integer_division.dart @@ -2,10 +2,9 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; +import 'package:analysis_server/src/utilities/extensions/ast.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; @@ -17,21 +16,24 @@ class UseEffectiveIntegerDivision extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - for (var n = node; n != null; n = n.parent) { - if (n is MethodInvocation && - n.offset == errorOffset && - n.length == errorLength) { - var target = (n as MethodInvocation).target.unParenthesized; - await builder.addDartFileEdit(file, (builder) { - // replace "/" with "~/" - var binary = target as BinaryExpression; - builder.addSimpleReplacement(range.token(binary.operator), '~/'); - // remove everything before and after - builder.addDeletion(range.startStart(n, binary.leftOperand)); - builder.addDeletion(range.endEnd(binary.rightOperand, n)); - }); - // done - break; + for (var n in node.withParents) { + if (n is MethodInvocation) { + if (n.offset == errorOffset && n.length == errorLength) { + var target = n.target; + if (target != null) { + target = target.unParenthesized; + await builder.addDartFileEdit(file, (builder) { + // replace "/" with "~/" + var binary = target as BinaryExpression; + builder.addSimpleReplacement(range.token(binary.operator), '~/'); + // remove everything before and after + builder.addDeletion(range.startStart(n, binary.leftOperand)); + builder.addDeletion(range.endEnd(binary.rightOperand, n)); + }); + } + // done + break; + } } } } diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart index ce4e1f4800c..86ad614abdb 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_eq_eq_null.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart index ca10cbfe3ab..8b06bc9688b 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_is_not_empty.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -21,10 +19,10 @@ class UseIsNotEmpty extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { - if (node is! PrefixExpression) { + var prefixExpression = node; + if (prefixExpression is! PrefixExpression) { return; } - PrefixExpression prefixExpression = node; var negation = prefixExpression.operator; if (negation.type != TokenType.BANG) { return; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_not_eq_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_not_eq_null.dart index 120e87d75fb..e53bc024954 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_not_eq_null.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_not_eq_null.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; diff --git a/pkg/analysis_server/lib/src/services/correction/dart/use_rethrow.dart b/pkg/analysis_server/lib/src/services/correction/dart/use_rethrow.dart index dc5522023dc..9ebe4dcc2a8 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/use_rethrow.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/use_rethrow.dart @@ -2,8 +2,6 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; @@ -20,6 +18,7 @@ class UseRethrow extends CorrectionProducer { @override Future compute(ChangeBuilder builder) async { + final coveredNode = this.coveredNode; if (coveredNode is ThrowExpression) { await builder.addDartFileEdit(file, (builder) { builder.addSimpleReplacement(range.node(coveredNode), 'rethrow'); diff --git a/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart b/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart index bfd97f5ff33..49fb849e02e 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart @@ -2,20 +2,16 @@ // 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. -// @dart = 2.9 - import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart'; import 'package:analysis_server/src/services/correction/fix.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/src/dart/ast/extensions.dart'; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:analyzer_plugin/utilities/range_factory.dart'; class WrapInText extends CorrectionProducer { - ParameterElement _parameterElement; - Expression _stringExpression; - @override FixKind get fixKind => DartFixKind.WRAP_IN_TEXT; @@ -24,43 +20,55 @@ class WrapInText extends CorrectionProducer { // // Extract the information needed to build the edit. // - _extractContextInformation(node); - if (_parameterElement == null || _stringExpression == null) { + var context = _extractContextInformation(node); + if (context == null) { return; } - if (!flutter.isWidgetType(_parameterElement.type)) { + if (!flutter.isWidgetType(context.parameterElement.type)) { return; } // // Extract the information needed to build the edit. // - var stringExpressionCode = utils.getNodeText(_stringExpression); + var stringExpressionCode = utils.getNodeText(context.stringExpression); // // Build the edit. // await builder.addDartFileEdit(file, (builder) { builder.addSimpleReplacement( - range.node(_stringExpression), + range.node(context.stringExpression), 'Text($stringExpressionCode)', ); }); } - /// Set the `String` typed named expression to [_stringExpression], and the - /// corresponding parameter to [_parameterElement]. Leave the fields `null` - /// if not a named argument, or not a `String` typed expression. - void _extractContextInformation(AstNode node) { + /// Return an instance of this class. Used as a tear-off in `FixProcessor`. + static WrapInText newInstance() => WrapInText(); + + static _Context? _extractContextInformation(AstNode node) { if (node is NamedExpression) { var expression = node.expression; - if (expression.staticType.isDartCoreString) { - _parameterElement = node.name.label.staticElement; - _stringExpression = expression; + if (expression.typeOrThrow.isDartCoreString) { + var parameterElement = node.name.label.staticElement; + if (parameterElement is ParameterElement) { + return _Context( + stringExpression: expression, + parameterElement: parameterElement, + ); + } } } } - - /// Return an instance of this class. Used as a tear-off in `FixProcessor`. - static WrapInText newInstance() => WrapInText(); +} + +class _Context { + final Expression stringExpression; + final ParameterElement parameterElement; + + _Context({ + required this.stringExpression, + required this.parameterElement, + }); } diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart index c61a3fd7162..2f4bec9e2fc 100644 --- a/pkg/analysis_server/lib/src/services/correction/util.dart +++ b/pkg/analysis_server/lib/src/services/correction/util.dart @@ -429,7 +429,7 @@ Expression? getQualifiedPropertyTarget(AstNode node) { /// Returns the given [statement] if not a block, or the first child statement /// if a block, or `null` if more than one child. -Statement? getSingleStatement(Statement statement) { +Statement? getSingleStatement(Statement? statement) { if (statement is Block) { List blockStatements = statement.statements; if (blockStatements.length != 1) {