Skip to content

Commit c5fd174

Browse files
committed
Auto-fix: Add support for 'use_if_expressions'
1 parent 4bde512 commit c5fd174

File tree

4 files changed

+83
-9
lines changed

4 files changed

+83
-9
lines changed

lkql_checker/share/lkql/use_if_expressions.lkql

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,45 @@
1+
import stdlib
2+
13
fun simple_return(l) = l != null and l.children_count == 1 and l[1] is ReturnStmt
24
fun simple_assignment(l) =
35
l != null and l.children_count == 1 and l[1] is AssignStmt(f_dest: Name)
46

7+
fun replace_by_expr(if_stmt, ctx) =
8+
|" Replace ``if_stmt`` node by a semantically equivalent node which use an
9+
|" IfExpr to perform the conditional branching.
10+
{
11+
val is_return = simple_return(if_stmt.f_then_stmts);
12+
val then_stmt = if_stmt.f_then_stmts[1];
13+
val else_stmt = if_stmt.f_else_part.f_stmts[1];
14+
val if_expr = new ParenExpr(new IfExpr(
15+
f_cond_expr = if_stmt.f_cond_expr,
16+
f_then_expr = if is_return then then_stmt.f_return_expr else then_stmt.f_expr,
17+
f_else_expr = if is_return then else_stmt.f_return_expr else else_stmt.f_expr,
18+
f_alternatives=new ElsifExprPartList([
19+
{
20+
val stmt = part.f_stmts[1];
21+
new ElsifExprPart(
22+
f_cond_expr = part.f_cond_expr,
23+
f_then_expr = if is_return then stmt.f_return_expr else stmt.f_expr
24+
)
25+
}
26+
for part in if_stmt.f_alternatives.children
27+
].to_list)
28+
));
29+
ctx.replace(
30+
if_stmt,
31+
if is_return
32+
then new ReturnStmt(if_expr)
33+
else new AssignStmt(
34+
f_dest = then_stmt.f_dest,
35+
f_expr = if_expr
36+
)
37+
)
38+
}
39+
540
@check(message="IF statement may be replaced by an IF expression",
6-
category="Style", subcategory="Programming Practice")
41+
category="Style", subcategory="Programming Practice",
42+
auto_fix=replace_by_expr)
743
fun use_if_expressions(node) =
844
|" Flag ``if`` statements which could be replaced by an ``if`` expression.
945
|" This rule detects the following code patterns:
@@ -53,12 +89,14 @@ fun use_if_expressions(node) =
5389
node is IfStmt
5490
when (simple_return(node.f_then_stmts) and
5591
simple_return(node.f_else_part?.f_stmts) and
56-
not [s for s in node.f_alternatives.children
57-
if not simple_return(s.f_stmts)])
92+
stdlib.all([simple_return(s.f_stmts)
93+
for s in node.f_alternatives.children]))
5894
or (simple_assignment(node.f_then_stmts) and
5995
simple_assignment(node.f_else_part?.f_stmts) and
60-
not [s for s in node.f_alternatives.children
61-
if not simple_assignment(s.f_stmts)] and {
62-
val stmts = from node select AssignStmt;
63-
val lhs = stmts[1].f_dest;
64-
not [s for s in stmts if not s.f_dest.p_name_matches(lhs)]})
96+
stdlib.all([simple_assignment(s.f_stmts)
97+
for s in node.f_alternatives.children]) and
98+
{
99+
val stmts = from node select AssignStmt;
100+
val lhs = stmts[1].f_dest;
101+
stdlib.all([s.f_dest.p_name_matches(lhs) for s in stmts])
102+
})

testsuite/tests/checks/use_if_expressions/stmt.adb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ begin
4747

4848
if X > 0 then -- NOFLAG
4949
return 2;
50-
end if:
50+
end if;
5151

5252
return X;
5353
end Stmt;

testsuite/tests/checks/use_if_expressions/test.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,38 @@ stmt.adb:40:4: rule violation: IF statement may be replaced by an IF expression
2525
46 || end if;
2626
||__________^
2727

28+
Patched "stmt.adb":
29+
===================
30+
31+
function Stmt (X : in out Integer) return Integer is
32+
Y : Integer;
33+
begin
34+
return(if X = 1 then 1 else 2);if X = 1 then -- NOFLAG
35+
null;
36+
else
37+
null;
38+
end if;
39+
40+
return(if X = 1 then 1 elsif X = 2 then 2 else 3);if X = 1 then -- NOFLAG
41+
return 1;
42+
elsif X = 2 then
43+
X := 2;
44+
else
45+
return 3;
46+
end if;
47+
48+
if X >= 2 then -- NOFLAG
49+
X := X + 1;
50+
elsif X <= 0 then
51+
Y := X - 1;
52+
else
53+
X := 0;
54+
end if;
55+
56+
X :=(if X >= 2 then X + 1 elsif X <= 0 then X - 1 else 0);if X > 0 then -- NOFLAG
57+
return 2;
58+
end if;
59+
60+
return X;
61+
end Stmt;
62+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
driver: 'checker'
22
rule_name: Use_If_Expressions
33
input_sources: ['stmt.adb']
4+
auto_fix: True

0 commit comments

Comments
 (0)