| // Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:code_builder/code_builder.dart'; | |
| import 'package:test/test.dart'; | |
| import '../common.dart'; | |
| void main() { | |
| useDartfmt(); | |
| group('Conditional', () { | |
| test('if statement', () { | |
| expect( | |
| Conditional( | |
| (b) => b | |
| ..branches.add( | |
| .new( | |
| (b) => b | |
| ..condition = .expression(refer('x').equalTo(literal(1))) | |
| ..body = refer('print').call([literal('one')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| if (x == 1) { | |
| print('one'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('if-else statement', () { | |
| expect( | |
| Conditional( | |
| (b) => b | |
| ..branches.add( | |
| .new( | |
| (b) => b | |
| ..condition = .expression(refer('x').equalTo(literal(1))) | |
| ..body = refer('print').call([literal('one')]).statement, | |
| ), | |
| ) | |
| ..orElse = refer('print').call([literal('other')]).statement, | |
| ), | |
| equalsDart(r''' | |
| if (x == 1) { | |
| print('one'); | |
| } else { | |
| print('other'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('if-else-if-else statement', () { | |
| expect( | |
| Conditional( | |
| (b) => b | |
| ..branches.addAll([ | |
| .new( | |
| (b) => b | |
| ..condition = .expression(refer('x').equalTo(literal(1))) | |
| ..body = refer('print').call([literal('one')]).statement, | |
| ), | |
| .new( | |
| (b) => b | |
| ..condition = .expression(refer('x').equalTo(literal(2))) | |
| ..body = refer('print').call([literal('two')]).statement, | |
| ), | |
| ]) | |
| ..orElse = refer('print').call([literal('other')]).statement, | |
| ), | |
| equalsDart(r''' | |
| if (x == 1) { | |
| print('one'); | |
| } else if (x == 2) { | |
| print('two'); | |
| } else { | |
| print('other'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('if-case condition', () { | |
| expect( | |
| Conditional( | |
| (b) => b | |
| ..branches.add( | |
| .new( | |
| (b) => b | |
| ..condition = .ifCase(refer('x'), .refer('Pattern')) | |
| ..body = refer('print').call([literal('matched')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| if (x case Pattern) { | |
| print('matched'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('if-case condition with guard', () { | |
| expect( | |
| Conditional( | |
| (b) => b | |
| ..branches.add( | |
| .new( | |
| (b) => b | |
| ..condition = .ifCase( | |
| refer('x'), | |
| .refer('Pattern'), | |
| guard: refer('y').greaterThan(literal(0)), | |
| ) | |
| ..body = refer('print').call([literal('matched')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| if (x case Pattern when y > 0) { | |
| print('matched'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('throws if no branches specified', () { | |
| expect(() => Conditional((b) => b), throwsArgumentError); | |
| }); | |
| }); | |
| group('ForLoop', () { | |
| test('traditional for loop', () { | |
| expect( | |
| ForLoop( | |
| (b) => b | |
| ..initialize = declareVar('i').assign(literal(0)) | |
| ..condition = refer('i').lessThan(literal(10)) | |
| ..advance = refer('i').operatorUnaryPostfixIncrement() | |
| ..body = refer('print').call([refer('i')]).statement, | |
| ), | |
| equalsDart(r''' | |
| for (var i = 0; i < 10; i++) { | |
| print(i); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('for loop with omitted parts', () { | |
| expect( | |
| ForLoop( | |
| (b) => b..body = refer('print').call([literal('infinite')]).statement, | |
| ), | |
| equalsDart(r''' | |
| for (;;) { | |
| print('infinite'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('for loop with label', () { | |
| expect( | |
| ForLoop( | |
| (b) => b | |
| ..initialize = declareVar('i').assign(literal(0)) | |
| ..condition = refer('i').lessThan(literal(10)) | |
| ..advance = refer('i').operatorUnaryPostfixIncrement() | |
| ..body = refer('print').call([refer('i')]).statement | |
| ..label = 'outer', | |
| ), | |
| equalsDart(r''' | |
| outer: | |
| for (var i = 0; i < 10; i++) { | |
| print(i); | |
| } | |
| '''), | |
| ); | |
| }); | |
| }); | |
| group('ForInLoop', () { | |
| test('synchronous for-in loop', () { | |
| expect( | |
| ForInLoop( | |
| (b) => b | |
| ..variable = declareFinal('item') | |
| ..object = refer('items') | |
| ..body = refer('print').call([refer('item')]).statement, | |
| ), | |
| equalsDart(r''' | |
| for (final item in items) { | |
| print(item); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('asynchronous await for loop', () { | |
| expect( | |
| ForInLoop( | |
| (b) => b | |
| ..variable = declareFinal('event') | |
| ..object = refer('stream') | |
| ..body = refer('print').call([refer('event')]).statement | |
| ..async = true, | |
| ), | |
| equalsDart(r''' | |
| await for (final event in stream) { | |
| print(event); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('for-in loop with label', () { | |
| expect( | |
| ForInLoop( | |
| (b) => b | |
| ..variable = declareFinal('item') | |
| ..object = refer('items') | |
| ..body = refer('print').call([refer('item')]).statement | |
| ..label = 'itemLoop', | |
| ), | |
| equalsDart(r''' | |
| itemLoop: | |
| for (final item in items) { | |
| print(item); | |
| } | |
| '''), | |
| ); | |
| }); | |
| }); | |
| group('WhileLoop', () { | |
| test('while loop', () { | |
| expect( | |
| WhileLoop( | |
| (b) => b | |
| ..condition = refer('running') | |
| ..body = refer('doWork').call([]).statement, | |
| ), | |
| equalsDart(r''' | |
| while (running) { | |
| doWork(); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('do-while loop', () { | |
| expect( | |
| WhileLoop( | |
| (b) => b | |
| ..condition = refer('running') | |
| ..body = refer('doWork').call([]).statement | |
| ..doWhile = true, | |
| ), | |
| equalsDart(r''' | |
| do { | |
| doWork(); | |
| } while (running); | |
| '''), | |
| ); | |
| }); | |
| test('while loop with label', () { | |
| expect( | |
| WhileLoop( | |
| (b) => b | |
| ..condition = refer('running') | |
| ..body = refer('doWork').call([]).statement | |
| ..label = 'loop', | |
| ), | |
| equalsDart(r''' | |
| loop: | |
| while (running) { | |
| doWork(); | |
| } | |
| '''), | |
| ); | |
| }); | |
| }); | |
| group('Try', () { | |
| test('try-catch', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..catches.add( | |
| .new( | |
| (b) => b | |
| ..exception = 'e' | |
| ..body = refer('print').call([refer('e')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } catch (e) { | |
| print(e); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('try-on without exception', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..catches.add( | |
| .new( | |
| (b) => b | |
| ..on = refer('FormatException') | |
| ..body = refer('print').call([literal('error')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } on FormatException { | |
| print('error'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('try-on-catch with stack trace', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..catches.add( | |
| .new( | |
| (b) => b | |
| ..on = refer('FormatException') | |
| ..exception = 'e' | |
| ..stackTrace = 's' | |
| ..body = refer('print').call([refer('s')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } on FormatException catch (e, s) { | |
| print(s); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('try-catch with stack trace only', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..catches.add( | |
| .new( | |
| (b) => b | |
| ..stackTrace = 's' | |
| ..body = refer('print').call([refer('s')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } catch (_, s) { | |
| print(s); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('try-finally without catch', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..finallyBlock = refer('cleanup').call([]).statement, | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } finally { | |
| cleanup(); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('try-catch-finally', () { | |
| expect( | |
| Try( | |
| (b) => b | |
| ..body = refer('risky').call([]).statement | |
| ..catches.add( | |
| .new( | |
| (b) => b | |
| ..exception = 'e' | |
| ..body = refer('print').call([refer('e')]).statement, | |
| ), | |
| ) | |
| ..finallyBlock = refer('cleanup').call([]).statement, | |
| ), | |
| equalsDart(r''' | |
| try { | |
| risky(); | |
| } catch (e) { | |
| print(e); | |
| } finally { | |
| cleanup(); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('throws if neither catch nor finally specified', () { | |
| expect(() => Try((b) => b), throwsArgumentError); | |
| }); | |
| }); | |
| group('SwitchStatement', () { | |
| test('basic switch statement', () { | |
| expect( | |
| SwitchStatement( | |
| (b) => b | |
| ..value = refer('value') | |
| ..cases.add( | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(1) | |
| ..body = refer('print').call([literal('one')]).statement, | |
| ), | |
| ) | |
| ..defaultCase = refer('print').call([literal('other')]).statement, | |
| ), | |
| equalsDart(r''' | |
| switch (value) { | |
| case 1: | |
| print('one'); | |
| default: | |
| print('other'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('switch statement with guard and fall-through', () { | |
| expect( | |
| SwitchStatement( | |
| (b) => b | |
| ..value = refer('value') | |
| ..cases.addAll([ | |
| .new((b) => b..pattern = .literal(1)), | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(2) | |
| ..guard = refer('flag') | |
| ..body = refer('print').call([literal('small')]).statement, | |
| ), | |
| ]), | |
| ), | |
| equalsDart(r''' | |
| switch (value) { | |
| case 1: | |
| case 2 when flag: | |
| print('small'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('switch statement with case label and statement label', () { | |
| expect( | |
| SwitchStatement( | |
| (b) => b | |
| ..value = refer('value') | |
| ..label = 'mySwitch' | |
| ..cases.add( | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(1) | |
| ..label = 'caseOne' | |
| ..body = refer('print').call([literal('one')]).statement, | |
| ), | |
| ), | |
| ), | |
| equalsDart(r''' | |
| mySwitch: | |
| switch (value) { | |
| caseOne: | |
| case 1: | |
| print('one'); | |
| } | |
| '''), | |
| ); | |
| }); | |
| }); | |
| group('SwitchExpression', () { | |
| test('basic switch expression', () { | |
| expect( | |
| SwitchExpression( | |
| (b) => b | |
| ..value = refer('value') | |
| ..cases.addAll([ | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(1) | |
| ..body = literal('one'), | |
| ), | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(2) | |
| ..body = literal('two'), | |
| ), | |
| .new( | |
| (b) => b | |
| ..pattern = .wildcard | |
| ..body = literal('other'), | |
| ), | |
| ]), | |
| ), | |
| equalsDart(r''' | |
| switch (value) { | |
| 1 => 'one', | |
| 2 => 'two', | |
| _ => 'other', | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('switch expression with guard', () { | |
| expect( | |
| SwitchExpression( | |
| (b) => b | |
| ..value = refer('value') | |
| ..cases.addAll([ | |
| .new( | |
| (b) => b | |
| ..pattern = .declareVar('x') | |
| ..guard = refer('x').greaterThan(literal(0)) | |
| ..body = literal('positive'), | |
| ), | |
| .new( | |
| (b) => b | |
| ..pattern = .wildcard | |
| ..body = literal('non-positive'), | |
| ), | |
| ]), | |
| ), | |
| equalsDart(r''' | |
| switch (value) { | |
| var x when x > 0 => 'positive', | |
| _ => 'non-positive', | |
| } | |
| '''), | |
| ); | |
| }); | |
| test('switch expression inside assignment', () { | |
| expect( | |
| declareFinal('result') | |
| .assign( | |
| SwitchExpression( | |
| (b) => b | |
| ..value = refer('status') | |
| ..cases.addAll([ | |
| .new( | |
| (b) => b | |
| ..pattern = .literal(200) | |
| ..body = literal('OK'), | |
| ), | |
| .new( | |
| (b) => b | |
| ..pattern = .wildcard | |
| ..body = literal('Error'), | |
| ), | |
| ]), | |
| ), | |
| ) | |
| .statement, | |
| equalsDart(r''' | |
| final result = switch (status) { | |
| 200 => 'OK', | |
| _ => 'Error', | |
| }; | |
| '''), | |
| ); | |
| }); | |
| }); | |
| } |