Skip to content

Commit c04f90a

Browse files
committed
optimize auto infer return and type narrow
1 parent e1da39f commit c04f90a

File tree

5 files changed

+51
-89
lines changed

5 files changed

+51
-89
lines changed

crates/emmylua_code_analysis/src/compilation/analyzer/lua/closure.rs

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
UnResolveClosureParams, UnResolveClosureReturn, UnResolveReturn,
88
},
99
db_index::{LuaDocReturnInfo, LuaSignatureId},
10-
SignatureReturnStatus,
10+
infer_expr, DbIndex, LuaInferCache, LuaMultiReturn, LuaType, SignatureReturnStatus, TypeOps,
1111
};
1212

1313
use super::{func_body::analyze_func_body_returns, LuaAnalyzer, LuaReturnPoint};
@@ -86,19 +86,20 @@ fn analyze_return(
8686

8787
let block = closure.get_block()?;
8888
let return_points = analyze_func_body_returns(block);
89-
let returns = match analyze_return_point(analyzer, &return_points) {
90-
Some(returns) => returns,
91-
None => {
92-
let unresolve = UnResolveReturn {
93-
file_id: analyzer.file_id,
94-
signature_id: signature_id.clone(),
95-
return_points,
96-
};
97-
98-
analyzer.add_unresolved(unresolve.into());
99-
return None;
100-
}
101-
};
89+
let returns =
90+
match analyze_return_point(&analyzer.db, &mut analyzer.infer_cache, &return_points) {
91+
Some(returns) => returns,
92+
None => {
93+
let unresolve = UnResolveReturn {
94+
file_id: analyzer.file_id,
95+
signature_id: signature_id.clone(),
96+
return_points,
97+
};
98+
99+
analyzer.add_unresolved(unresolve.into());
100+
return None;
101+
}
102+
};
102103
let signature = analyzer
103104
.db
104105
.get_signature_index_mut()
@@ -134,43 +135,37 @@ fn analyze_lambda_returns(
134135
Some(())
135136
}
136137

137-
fn analyze_return_point(
138-
analyzer: &mut LuaAnalyzer,
138+
pub fn analyze_return_point(
139+
db: &DbIndex,
140+
cache: &mut LuaInferCache,
139141
return_points: &Vec<LuaReturnPoint>,
140142
) -> Option<Vec<LuaDocReturnInfo>> {
141-
let mut return_infos = Vec::new();
143+
let mut return_type = LuaType::Unknown;
142144
for point in return_points {
143145
match point {
144146
LuaReturnPoint::Expr(expr) => {
145-
let expr_type = analyzer.infer_expr(&expr)?;
146-
if return_infos.is_empty() {
147-
return_infos.push(LuaDocReturnInfo {
148-
name: None,
149-
type_ref: expr_type,
150-
description: None,
151-
});
152-
} else {
153-
// todo merge two type
154-
// let has_return = return_infos[0].type_ref.clone();
155-
return_infos[0].type_ref = expr_type;
156-
}
147+
let expr_type = infer_expr(db, cache, expr.clone())?;
148+
return_type = TypeOps::Union.apply(&return_type, &expr_type);
157149
}
158150
LuaReturnPoint::MuliExpr(exprs) => {
159-
// todo merge type
160-
if return_infos.is_empty() {
161-
for expr in exprs {
162-
let expr_type = analyzer.infer_expr(&expr)?;
163-
return_infos.push(LuaDocReturnInfo {
164-
name: None,
165-
type_ref: expr_type,
166-
description: None,
167-
});
168-
}
151+
let mut multi_return = vec![];
152+
for expr in exprs {
153+
let expr_type = infer_expr(db, cache, expr.clone())?;
154+
multi_return.push(expr_type);
169155
}
156+
let typ = LuaType::MuliReturn(LuaMultiReturn::Multi(multi_return).into());
157+
return_type = TypeOps::Union.apply(&return_type, &typ);
158+
}
159+
LuaReturnPoint::Nil => {
160+
return_type = TypeOps::Union.apply(&return_type, &LuaType::Nil);
170161
}
171162
_ => {}
172163
}
173164
}
174165

175-
Some(return_infos)
166+
Some(vec![LuaDocReturnInfo {
167+
type_ref: return_type,
168+
description: None,
169+
name: None,
170+
}])
176171
}

crates/emmylua_code_analysis/src/compilation/analyzer/lua/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod stats;
66
use std::collections::HashMap;
77

88
use closure::analyze_closure;
9+
pub use closure::analyze_return_point;
910
use emmylua_parser::{LuaAst, LuaAstNode, LuaExpr};
1011
pub use func_body::LuaReturnPoint;
1112
use module::analyze_chunk_return;

crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs

Lines changed: 3 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
compilation::analyzer::lua::LuaReturnPoint,
3-
db_index::{DbIndex, LuaDocReturnInfo, LuaMemberOwner, LuaType},
2+
compilation::analyzer::lua::analyze_return_point,
3+
db_index::{DbIndex, LuaMemberOwner, LuaType},
44
semantic::{infer_expr, LuaInferCache},
55
LuaPropertyOwnerId, SignatureReturnStatus,
66
};
@@ -101,51 +101,7 @@ pub fn try_resolve_return_point(
101101
cache: &mut LuaInferCache,
102102
return_: &UnResolveReturn,
103103
) -> Option<bool> {
104-
let mut is_nullable = false;
105-
let mut return_docs = Vec::new();
106-
for return_point in &return_.return_points {
107-
match return_point {
108-
LuaReturnPoint::Expr(expr) => {
109-
let expr_type = infer_expr(db, cache, expr.clone())?;
110-
if return_docs.is_empty() {
111-
return_docs.push(LuaDocReturnInfo {
112-
name: None,
113-
type_ref: expr_type,
114-
description: None,
115-
});
116-
} else {
117-
let last = return_docs.first_mut()?;
118-
last.type_ref = expr_type;
119-
}
120-
}
121-
LuaReturnPoint::MuliExpr(exprs) => {
122-
if return_docs.is_empty() {
123-
for expr in exprs {
124-
let expr_type = infer_expr(db, cache, expr.clone())?;
125-
126-
return_docs.push(LuaDocReturnInfo {
127-
name: None,
128-
type_ref: expr_type,
129-
description: None,
130-
});
131-
}
132-
}
133-
}
134-
LuaReturnPoint::Nil => {
135-
is_nullable = true;
136-
}
137-
LuaReturnPoint::Error => {}
138-
}
139-
}
140-
141-
if is_nullable {
142-
for doc in &mut return_docs {
143-
if !doc.type_ref.is_nullable() {
144-
doc.type_ref = LuaType::Nullable(doc.type_ref.clone().into());
145-
}
146-
}
147-
}
148-
104+
let return_docs = analyze_return_point(&db, cache, &return_.return_points)?;
149105
let signature = db
150106
.get_signature_index_mut()
151107
.get_mut(&return_.signature_id)?;

crates/emmylua_code_analysis/src/db_index/type/type_ops/narrow_type.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub fn narrow_down_type(source: LuaType, target: LuaType) -> Option<LuaType> {
8888
| LuaType::TableGeneric(_) => return Some(source),
8989
_ => {}
9090
},
91+
LuaType::Instance(base) => return narrow_down_type(source, base.get_base().clone()),
9192
LuaType::Unknown => return Some(source),
9293
_ => {
9394
if target.is_unknown() {
@@ -100,24 +101,26 @@ pub fn narrow_down_type(source: LuaType, target: LuaType) -> Option<LuaType> {
100101

101102
match &source {
102103
LuaType::Union(union) => {
103-
let union_types = union
104+
let mut union_types = union
104105
.get_types()
105106
.iter()
106107
.filter_map(|t| narrow_down_type(t.clone(), target.clone()))
107108
.collect::<Vec<_>>();
108109

110+
union_types.dedup();
109111
return match union_types.len() {
110112
0 => Some(target),
111113
1 => Some(union_types[0].clone()),
112114
_ => Some(LuaType::Union(LuaUnionType::new(union_types).into())),
113115
};
114116
}
115117
LuaType::Nullable(inner) => {
116-
let union_types = vec![LuaType::Nil, (**inner).clone()]
118+
let mut union_types = vec![LuaType::Nil, (**inner).clone()]
117119
.iter()
118120
.filter_map(|t| narrow_down_type(t.clone(), target.clone()))
119121
.collect::<Vec<_>>();
120122

123+
union_types.dedup();
121124
return match union_types.len() {
122125
0 => Some(target),
123126
1 => Some(union_types[0].clone()),

crates/emmylua_code_analysis/src/db_index/type/type_ops/union_type.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ pub fn union_type(source: LuaType, target: LuaType) -> LuaType {
2424
// boolean | boolean const
2525
(LuaType::Boolean, LuaType::BooleanConst(_)) => LuaType::Boolean,
2626
(LuaType::BooleanConst(_), LuaType::Boolean) => LuaType::Boolean,
27+
(LuaType::BooleanConst(left), LuaType::BooleanConst(right)) => {
28+
if left == right {
29+
LuaType::BooleanConst(left.clone())
30+
} else {
31+
LuaType::Boolean
32+
}
33+
}
2734
// table | table const
2835
(LuaType::Table, LuaType::TableConst(_)) => LuaType::Table,
2936
(LuaType::TableConst(_), LuaType::Table) => LuaType::Table,

0 commit comments

Comments
 (0)