Skip to content

Commit ed52f80

Browse files
committed
refactor: update old usages of cfg.
1 parent 5cc9c44 commit ed52f80

File tree

37 files changed

+132
-163
lines changed

37 files changed

+132
-163
lines changed

crates/oxc_linter/src/rules/eslint/getter_return.rs

+18-38
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use oxc_diagnostics::OxcDiagnostic;
99

1010
use oxc_macros::declare_oxc_lint;
1111
use oxc_semantic::{
12-
pg::neighbors_filtered_by_edge_weight, AssignmentValue, BasicBlockElement, EdgeType, Register,
12+
pg::neighbors_filtered_by_edge_weight, EdgeType, InstructionKind, ReturnInstructionKind,
1313
};
1414
use oxc_span::Span;
1515

@@ -229,49 +229,28 @@ impl GetterReturn {
229229
}
230230

231231
// Scan through the values in this basic block.
232-
for entry in cfg.basic_block(*basic_block_id) {
233-
match entry {
234-
// If the element is an assignment.
235-
//
236-
// Everything you can write in javascript that would have
237-
// the function continue are expressed as assignments in the cfg.
238-
BasicBlockElement::Assignment(to_reg, val) => {
239-
// If the assignment is to the return register.
240-
//
241-
// The return register is a special register that return statements
242-
// assign the returned value to.
243-
if matches!(to_reg, Register::Return) {
232+
for entry in cfg.basic_block(*basic_block_id).instructions() {
233+
match entry.kind {
234+
// If the element is a return.
244235
// `allow_implicit` allows returning without a value to not
245-
// fail the rule. We check for this by checking if the value
246-
// being returned in the cfg this is expressed as
247-
// `AssignmentValue::ImplicitUndefined`.
248-
//
249-
// There is an assumption being made here that returning an
250-
// `undefined` will put the `undefined` directly into the
251-
// return and will not put the `undefined` into an immediate
252-
// register and return the register. However, the tests for
253-
// this rule enforce that this invariant is not broken.
254-
if !self.allow_implicit
255-
&& matches!(val, AssignmentValue::ImplicitUndefined)
256-
{
257-
// Return false as the second argument to signify we should
258-
// not continue walking this branch, as we know a return
259-
// is the end of this path.
260-
return (DefinitelyReturnsOrThrowsOrUnreachable::No, false);
261-
}
236+
// fail the rule.
237+
// Return false as the second argument to signify we should
238+
// not continue walking this branch, as we know a return
239+
// is the end of this path.
240+
InstructionKind::Return(ReturnInstructionKind::ImplicitUndefined) if !self.allow_implicit => {
241+
return (DefinitelyReturnsOrThrowsOrUnreachable::No, false);
242+
}
262243
// Otherwise, we definitely returned since we assigned
263244
// to the return register.
264245
//
265246
// Return false as the second argument to signify we should
266247
// not continue walking this branch, as we know a return
267248
// is the end of this path.
268-
return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false);
269-
}
270-
}
249+
| InstructionKind::Return(_)
271250
// Throws are classified as returning.
272251
//
273252
// todo: test with catching...
274-
BasicBlockElement::Throw(_) |
253+
| InstructionKind::Throw
275254
// Although the unreachable code is not returned, it will never be executed.
276255
// There is no point in checking it for return.
277256
//
@@ -283,12 +262,13 @@ impl GetterReturn {
283262
// return -1;
284263
// ```
285264
// Make return useless.
286-
BasicBlockElement::Unreachable => {
287-
288-
return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false);
265+
| InstructionKind::Unreachable =>{
266+
return (DefinitelyReturnsOrThrowsOrUnreachable::Yes, false);
289267
}
290268
// Ignore irrelevant elements.
291-
BasicBlockElement::Break(_) => {}
269+
| InstructionKind::Break
270+
| InstructionKind::Statement
271+
| InstructionKind::Jump { .. } => {}
292272
}
293273
}
294274

crates/oxc_linter/src/rules/react/require_render_return.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use oxc_diagnostics::OxcDiagnostic;
33

44
use oxc_macros::declare_oxc_lint;
55
use oxc_semantic::{
6-
pg::neighbors_filtered_by_edge_weight, AssignmentValue, BasicBlockElement, EdgeType, Register,
6+
pg::neighbors_filtered_by_edge_weight, EdgeType, InstructionKind, ReturnInstructionKind,
77
};
88
use oxc_span::{GetSpan, Span};
99

@@ -109,15 +109,11 @@ fn contains_return_statement<'a>(node: &AstNode<'a>, ctx: &LintContext<'a>) -> b
109109
}
110110
}
111111

112-
for entry in cfg.basic_block(*basic_block_id) {
113-
if let BasicBlockElement::Assignment(to_reg, val) = entry {
114-
if matches!(to_reg, Register::Return)
115-
&& matches!(val, AssignmentValue::NotImplicitUndefined)
116-
{
117-
return (FoundReturn::Yes, STOP_WALKING_ON_THIS_PATH);
118-
}
119-
} else {
120-
// We don't care about other types of instructions.
112+
for entry in cfg.basic_block(*basic_block_id).instructions() {
113+
if let InstructionKind::Return(ReturnInstructionKind::NotImplicitUndefined) =
114+
entry.kind
115+
{
116+
return (FoundReturn::Yes, STOP_WALKING_ON_THIS_PATH);
121117
}
122118
}
123119

crates/oxc_linter/src/rules/react/rules_of_hooks.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use oxc_macros::declare_oxc_lint;
77
use oxc_semantic::{
88
petgraph::{self},
99
pg::neighbors_filtered_by_edge_weight,
10-
AstNodeId, AstNodes, BasicBlockElement, BasicBlockId, EdgeType, Register,
10+
AstNodeId, AstNodes, BasicBlockId, EdgeType, Instruction, InstructionKind,
1111
};
1212
use oxc_span::{Atom, CompactStr};
1313
use oxc_syntax::operator::AssignmentOperator;
@@ -314,15 +314,16 @@ impl RulesOfHooks {
314314

315315
let (push, keep_walking) = cfg
316316
.basic_block(*id)
317+
.instructions
317318
.iter()
318-
.fold_while((false, true), |acc, it| match it {
319-
BasicBlockElement::Break(_) => FoldWhile::Done((true, false)),
320-
BasicBlockElement::Unreachable
321-
| BasicBlockElement::Throw(_)
322-
| BasicBlockElement::Assignment(Register::Return, _) => {
323-
FoldWhile::Continue((acc.0, false))
319+
.fold_while((false, true), |acc, Instruction { kind, .. }| match kind {
320+
InstructionKind::Break => FoldWhile::Done((true, false)),
321+
InstructionKind::Unreachable
322+
| InstructionKind::Throw
323+
| InstructionKind::Return(_) => FoldWhile::Continue((acc.0, false)),
324+
InstructionKind::Jump { .. } | InstructionKind::Statement => {
325+
FoldWhile::Continue(acc)
324326
}
325-
BasicBlockElement::Assignment(_, _) => FoldWhile::Continue(acc),
326327
})
327328
.into_inner();
328329

crates/oxc_semantic/src/builder.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{
1818
class::ClassTableBuilder,
1919
control_flow::{
2020
ControlFlowGraphBuilder, EdgeType, Instruction, InstructionKind, Register,
21-
StatementControlFlowType,
21+
ReturnInstructionKind, StatementControlFlowType,
2222
},
2323
diagnostics::redeclaration,
2424
jsdoc::JSDocBuilder,
@@ -1150,11 +1150,20 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
11501150

11511151
if let Some(arg) = &stmt.argument {
11521152
self.visit_expression(arg);
1153-
}
1154-
1155-
/* cfg */
1156-
self.cfg.push_instruction(Instruction::new(InstructionKind::Return, Some(node_id)));
1153+
/* cfg */
1154+
self.cfg.push_instruction(Instruction::new(
1155+
InstructionKind::Return(ReturnInstructionKind::NotImplicitUndefined),
1156+
Some(node_id),
1157+
));
11571158
/* cfg */
1159+
} else {
1160+
/* cfg */
1161+
self.cfg.push_instruction(Instruction::new(
1162+
InstructionKind::Return(ReturnInstructionKind::ImplicitUndefined),
1163+
Some(node_id),
1164+
));
1165+
/* cfg */
1166+
}
11581167

11591168
/* cfg - put unreachable after return */
11601169
let _ = self.cfg.new_basic_block();

crates/oxc_semantic/src/control_flow/builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ impl ControlFlowGraphBuilder {
102102
}
103103

104104
pub fn put_break(&mut self, label: Option<AstNodeId>) {
105-
todo!("{:?}", label);
106-
// self.push_instruction(Instruction { kind: InstructionKind::Break, node_id: label });
105+
self.push_instruction(Instruction { kind: InstructionKind::Break, node_id: label });
106+
// todo!("{:?}", label);
107107
// self.current_basic_block().push(BasicBlockElement::Break(label));
108108
}
109109

crates/oxc_semantic/src/control_flow/mod.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ impl BasicBlock {
116116
fn new() -> Self {
117117
BasicBlock { instructions: Vec::new() }
118118
}
119+
120+
pub fn instructions(&self) -> &Vec<Instruction> {
121+
&self.instructions
122+
}
119123
}
120124

121125
#[derive(Debug, Clone)]
@@ -135,8 +139,15 @@ pub enum InstructionKind {
135139
Unreachable,
136140
Statement,
137141
Jump { conditional: bool, block: BasicBlockId },
138-
Return,
142+
Return(ReturnInstructionKind),
139143
Throw,
144+
Break,
145+
}
146+
147+
#[derive(Debug, Clone)]
148+
pub enum ReturnInstructionKind {
149+
ImplicitUndefined,
150+
NotImplicitUndefined,
140151
}
141152

142153
#[derive(Debug, Clone)]
@@ -189,40 +200,23 @@ pub struct PreservedExpressionState {
189200
}
190201

191202
#[must_use]
192-
fn print_register(register: Register) -> String {
193-
match &register {
194-
Register::Index(i) => format!("${i}"),
195-
Register::Return => "$return".into(),
196-
}
197-
}
198-
199-
#[must_use]
200-
pub fn print_basic_block(basic_block_elements: &Vec<BasicBlockElement>) -> String {
203+
pub fn print_basic_block(basic_block: &BasicBlock) -> String {
201204
let mut output = String::new();
202-
for basic_block in basic_block_elements {
203-
match basic_block {
204-
BasicBlockElement::Unreachable => output.push_str("Unreachable()\n"),
205-
BasicBlockElement::Throw(reg) => {
206-
output.push_str(&format!("throw {}\n", print_register(*reg)));
205+
for instruction in basic_block.instructions() {
206+
match instruction.kind {
207+
InstructionKind::Statement => output.push_str("statement\n"),
208+
InstructionKind::Unreachable => output.push_str("Unreachable()\n"),
209+
InstructionKind::Throw => output.push_str("throw\n"),
210+
InstructionKind::Break => output.push_str("break\n"),
211+
InstructionKind::Return(ReturnInstructionKind::ImplicitUndefined) => {
212+
output.push_str("return <implicit undefined>\n");
207213
}
208-
209-
BasicBlockElement::Break(Some(reg)) => {
210-
output.push_str(&format!("break {}\n", print_register(*reg)));
211-
}
212-
BasicBlockElement::Break(None) => {
213-
output.push_str("break");
214+
InstructionKind::Return(ReturnInstructionKind::NotImplicitUndefined) => {
215+
output.push_str("return <value>\n");
214216
}
215-
BasicBlockElement::Assignment(to, with) => {
216-
output.push_str(&format!("{} = ", print_register(*to)));
217-
218-
match with {
219-
AssignmentValue::ImplicitUndefined => {
220-
output.push_str("<implicit undefined>");
221-
}
222-
AssignmentValue::NotImplicitUndefined => output.push_str("<value>"),
223-
}
224-
225-
output.push('\n');
217+
#[allow(clippy::todo)]
218+
InstructionKind::Jump { .. } => {
219+
todo!("We haven't switched to use jumps yet");
226220
}
227221
}
228222
}

crates/oxc_semantic/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ use rustc_hash::FxHashSet;
3131

3232
pub use crate::{
3333
control_flow::{
34-
print_basic_block, AssignmentValue, BasicBlockElement, BasicBlockId, BinaryAssignmentValue,
35-
BinaryOp, CallType, CalleeWithArgumentsAssignmentValue, CollectionAssignmentValue,
36-
ControlFlowGraph, EdgeType, Instruction, InstructionKind,
37-
ObjectPropertyAccessAssignmentValue, Register, UnaryExpressioneAssignmentValue,
38-
UpdateAssignmentValue,
34+
print_basic_block, AssignmentValue, BasicBlock, BasicBlockElement, BasicBlockId,
35+
BinaryAssignmentValue, BinaryOp, CallType, CalleeWithArgumentsAssignmentValue,
36+
CollectionAssignmentValue, ControlFlowGraph, EdgeType, Instruction, InstructionKind,
37+
ObjectPropertyAccessAssignmentValue, Register, ReturnInstructionKind,
38+
UnaryExpressioneAssignmentValue, UpdateAssignmentValue,
3939
},
4040
node::{AstNode, AstNodeId, AstNodes},
4141
reference::{Reference, ReferenceFlag, ReferenceId},

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js-2.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/break_from_a_label_in_global_
55
---
66
digraph {
77
0 [ label = ""]
8-
1 [ label = "Unreachable()\nbreak $0"]
8+
1 [ label = "Unreachable()\nbreak"]
99
0 -> 1 [ ]
1010
0 -> 1 [ ]
1111
}

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@break_from_a_label_in_global_scope.js.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ bb0: {
99

1010
bb1: {
1111
Unreachable()
12-
break $0
12+
break
1313
}

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js-2.snap

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/class_extend_super.js
55
---
66
digraph {
77
0 [ label = ""]
8-
1 [ label = "$return = <value>"]
8+
1 [ label = "return <value>"]
99
2 [ label = ""]
1010
3 [ label = "Unreachable()"]
1111
4 [ label = ""]
1212
0 -> 1 [ ]
1313
2 -> 3 [ ]
1414
0 -> 4 [ ]
1515
}
16-

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@class_extend_super.js.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ bb0: {
88
}
99

1010
bb1: {
11-
$return = <value>
11+
return <value>
1212
}
1313

1414
bb2: {

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js-2.snap

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ input_file: crates/oxc_semantic/tests/cfg_fixtures/fn_return_obj_expr_with_compu
55
---
66
digraph {
77
0 [ label = ""]
8-
1 [ label = "$return = <value>"]
8+
1 [ label = "return <value>"]
99
2 [ label = ""]
1010
3 [ label = "Unreachable()"]
1111
4 [ label = ""]
1212
0 -> 1 [ ]
1313
2 -> 3 [ ]
1414
0 -> 4 [ ]
1515
}
16-

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@fn_return_obj_expr_with_computed_key.js.snap

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ bb0: {
88
}
99

1010
bb1: {
11-
$return = <value>
11+
return <value>
1212
}
1313

1414
bb2: {

crates/oxc_semantic/tests/snapshots/cfg__cfg_files@if_else.js-2.snap

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ digraph {
88
1 [ label = ""]
99
2 [ label = ""]
1010
3 [ label = ""]
11-
4 [ label = "$return = <value>"]
11+
4 [ label = "return <value>"]
1212
5 [ label = ""]
1313
6 [ label = "Unreachable()"]
14-
7 [ label = "$return = <value>"]
14+
7 [ label = "return <value>"]
1515
8 [ label = ""]
1616
9 [ label = "Unreachable()"]
1717
10 [ label = ""]
18-
11 [ label = "Unreachable()\n$return = <value>"]
18+
11 [ label = "Unreachable()\nreturn <value>"]
1919
12 [ label = ""]
2020
13 [ label = "Unreachable()"]
2121
14 [ label = ""]
@@ -33,4 +33,3 @@ digraph {
3333
12 -> 13 [ ]
3434
0 -> 14 [ ]
3535
}
36-

0 commit comments

Comments
 (0)