Skip to content

Commit fe866be

Browse files
committed
refactor-flow
1 parent c10aa11 commit fe866be

File tree

27 files changed

+1155
-1738
lines changed

27 files changed

+1155
-1738
lines changed

crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ use emmylua_parser::{
66
};
77

88
use crate::{
9-
compilation::analyzer::{
10-
bind_type::bind_type, flow::CastAction, unresolve::UnResolveModuleRef,
11-
},
9+
compilation::analyzer::{bind_type::bind_type, unresolve::UnResolveModuleRef},
1210
db_index::{
1311
LuaDeclId, LuaDocParamInfo, LuaDocReturnInfo, LuaMemberId, LuaOperator, LuaSemanticDeclId,
1412
LuaSignatureId, LuaType,
1513
},
16-
InFiled, InferFailReason, LuaOperatorMetaMethod, LuaTypeCache, OperatorFunction,
14+
InFiled, InferFailReason, LuaOperatorMetaMethod, LuaTypeCache, LuaTypeOwner, OperatorFunction,
1715
SignatureReturnStatus, TypeAssertion, TypeOps,
1816
};
1917

@@ -188,6 +186,12 @@ pub fn analyze_return(analyzer: &mut DocAnalyzer, tag: LuaDocTagReturn) -> Optio
188186
Some(())
189187
}
190188

189+
enum CastAction {
190+
Add,
191+
Remove,
192+
Force,
193+
}
194+
191195
pub fn analyze_return_cast(analyzer: &mut DocAnalyzer, tag: LuaDocTagReturnCast) -> Option<()> {
192196
if let Some(LuaSemanticDeclId::Signature(signature_id)) = get_owner_id(analyzer) {
193197
let name_token = tag.get_name_token()?;
@@ -354,13 +358,12 @@ pub fn analyze_cast(analyzer: &mut DocAnalyzer, tag: LuaDocTagCast) -> Option<()
354358
for op in tag.get_op_types() {
355359
if let Some(doc_type) = op.get_type() {
356360
let typ = infer_type(analyzer, doc_type.clone());
357-
analyzer.context.cast_flow.insert(
358-
InFiled {
359-
file_id: analyzer.file_id,
360-
value: doc_type.get_syntax_id(),
361-
},
362-
typ,
363-
);
361+
let type_owner =
362+
LuaTypeOwner::SyntaxId(InFiled::new(analyzer.file_id, doc_type.get_syntax_id()));
363+
analyzer
364+
.db
365+
.get_type_index_mut()
366+
.bind_type(type_owner, LuaTypeCache::DocType(typ));
364367
}
365368
}
366369
Some(())
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use emmylua_parser::{LuaAstNode, LuaComment, LuaDocTag};
2+
3+
use crate::compilation::analyzer::flow::{
4+
binder::FlowBinder,
5+
flow_node::{FlowId, FlowNodeKind},
6+
};
7+
8+
pub fn bind_comment(binder: &mut FlowBinder, lua_comment: LuaComment, current: FlowId) -> FlowId {
9+
let cast_tags = lua_comment.get_doc_tags().filter_map(|it| match it {
10+
LuaDocTag::Cast(cast) => Some(cast),
11+
_ => None,
12+
});
13+
14+
let mut parent = current;
15+
for cast in cast_tags {
16+
let flow_id = binder.create_node(FlowNodeKind::TagCast(cast.to_ptr()));
17+
binder.add_antecedent(flow_id, parent);
18+
parent = flow_id;
19+
}
20+
21+
parent
22+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use emmylua_parser::{
2+
BinaryOperator, LuaAst, LuaAstNode, LuaBinaryExpr, LuaCallExpr, LuaExpr, LuaLiteralExpr, LuaLiteralToken
3+
};
4+
5+
use crate::{
6+
compilation::analyzer::flow::{
7+
bind_analyze::{bind_each_child, exprs::bind_expr},
8+
binder::FlowBinder,
9+
flow_node::{FlowId, FlowNodeKind},
10+
},
11+
LuaType,
12+
};
13+
14+
pub fn bind_binary_expr(
15+
binder: &mut FlowBinder,
16+
binary_expr: LuaBinaryExpr,
17+
current: FlowId,
18+
) -> FlowId {
19+
let Some(op_token) = binary_expr.get_op_token() else {
20+
return current;
21+
};
22+
23+
match op_token.get_op() {
24+
BinaryOperator::OpAnd => bind_and_expr(binder, binary_expr, current),
25+
BinaryOperator::OpOr => bind_or_expr(binder, binary_expr, current),
26+
BinaryOperator::OpEq => bind_eq_expr(binder, binary_expr, current),
27+
BinaryOperator::OpNe => bind_ne_expr(binder, binary_expr, current),
28+
_ => {
29+
bind_each_child(binder, LuaAst::LuaBinaryExpr(binary_expr.clone()), current);
30+
current
31+
}
32+
}
33+
}
34+
35+
fn bind_and_expr(binder: &mut FlowBinder, binary_expr: LuaBinaryExpr, current: FlowId) -> FlowId {
36+
let Some((left, right)) = binary_expr.get_exprs() else {
37+
return current;
38+
};
39+
40+
let left_flow_id = bind_expr(binder, left, current);
41+
let right_flow_id = bind_expr(binder, right, left_flow_id);
42+
right_flow_id
43+
}
44+
45+
fn bind_or_expr(binder: &mut FlowBinder, binary_expr: LuaBinaryExpr, current: FlowId) -> FlowId {
46+
let Some((left, right)) = binary_expr.get_exprs() else {
47+
return current;
48+
};
49+
50+
51+
if let Some(LuaExpr::BinaryExpr(parent_binary)) = binary_expr.get_parent::<LuaExpr>() {
52+
if is_binary_and(parent_binary) {
53+
return bind_and_expr(binder, parent_binary, current);
54+
}
55+
}
56+
57+
58+
current
59+
}
60+
61+
fn is_binary_and(binary_expr: LuaBinaryExpr) -> bool {
62+
let Some(op_token) = binary_expr.get_op_token() else {
63+
return false;
64+
};
65+
66+
match op_token.get_op() {
67+
BinaryOperator::OpAnd => true,
68+
_ => false
69+
}
70+
}
71+
72+
fn bind_and_or_expr(binder: &mut FlowBinder, binary_expr: LuaBinaryExpr, current: FlowId) -> FlowId {
73+
todo!()
74+
}
75+
76+
fn bind_eq_expr(binder: &mut FlowBinder, binary_expr: LuaBinaryExpr, current: FlowId) -> FlowId {
77+
let Some((left, right)) = binary_expr.get_exprs() else {
78+
return current;
79+
};
80+
81+
// if let LuaExpr::CallExpr(call_expr) = &left {
82+
// if call_expr.is_type() {
83+
// if let LuaExpr::LiteralExpr(literal) = &right {
84+
// if let Some(flow_assertion) =
85+
// get_type_guard_assertion(binder, call_expr.clone(), literal.clone(), current)
86+
// {
87+
// let flow_id =
88+
// binder.create_node(FlowNodeKind::Assertion(flow_assertion.into()));
89+
// binder.add_antecedent(flow_id, current);
90+
// return flow_id;
91+
// }
92+
// }
93+
// }
94+
// } else if let LuaExpr::CallExpr(call_expr) = &right {
95+
// if call_expr.is_type() {
96+
// if let LuaExpr::LiteralExpr(literal) = &left {
97+
// if let Some(flow_assertion) =
98+
// get_type_guard_assertion(binder, call_expr.clone(), literal.clone(), current)
99+
// {
100+
// let flow_id =
101+
// binder.create_node(FlowNodeKind::Assertion(flow_assertion.into()));
102+
// binder.add_antecedent(flow_id, current);
103+
// return flow_id;
104+
// }
105+
// }
106+
// }
107+
// }
108+
109+
if let LuaExpr::LiteralExpr(left_literal) = &left {
110+
return bind_eq_literal_expr(binder, right.clone(), left_literal.clone(), current);
111+
} else if let LuaExpr::LiteralExpr(right_literal) = &right {
112+
return bind_eq_literal_expr(binder, left.clone(), right_literal.clone(), current);
113+
}
114+
115+
current
116+
}
117+
118+
fn bind_eq_literal_expr(
119+
binder: &mut FlowBinder,
120+
expr: LuaExpr,
121+
literal_expr: LuaLiteralExpr,
122+
current: FlowId,
123+
) -> FlowId {
124+
let literal_token = match literal_expr.get_literal() {
125+
Some(token) => token,
126+
None => return current,
127+
};
128+
let expr_flow_id = bind_expr(binder, expr, current);
129+
if expr_flow_id == current {
130+
return current;
131+
}
132+
133+
current
134+
}
135+
136+
fn bind_ne_expr(binder: &mut FlowBinder, binary_expr: LuaBinaryExpr, current: FlowId) -> FlowId {
137+
let flow_id = bind_eq_expr(binder, binary_expr, current);
138+
if flow_id == current {
139+
return current;
140+
}
141+
142+
current
143+
}
144+
145+
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
mod bind_binary_expr;
2+
3+
use emmylua_parser::{
4+
LuaAst, LuaAstNode, LuaCallExpr, LuaClosureExpr, LuaExpr, LuaIndexExpr, LuaNameExpr,
5+
LuaTableExpr, LuaUnaryExpr, UnaryOperator,
6+
};
7+
8+
use crate::compilation::analyzer::flow::{
9+
bind_analyze::bind_each_child,
10+
binder::FlowBinder,
11+
flow_node::{FlowId, FlowNodeKind},
12+
};
13+
pub use bind_binary_expr::bind_binary_expr;
14+
15+
pub fn bind_condition_expr(
16+
binder: &mut FlowBinder,
17+
condition_expr: LuaExpr,
18+
current: FlowId,
19+
true_target: FlowId,
20+
false_target: FlowId,
21+
) {
22+
let old_true_target = binder.true_target;
23+
let old_false_target = binder.false_target;
24+
binder.true_target = true_target;
25+
binder.false_target = false_target;
26+
bind_expr(binder, condition_expr.clone(), current);
27+
binder.true_target = old_true_target;
28+
binder.false_target = old_false_target;
29+
30+
let true_condition = binder.create_node(FlowNodeKind::TrueCondition(condition_expr.to_ptr()));
31+
binder.add_antecedent(true_condition, current);
32+
let false_condition = binder.create_node(FlowNodeKind::FalseCondition(condition_expr.to_ptr()));
33+
binder.add_antecedent(false_condition, current);
34+
35+
binder.add_antecedent(true_condition, true_target);
36+
binder.add_antecedent(false_condition, false_target);
37+
}
38+
39+
pub fn bind_expr(binder: &mut FlowBinder, expr: LuaExpr, current: FlowId) -> FlowId {
40+
match expr {
41+
LuaExpr::NameExpr(name_expr) => bind_name_expr(binder, name_expr, current),
42+
LuaExpr::CallExpr(call_expr) => bind_call_expr(binder, call_expr, current),
43+
LuaExpr::TableExpr(table_expr) => bind_table_expr(binder, table_expr, current),
44+
LuaExpr::LiteralExpr(_) => current,
45+
LuaExpr::ClosureExpr(closure_expr) => bind_closure_expr(binder, closure_expr, current),
46+
LuaExpr::ParenExpr(paren_expr) => bind_paren_expr(binder, paren_expr, current),
47+
LuaExpr::IndexExpr(index_expr) => bind_index_expr(binder, index_expr, current),
48+
LuaExpr::BinaryExpr(binary_expr) => bind_binary_expr(binder, binary_expr, current),
49+
LuaExpr::UnaryExpr(unary_expr) => bind_unary_expr(binder, unary_expr, current),
50+
}
51+
}
52+
53+
pub fn bind_name_expr(binder: &mut FlowBinder, name_expr: LuaNameExpr, current: FlowId) -> FlowId {
54+
binder.bind_syntax_node(name_expr.get_syntax_id(), current);
55+
56+
if let Some(parent) = name_expr.get_parent::<LuaExpr>() {
57+
match parent {
58+
LuaExpr::IndexExpr(_) | LuaExpr::CallExpr(_) => {
59+
// If the name is part of an index or call expression, we don't create a true condition
60+
// node here, as it will be handled by the index or call binding.
61+
return current;
62+
}
63+
_ => {}
64+
}
65+
}
66+
let expr = LuaExpr::NameExpr(name_expr.clone());
67+
let true_condition = binder.create_node(FlowNodeKind::TrueCondition(expr.to_ptr()));
68+
binder.add_antecedent(true_condition, current);
69+
true_condition
70+
}
71+
72+
pub fn bind_table_expr(
73+
binder: &mut FlowBinder,
74+
table_expr: LuaTableExpr,
75+
current: FlowId,
76+
) -> FlowId {
77+
bind_each_child(binder, LuaAst::LuaTableExpr(table_expr), current);
78+
current
79+
}
80+
81+
pub fn bind_closure_expr(
82+
binder: &mut FlowBinder,
83+
closure_expr: LuaClosureExpr,
84+
current: FlowId,
85+
) -> FlowId {
86+
bind_each_child(binder, LuaAst::LuaClosureExpr(closure_expr), current);
87+
current
88+
}
89+
90+
pub fn bind_index_expr(
91+
binder: &mut FlowBinder,
92+
index_expr: LuaIndexExpr,
93+
current: FlowId,
94+
) -> FlowId {
95+
bind_each_child(binder, LuaAst::LuaIndexExpr(index_expr.clone()), current);
96+
97+
if let Some(parent) = index_expr.get_parent::<LuaExpr>() {
98+
match parent {
99+
LuaExpr::IndexExpr(_) | LuaExpr::CallExpr(_) => {
100+
// If the name is part of an index or call expression, we don't create a true condition
101+
// node here, as it will be handled by the index or call binding.
102+
return current;
103+
}
104+
_ => {}
105+
}
106+
}
107+
let expr = LuaExpr::IndexExpr(index_expr.clone());
108+
let true_condition = binder.create_node(FlowNodeKind::TrueCondition(expr.to_ptr()));
109+
binder.add_antecedent(true_condition, current);
110+
true_condition
111+
}
112+
113+
pub fn bind_paren_expr(
114+
binder: &mut FlowBinder,
115+
paren_expr: emmylua_parser::LuaParenExpr,
116+
current: FlowId,
117+
) -> FlowId {
118+
let Some(inner_expr) = paren_expr.get_expr() else {
119+
return current;
120+
};
121+
122+
bind_expr(binder, inner_expr, current)
123+
}
124+
125+
pub fn bind_unary_expr(
126+
binder: &mut FlowBinder,
127+
unary_expr: LuaUnaryExpr,
128+
current: FlowId,
129+
) -> FlowId {
130+
let Some(inner_expr) = unary_expr.get_expr() else {
131+
return current;
132+
};
133+
let inner_flow = bind_expr(binder, inner_expr, current);
134+
135+
let Some(op) = unary_expr.get_op_token() else {
136+
return current;
137+
};
138+
match op.get_op() {
139+
UnaryOperator::OpNot => {
140+
// If it's a not operator, we create a false condition node
141+
if let Some(flow_node) = binder.get_flow(inner_flow) {
142+
if flow_node.kind.is_conditional() {
143+
// If the inner flow is already a conditional, we can just negate it
144+
let Some(negated_condition) = flow_node.kind.get_negation_condition() else {
145+
return current;
146+
};
147+
148+
let negated_flow = binder.create_node(negated_condition);
149+
binder.add_antecedent(negated_flow, current);
150+
return negated_flow;
151+
}
152+
}
153+
}
154+
_ => {}
155+
}
156+
157+
current
158+
}
159+
160+
pub fn bind_call_expr(binder: &mut FlowBinder, call_expr: LuaCallExpr, current: FlowId) -> FlowId {
161+
bind_each_child(binder, LuaAst::LuaCallExpr(call_expr.clone()), current);
162+
163+
if let Some(parent) = call_expr.get_parent::<LuaExpr>() {
164+
match parent {
165+
LuaExpr::IndexExpr(_) | LuaExpr::CallExpr(_) => {
166+
// If the name is part of an index or call expression, we don't create a true condition
167+
// node here, as it will be handled by the index or call binding.
168+
return current;
169+
}
170+
_ => {}
171+
}
172+
}
173+
let expr = LuaExpr::CallExpr(call_expr.clone());
174+
let true_condition = binder.create_node(FlowNodeKind::TrueCondition(expr.to_ptr()));
175+
binder.add_antecedent(true_condition, current);
176+
true_condition
177+
}

0 commit comments

Comments
 (0)