diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart index 8af69ab7123b..8dfef63658e7 100644 --- a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart +++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart @@ -79,6 +79,8 @@ class RemoveComparison extends CorrectionProducer { (type == TokenType.BAR_BAR && _conditionIsFalse)) { await _removeOperatorAndOperand(builder, parent); } + } else if (parent is IfElement) { + await _ifElement(parent, builder); } else if (parent is IfStatement) { if (parent.elseStatement == null && _conditionIsTrue) { await _ifStatement(parent, builder); @@ -86,6 +88,33 @@ class RemoveComparison extends CorrectionProducer { } } + Future _ifElement(IfElement node, ChangeBuilder builder) async { + if (_conditionIsTrue) { + await builder.addDartFileEdit(file, (builder) { + final text = _textWithLeadingComments(node.thenElement); + final unIndented = utils.indentLeft(text); + builder.addSimpleReplacement(range.node(node), unIndented); + }); + } else if (_conditionIsFalse) { + final elseElement = node.elseElement; + if (elseElement != null) { + await builder.addDartFileEdit(file, (builder) { + final text = _textWithLeadingComments(elseElement); + final unIndented = utils.indentLeft(text); + builder.addSimpleReplacement(range.node(node), unIndented); + }); + } else { + final elements = node.parent.containerElements; + if (elements != null) { + await builder.addDartFileEdit(file, (builder) { + final nodeRange = range.nodeInList(elements, node); + builder.addDeletion(nodeRange); + }); + } + } + } + } + Future _ifStatement(IfStatement node, ChangeBuilder builder) async { await builder.addDartFileEdit(file, (builder) { var nodeRange = utils.getLinesRangeStatements([node]); @@ -127,4 +156,20 @@ class RemoveComparison extends CorrectionProducer { builder.addDeletion(operatorAndOperand); }); } + + String _textWithLeadingComments(AstNode node) { + return utils.getNodeText(node, withLeadingComments: true); + } +} + +extension on AstNode? { + NodeList? get containerElements { + final self = this; + if (self is ListLiteral) { + return self.elements; + } else if (self is SetOrMapLiteral) { + return self.elements; + } + return null; + } } diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart index 23b6be9d6f41..af298bbb587d 100644 --- a/pkg/analysis_server/lib/src/services/correction/util.dart +++ b/pkg/analysis_server/lib/src/services/correction/util.dart @@ -876,8 +876,17 @@ class CorrectionUtils { } /// Returns the text of the given [AstNode] in the unit. - String getNodeText(AstNode node) { - return getText(node.offset, node.length); + String getNodeText( + AstNode node, { + bool withLeadingComments = false, + }) { + final firstToken = withLeadingComments + ? node.beginToken.precedingComments ?? node.beginToken + : node.beginToken; + final offset = firstToken.offset; + final end = node.endToken.end; + final length = end - offset; + return getText(offset, length); } /// Returns the line prefix consisting of spaces and tabs on the left from the @@ -975,6 +984,28 @@ class CorrectionUtils { throw UnimplementedError('(${type.runtimeType}) $type'); } + /// Splits [text] into lines, and removes one level of indent from each line. + /// Lines that don't start with indentation are left as is. + String indentLeft(String text) { + final buffer = StringBuffer(); + final indent = getIndent(1); + final eol = endOfLine; + final lines = text.split(eol); + for (final line in lines) { + if (buffer.isNotEmpty) { + buffer.write(eol); + } + final String updatedLine; + if (line.startsWith(indent)) { + updatedLine = line.substring(indent.length); + } else { + updatedLine = line; + } + buffer.write(updatedLine); + } + return buffer.toString(); + } + /// Indents given source left or right. String indentSourceLeftRight(String source, {bool indentLeft = true}) { var sb = StringBuffer(); diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart index 9982a599b5d3..84c8603b0fcb 100644 --- a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart +++ b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart @@ -150,6 +150,189 @@ void f(String s) { '''); } + Future test_ifElement_alwaysFalse_hasElse() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + if (x == null) 1 else -1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + -1, + 2, + ]; +} +'''); + } + + Future test_ifElement_alwaysFalse_hasElse_withComments() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + // C1 + if (x == null) + // C2 + 1 + else + // C3 + -1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + // C1 + // C3 + -1, + 2, + ]; +} +'''); + } + + Future test_ifElement_alwaysFalse_noElse_insideList() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + if (x == null) 1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + 2, + ]; +} +'''); + } + + Future + test_ifElement_alwaysFalse_noElse_insideList_withComments() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + // C1 + if (x == null) + // C2 + 1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + 2, + ]; +} +'''); + } + + Future test_ifElement_alwaysFalse_noElse_insideSet() async { + await resolveTestCode(''' +Object f(int x) { + return { + 0, + if (x == null) 1, + 2, + }; +} +'''); + await assertHasFix(''' +Object f(int x) { + return { + 0, + 2, + }; +} +'''); + } + + Future test_ifElement_alwaysTrue() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + if (x != null) + 1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + 1, + 2, + ]; +} +'''); + } + + Future test_ifElement_alwaysTrue_hasElse() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + if (x != null) 1 else -1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + 1, + 2, + ]; +} +'''); + } + + Future test_ifElement_alwaysTrue_withComments() async { + await resolveTestCode(''' +void f(int x) { + [ + 0, + // C1 + if (x != null) + // C2 + 1, + 2, + ]; +} +'''); + await assertHasFix(''' +void f(int x) { + [ + 0, + // C1 + // C2 + 1, + 2, + ]; +} +'''); + } + Future test_ifStatement_thenBlock() async { await resolveTestCode(''' void f(String s) {