mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
Add createJavaCfgVisitor + java-harvest over the shared CfgBuilder / ControlFlowContext: if/else, classic for, enhanced-for, while, do-while, classic-vs-arrow switch (switch_block_statement_group fallthrough vs switch_rule no-fallthrough), try/catch/finally + try-with-resources (auto-close synthesized as a finalizer, closes on normal AND exception exit) + synchronized (monitor-release finalizer), labeled break/continue to the labeled frame, yield, return/throw/break/continue. Wire into javaProvider. Every literal validated against tree-sitter-java via the probe (switch_expression covers both switch forms, generic_type, line_comment, for init field). Edge kinds match the contract; functionStartColumn populated; while(true)/for(;;) keep EXIT reverse-reachable (production CDG probe: 3 edges; hazard fixture: 34 CDG edges). buildFunctionCfg returns undefined rather than throwing. 43 real-parser regression tests; grammar-literal gate green; no regression (cfg unit suite 304, tsc clean). Documented gaps: switch-as- expression-value inline, yield state machine, async/field-write defs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
149 lines
3.3 KiB
Java
149 lines
3.3 KiB
Java
// Java CFG hazard fixture (#2195 U4). Each method exercises one control-flow
|
|
// construct the Java CfgVisitor models; the worker-mode pipeline + snapshot
|
|
// tests assert non-trivial BasicBlock / CFG / REACHING_DEF / CDG output here.
|
|
package fixtures;
|
|
|
|
import java.io.IOException;
|
|
|
|
class Hazards {
|
|
|
|
// if / else — cond-true / cond-false to both arms, joining after.
|
|
int branch(int x) {
|
|
int r;
|
|
if (x > 0) {
|
|
r = 1;
|
|
} else {
|
|
r = 2;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
// classic C-style for — init once, condition header, back-edge through update.
|
|
int classicFor(int n) {
|
|
int sum = 0;
|
|
for (int i = 0; i < n; i++) {
|
|
sum += i;
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
// enhanced for (for-each) — loop var def, iterated value use.
|
|
int forEach(int[] xs) {
|
|
int total = 0;
|
|
for (int v : xs) {
|
|
total += v;
|
|
}
|
|
return total;
|
|
}
|
|
|
|
// while — bottom-of-header re-test, back-edge.
|
|
int whileLoop(int x) {
|
|
while (x > 0) {
|
|
x = step(x);
|
|
}
|
|
return x;
|
|
}
|
|
|
|
// do-while — body runs before the test.
|
|
int doWhile(int x) {
|
|
do {
|
|
x = step(x);
|
|
} while (x > 0);
|
|
return x;
|
|
}
|
|
|
|
// try-with-resources — the resource closes on BOTH normal and exception exit
|
|
// (finally semantics); a return inside crosses the close (finally-return).
|
|
int withResources(String path) throws IOException {
|
|
try (var r = open(path)) {
|
|
return read(r);
|
|
} catch (IOException e) {
|
|
return handle(e);
|
|
} finally {
|
|
cleanup();
|
|
}
|
|
}
|
|
|
|
// labeled break — `break outer;` from a nested loop targets the labeled frame.
|
|
int labeledBreak(int[][] grid, int needle) {
|
|
int found = -1;
|
|
outer:
|
|
for (int i = 0; i < grid.length; i++) {
|
|
for (int j = 0; j < grid[i].length; j++) {
|
|
if (grid[i][j] == needle) {
|
|
found = i;
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
// classic colon switch — fallthrough between break-less cases; the case test
|
|
// is recorded as a may-def on the dispatch block.
|
|
int classicSwitch(int x) {
|
|
int r = 0;
|
|
switch (x) {
|
|
case 1:
|
|
case 2:
|
|
r = 10;
|
|
break;
|
|
case 3:
|
|
r = 30;
|
|
default:
|
|
r = -1;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
// arrow switch — each rule rejoins after the switch (no fallthrough).
|
|
int arrowSwitch(int x) {
|
|
int r = 0;
|
|
switch (x) {
|
|
case 1 -> r = 1;
|
|
case 2, 3 -> r = 2;
|
|
default -> r = -1;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
// switch expression with yield — yields a value to the enclosing switch.
|
|
int yieldSwitch(int x) {
|
|
int r = switch (x) {
|
|
case 1 -> 10;
|
|
default -> {
|
|
yield 20;
|
|
}
|
|
};
|
|
return r;
|
|
}
|
|
|
|
// synchronized — the monitor release is a deterministic finalizer.
|
|
void sync(Object lock) {
|
|
synchronized (lock) {
|
|
touch();
|
|
}
|
|
after();
|
|
}
|
|
|
|
// a server-style non-terminating loop — EXIT must stay reverse-reachable so
|
|
// CDG is not silently skipped for the method.
|
|
void serve() {
|
|
while (true) {
|
|
if (ready()) {
|
|
handle();
|
|
}
|
|
}
|
|
}
|
|
|
|
// helpers (no bodies of interest)
|
|
int step(int x) { return x - 1; }
|
|
Object open(String p) { return null; }
|
|
int read(Object r) { return 0; }
|
|
int handle(IOException e) { return 0; }
|
|
void cleanup() {}
|
|
void touch() {}
|
|
void after() {}
|
|
boolean ready() { return false; }
|
|
void handle() {}
|
|
}
|