@@ -6,8 +6,6 @@ import 'package:analysis_server/src/services/correction/fix.dart';
66import 'package:analysis_server_plugin/edit/dart/correction_producer.dart' ;
77import 'package:analyzer/dart/ast/ast.dart' ;
88import 'package:analyzer/dart/ast/precedence.dart' ;
9- import 'package:analyzer/dart/ast/token.dart' ;
10- import 'package:analyzer/source/source_range.dart' ;
119import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart' ;
1210import 'package:analyzer_plugin/utilities/fixes/fixes.dart' ;
1311import 'package:analyzer_plugin/utilities/range_factory.dart' ;
@@ -29,223 +27,49 @@ class ConvertToBooleanExpression extends ResolvedCorrectionProducer {
2927 Future <void > compute (ChangeBuilder builder) async {
3028 AstNode ? node = this .node;
3129 if (node is BooleanLiteral ) node = node.parent;
30+ if (node is ! BinaryExpression ) return ;
3231
33- if (node case BinaryExpression (
34- : var rightOperand,
35- : var leftOperand,
36- operator : Token (type: var operator ),
37- )) {
38- if (rightOperand is BooleanLiteral ) {
39- return await _processBinaryExp (
40- builder,
41- node,
42- operator ,
43- rightOperand,
44- leftOperand,
45- currentIsLeft: false ,
46- );
47- }
48- if (leftOperand is BooleanLiteral ) {
49- return await _processBinaryExp (
50- builder,
51- node,
52- operator ,
53- leftOperand,
54- rightOperand,
55- currentIsLeft: true ,
56- );
57- }
58- } else if (node
59- case ConditionalExpression (
60- : var condition,
61- : var thenExpression,
62- : var elseExpression,
63- ) &&
64- var conditionalExp) {
65- await (switch ((thenExpression, elseExpression)) {
66- (BooleanLiteral then, BooleanLiteral elseExp) => () async {
67- var equalValues = then.value == elseExp.value;
68- var rangeStart =
69- equalValues
70- // keep `then`
71- ? range.startStart (condition, then)
72- // keep `condition`
73- : range.endEnd (condition, then);
74- // remove ` : elseExp`
75- var rangeEnd = range.endEnd (then, elseExp);
76- await _addEdit (
77- builder,
78- parensRange: range.node (equalValues ? then : condition),
79- deleteRanges: [rangeStart, rangeEnd],
80- negated: ! then.value && elseExp.value,
81- needsParens: ! equalValues && condition.needsParens (),
82- bangBeforeParens: false ,
83- );
84- }(),
85- (BooleanLiteral then, Expression elseExp) => () async {
86- var replaceRange = range.endStart (condition, elseExp);
87- var operator = then.ifBarElseAmpersand;
88- await _addEdit (
89- builder,
90- parensRange: range.node (conditionalExp.condition),
91- deleteRanges: const < SourceRange > [],
92- negated: ! then.value,
93- replace: (replaceRange, ' ${operator .lexeme } ' ),
94- needsParens: conditionalExp.condition.needsParens (
95- then.value ? operator : null ,
96- ),
97- bangBeforeParens: true ,
98- parensRange2:
99- elseExp.needsParens (operator ) ? range.node (elseExp) : null ,
100- );
101- }(),
102- (Expression then, BooleanLiteral elseExp) => () async {
103- var rangeStart = range.endStart (condition, then);
104- var rangeEnd = range.endEnd (then, elseExp);
105- var operator = elseExp.ifBarElseAmpersand;
106- await _addEdit (
107- builder,
108- parensRange: range.node (conditionalExp.condition),
109- deleteRanges: [rangeEnd],
110- negated: elseExp.value,
111- replace: (rangeStart, ' ${operator .lexeme } ' ),
112- needsParens: conditionalExp.condition.needsParens (
113- elseExp.value ? null : operator ,
114- ),
115- bangBeforeParens: true ,
116- parensRange2: then.needsParens (operator ) ? range.node (then) : null ,
117- );
118- }(),
119- (_, _) => null ,
120- });
32+ var rightOperand = node.rightOperand;
33+ var leftOperand = node.leftOperand;
34+
35+ Expression expression;
36+ BooleanLiteral literal;
37+
38+ var deleteRange = range.endEnd (leftOperand, rightOperand);
39+
40+ if (rightOperand is BooleanLiteral ) {
41+ literal = rightOperand;
42+ expression = node.leftOperand;
43+ } else if (leftOperand is BooleanLiteral ) {
44+ literal = leftOperand;
45+ expression = node.rightOperand;
46+ deleteRange = range.startStart (leftOperand, rightOperand);
47+ } else {
48+ return ;
12149 }
122- }
12350
124- /// This correction producer can act on a variety of code, and various edits
125- /// might be applied.
126- ///
127- /// The [deleteRanges] are ranges that should be deleted from the code.
128- ///
129- /// The [replace] will be normally used to replace part of the expression
130- /// with a new operator.
131- ///
132- /// The [parensRange] is related to [needsParens] and [bangBeforeParens] . The
133- /// `bang` is added only if [negated] is true. It was meant for adding the
134- /// parens when the `bang` or the new operator given by [replace] makes the
135- /// precedence of the expression different than the original one.
136- ///
137- /// The [parensRange2] is meant to be used when converting conditional
138- /// expressions and should be non-`null` if the second expression needs
139- /// parentheses considering the new operator added by the given [replace] .
140- Future <void > _addEdit (
141- ChangeBuilder builder, {
142- required SourceRange parensRange,
143- required bool needsParens,
144- required List <SourceRange > deleteRanges,
145- required bool negated,
146- required bool bangBeforeParens,
147- (SourceRange , String )? replace,
148- SourceRange ? parensRange2,
149- }) async {
51+ var negated = ! isPositiveCase (node, literal);
15052 await builder.addDartFileEdit (file, (builder) {
151- if (bangBeforeParens) {
152- if (negated) {
153- builder.addSimpleInsertion (parensRange.offset, TokenType .BANG .lexeme);
154- }
155- if (needsParens) {
156- builder.addSimpleInsertion (parensRange.offset, '(' );
157- builder.addSimpleInsertion (parensRange.end, ')' );
158- }
159- } else {
160- if (needsParens) {
161- builder.addSimpleInsertion (parensRange.offset, '(' );
162- }
163- if (negated) {
164- builder.addSimpleInsertion (parensRange.offset, TokenType .BANG .lexeme);
53+ if (negated) {
54+ builder.addSimpleInsertion (expression.offset, '!' );
55+ if (expression.needsParens) {
56+ builder.addSimpleInsertion (expression.offset, '(' );
57+ builder.addSimpleInsertion (expression.end, ')' );
16558 }
166- if (needsParens) {
167- builder.addSimpleInsertion (parensRange.end, ')' );
168- }
169- }
170- if (replace != null ) {
171- builder.addSimpleReplacement (replace.$1, replace.$2);
172- }
173- if (parensRange2 != null ) {
174- builder.addSimpleInsertion (parensRange2.offset, '(' );
175- builder.addSimpleInsertion (parensRange2.end, ')' );
176- }
177- for (var range in deleteRanges) {
178- builder.addDeletion (range);
17959 }
60+ builder.addDeletion (deleteRange);
18061 });
18162 }
18263
183- Future <void > _processBinaryExp (
184- ChangeBuilder builder,
185- BinaryExpression binaryExp,
186- TokenType operator ,
187- BooleanLiteral current,
188- Expression other, {
189- required bool currentIsLeft,
190- }) async {
191- List <SourceRange > deleteRanges;
192- SourceRange parensRange;
193- bool needsParens;
194- switch (operator ) {
195- case TokenType .BAR || TokenType .BAR_BAR when current.value:
196- case TokenType .AMPERSAND || TokenType .AMPERSAND_AMPERSAND
197- when ! current.value:
198- deleteRanges = [
199- currentIsLeft
200- ? range.endEnd (current, other)
201- : range.startStart (other, current),
202- ];
203- parensRange = range.node (current);
204- needsParens = current.needsParens ();
205- default :
206- deleteRanges = [
207- currentIsLeft
208- ? range.startStart (current, other)
209- : range.endEnd (other, current),
210- ];
211- parensRange = range.node (other);
212- needsParens = other.needsParens ();
213- }
214- await _addEdit (
215- builder,
216- negated: ! isPositiveCase (binaryExp, current),
217- parensRange: parensRange,
218- deleteRanges: deleteRanges,
219- needsParens: needsParens,
220- bangBeforeParens: true ,
221- );
222- }
223-
22464 static bool isPositiveCase (
22565 BinaryExpression expression,
22666 BooleanLiteral literal,
22767 ) {
228- return switch (expression.operator .type) {
229- TokenType .BAR ||
230- TokenType .BAR_BAR ||
231- TokenType .AMPERSAND ||
232- TokenType .AMPERSAND_AMPERSAND => true ,
233- TokenType .EQ_EQ => literal.value,
234- TokenType .BANG_EQ || TokenType .CARET => ! literal.value,
235- _ => throw StateError ('Unexpected operator ${expression .operator .type }' ),
236- };
68+ if (expression.operator .lexeme == '==' ) return literal.value;
69+ return ! literal.value;
23770 }
23871}
23972
240- extension on BooleanLiteral {
241- TokenType get ifBarElseAmpersand =>
242- value ? TokenType .BAR_BAR : TokenType .AMPERSAND_AMPERSAND ;
243- }
244-
24573extension on Expression {
246- bool needsParens ([TokenType ? tokenType]) =>
247- precedence <=
248- (tokenType != null
249- ? Precedence .forTokenType (tokenType)
250- : Precedence .prefix);
74+ bool get needsParens => precedence <= Precedence .prefix;
25175}
0 commit comments