Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | 956x 956x 956x 34x 45x 956x 12x 956x 14x 956x 8x 956x 16x 956x 6x 956x 2x 956x 71x 61x 10x 16x 34x 16x 9x | /**
* ChildStatementCollector
*
* Collects child statements and blocks from control flow statements.
* This centralizes recursion patterns to prevent missing nested statements.
*
* Issue #566: Extracted from CodeGenerator for improved testability.
*/
import * as Parser from "../../../logic/parser/grammar/CNextParser.js";
/**
* Result of collecting child statements and blocks from a statement.
*/
interface IChildStatementResult {
statements: Parser.StatementContext[];
blocks: Parser.BlockContext[];
}
class ChildStatementCollector {
/**
* Collect all child statements and blocks from a control flow statement.
* Handles if, while, for, do-while, switch, critical, and nested blocks.
*/
static collectAll(stmt: Parser.StatementContext): IChildStatementResult {
const statements: Parser.StatementContext[] = [];
const blocks: Parser.BlockContext[] = [];
// if statement: has statement() children (can be blocks or single statements)
if (stmt.ifStatement()) {
for (const childStmt of stmt.ifStatement()!.statement()) {
ChildStatementCollector._classifyChildStatement(
childStmt,
statements,
blocks,
);
}
}
// while statement: single statement() child
if (stmt.whileStatement()) {
ChildStatementCollector._classifyChildStatement(
stmt.whileStatement()!.statement(),
statements,
blocks,
);
}
// for statement: single statement() child
if (stmt.forStatement()) {
ChildStatementCollector._classifyChildStatement(
stmt.forStatement()!.statement(),
statements,
blocks,
);
}
// do-while statement: has block() directly
if (stmt.doWhileStatement()) {
blocks.push(stmt.doWhileStatement()!.block());
}
// switch statement: case blocks and optional default block
if (stmt.switchStatement()) {
ChildStatementCollector._collectSwitchChildren(
stmt.switchStatement()!,
blocks,
);
}
// critical statement: has block() directly (ADR-050)
if (stmt.criticalStatement()) {
blocks.push(stmt.criticalStatement()!.block());
}
// Nested block statement
if (stmt.block()) {
blocks.push(stmt.block()!);
}
return { statements, blocks };
}
/**
* Classify a child statement as block or single statement.
* Blocks are pushed to the blocks array, statements to the statements array.
*/
private static _classifyChildStatement(
childStmt: Parser.StatementContext,
statements: Parser.StatementContext[],
blocks: Parser.BlockContext[],
): void {
if (childStmt.block()) {
blocks.push(childStmt.block()!);
} else {
statements.push(childStmt);
}
}
/**
* Collect blocks from switch statement cases and default.
*/
private static _collectSwitchChildren(
switchStmt: Parser.SwitchStatementContext,
blocks: Parser.BlockContext[],
): void {
for (const caseCtx of switchStmt.switchCase()) {
blocks.push(caseCtx.block());
}
if (switchStmt.defaultCase()) {
blocks.push(switchStmt.defaultCase()!.block());
}
}
}
export default ChildStatementCollector;
|