Skip to content

Commit 9ee149a

Browse files
committed
optimize type check performance
1 parent ed99caa commit 9ee149a

File tree

13 files changed

+70
-50
lines changed

13 files changed

+70
-50
lines changed

crates/emmylua_code_analysis/src/diagnostic/checker/assign_type_mismatch.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ fn check_assign_stat(
3838
) -> Option<()> {
3939
let (vars, exprs) = assign.get_var_and_expr_list();
4040
let value_types =
41-
semantic_model.infer_multi_value_adjusted_expression_types(&exprs, Some(vars.len()))?;
41+
semantic_model.infer_multi_value_adjusted_expression_types(&exprs, Some(vars.len()));
4242

4343
for (idx, var) in vars.iter().enumerate() {
4444
match var {
@@ -113,6 +113,7 @@ fn check_name_expr(
113113
if let Some(expr) = expr {
114114
handle_value_is_table_expr(context, semantic_model, origin_type, &expr);
115115
}
116+
116117
Some(())
117118
}
118119

@@ -169,8 +170,8 @@ fn check_local_stat(
169170
) -> Option<()> {
170171
let vars = local.get_local_name_list().collect::<Vec<_>>();
171172
let value_exprs = local.get_value_exprs().collect::<Vec<_>>();
172-
let value_types = semantic_model
173-
.infer_multi_value_adjusted_expression_types(&value_exprs, Some(vars.len()))?;
173+
let value_types =
174+
semantic_model.infer_multi_value_adjusted_expression_types(&value_exprs, Some(vars.len()));
174175

175176
for (idx, var) in vars.iter().enumerate() {
176177
let name_token = var.get_name_token()?;
@@ -208,20 +209,29 @@ fn handle_value_is_table_expr(
208209
value_expr: &LuaExpr,
209210
) -> Option<()> {
210211
let table_type = table_type?;
211-
let member_infos = semantic_model.infer_member_infos(&table_type)?;
212-
let fields = LuaTableExpr::cast(value_expr.syntax().clone())?.get_fields();
212+
let fields = LuaTableExpr::cast(value_expr.syntax().clone())?
213+
.get_fields()
214+
.collect::<Vec<_>>();
215+
if fields.len() > 50 {
216+
// 如果字段过多, 则不进行类型检查
217+
return Some(());
218+
}
219+
213220
for field in fields {
214221
if field.is_value_field() {
215222
continue;
216223
}
217224

218225
let field_key = field.get_field_key();
219226
if let Some(field_key) = field_key {
220-
let field_path_part = field_key.get_path_part();
221-
let source_type = member_infos
222-
.iter()
223-
.find(|info| info.key.to_path() == field_path_part)
224-
.map(|info| info.typ.clone());
227+
let member_key = semantic_model.get_member_key(&field_key)?;
228+
let source_type = match semantic_model.infer_member_type(&table_type, &member_key) {
229+
Ok(typ) => Some(typ),
230+
Err(_) => {
231+
continue;
232+
}
233+
};
234+
225235
let expr = field.get_value_expr();
226236
if let Some(expr) = expr {
227237
let expr_type = semantic_model.infer_expr(expr).unwrap_or(LuaType::Any);

crates/emmylua_code_analysis/src/diagnostic/checker/check_field.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ fn is_valid_member(
207207

208208
let prefix_types = get_prefix_types(prefix_typ);
209209
for prefix_type in prefix_types {
210-
if let Some(members) = semantic_model.infer_member_infos(&prefix_type) {
210+
if let Some(members) = semantic_model.get_member_infos(&prefix_type) {
211211
for info in &members {
212212
match &info.key {
213213
LuaMemberKey::Expr(typ) => {

crates/emmylua_code_analysis/src/diagnostic/checker/duplicate_index.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ fn check_table_duplicate_index(
2424
_: &SemanticModel,
2525
table: LuaTableExpr,
2626
) -> Option<()> {
27-
let fields = table.get_fields();
27+
let fields = table.get_fields().collect::<Vec<_>>();
28+
if fields.len() > 50 {
29+
// Skip checking if there are too many fields to avoid performance issues
30+
return Some(());
31+
}
32+
2833
let mut index_map: HashMap<String, Vec<LuaIndexKey>> = HashMap::new();
2934

3035
for field in fields {
3136
let key = field.get_field_key();
3237
if let Some(key) = key {
3338
index_map
34-
.entry(key.get_path_part().to_string())
39+
.entry(key.get_path_part())
3540
.or_insert_with(Vec::new)
3641
.push(key);
3742
}

crates/emmylua_code_analysis/src/diagnostic/checker/param_type_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fn check_call_expr(
3939
let mut params = func.get_params().to_vec();
4040
let arg_exprs: Vec<LuaExpr> = call_expr.get_args_list()?.get_args().collect::<Vec<_>>();
4141
let (mut arg_types, mut arg_ranges) = {
42-
let infos = semantic_model.infer_multi_value_adjusted_expression_types(&arg_exprs, None)?;
42+
let infos = semantic_model.infer_multi_value_adjusted_expression_types(&arg_exprs, None);
4343
let arg_types = infos.iter().map(|(typ, _)| typ.clone()).collect::<Vec<_>>();
4444
let arg_ranges = infos
4545
.iter()

crates/emmylua_code_analysis/src/diagnostic/checker/return_type_mismatch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ fn check_return_stat(
5858
let infos = semantic_model.infer_multi_value_adjusted_expression_types(
5959
&return_stat.get_expr_list().collect::<Vec<_>>(),
6060
None,
61-
)?;
61+
);
6262
let mut return_expr_types = infos.iter().map(|(typ, _)| typ.clone()).collect::<Vec<_>>();
6363
// 解决 setmetatable 的返回值类型问题
6464
let setmetatable_index = has_setmetatable(semantic_model, return_stat);

crates/emmylua_code_analysis/src/diagnostic/checker/unbalanced_assignments.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ fn check_unbalanced_assignment(
5959
return Some(());
6060
}
6161

62-
let value_types = semantic_model
63-
.infer_multi_value_adjusted_expression_types(value_exprs, Some(vars.len()))?;
62+
let value_types =
63+
semantic_model.infer_multi_value_adjusted_expression_types(value_exprs, Some(vars.len()));
6464
if let Some(last_type) = value_types.last() {
6565
if check_last(&last_type.0) {
6666
return Some(());

crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,14 @@ fn infer_member_type_pass_flow(
7777
return Ok(member_type.clone());
7878
}
7979
LuaType::Ref(decl_id) => {
80-
if let Some(members) = db
81-
.get_member_index()
82-
.get_members(&LuaMemberOwner::Type(decl_id.clone()))
80+
let index_key = index_expr.get_index_key().ok_or(InferFailReason::None)?;
81+
let key = LuaMemberKey::from_index_key(db, cache, &index_key)?;
82+
let member_index = db.get_member_index();
83+
if member_index
84+
.get_member_item(&LuaMemberOwner::Type(decl_id.clone()), &key)
85+
.is_some()
8386
{
84-
if let Some(key) = index_expr.get_index_key() {
85-
if let Some(_) = members
86-
.iter()
87-
.find(|m| m.get_key().to_path() == key.get_path_part())
88-
{
89-
allow_reassign = false
90-
}
91-
}
87+
allow_reassign = false;
9288
}
9389
}
9490
_ => {}

crates/emmylua_code_analysis/src/semantic/infer/mod.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ use smol_str::SmolStr;
2929

3030
use crate::{
3131
db_index::{DbIndex, LuaOperator, LuaOperatorMetaMethod, LuaSignatureId, LuaType},
32-
InFiled, VariadicType,
32+
InFiled, LuaMemberKey, VariadicType,
3333
};
3434

35-
use super::{member::find_members, CacheEntry, CacheKey, LuaInferCache};
35+
use super::{member::infer_raw_member_type, CacheEntry, CacheKey, LuaInferCache};
3636

3737
pub type InferResult = Result<LuaType, InferFailReason>;
3838
pub use infer_call::InferCallFuncResult;
@@ -175,24 +175,24 @@ pub fn infer_multi_value_adjusted_expression_types(
175175
cache: &mut LuaInferCache,
176176
exprs: &[LuaExpr],
177177
var_count: Option<usize>,
178-
) -> Option<Vec<(LuaType, TextRange)>> {
178+
) -> Vec<(LuaType, TextRange)> {
179179
let mut value_types = Vec::new();
180180
for (idx, expr) in exprs.iter().enumerate() {
181-
let expr_type = infer_expr(db, cache, expr.clone()).ok()?;
181+
let expr_type = infer_expr(db, cache, expr.clone()).unwrap_or(LuaType::Unknown);
182182
match expr_type {
183-
LuaType::Variadic(multi) => {
183+
LuaType::Variadic(variadic) => {
184184
if let Some(var_count) = var_count {
185185
if idx < var_count {
186186
for i in idx..var_count {
187-
if let Some(typ) = multi.get_type(i - idx) {
187+
if let Some(typ) = variadic.get_type(i - idx) {
188188
value_types.push((typ.clone(), expr.get_range()));
189189
} else {
190190
break;
191191
}
192192
}
193193
}
194194
} else {
195-
match multi.deref() {
195+
match variadic.deref() {
196196
VariadicType::Base(base) => {
197197
value_types.push((base.clone(), expr.get_range()));
198198
}
@@ -210,7 +210,7 @@ pub fn infer_multi_value_adjusted_expression_types(
210210
}
211211
}
212212

213-
Some(value_types)
213+
value_types
214214
}
215215

216216
/// 从右值推断左值已绑定的类型
@@ -254,14 +254,15 @@ pub fn infer_left_value_type_from_right_value(
254254
let field_key = table_field.get_field_key()?;
255255
let table_expr = table_field.get_parent::<LuaTableExpr>()?;
256256
let table_type = infer_table_should_be(db, cache, table_expr.clone()).ok()?;
257-
let member_infos = find_members(db, &table_type)?;
258-
let mut typ = None;
259-
for member_info in member_infos.iter() {
260-
if member_info.key.to_path() == field_key.get_path_part() {
261-
typ = Some(member_info.typ.clone());
262-
}
257+
let member_key = match LuaMemberKey::from_index_key(db, cache, &field_key) {
258+
Ok(key) => key,
259+
Err(_) => return None,
260+
};
261+
match infer_raw_member_type(db, &table_type, &member_key) {
262+
Ok(typ) => Some(typ),
263+
Err(InferFailReason::FieldNotFound) => None,
264+
Err(_) => Some(LuaType::Unknown),
263265
}
264-
typ
265266
}
266267
_ => None,
267268
};

crates/emmylua_code_analysis/src/semantic/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ impl<'a> SemanticModel<'a> {
111111
infer_table_should_be(self.db, &mut self.infer_cache.borrow_mut(), table).ok()
112112
}
113113

114-
pub fn infer_member_infos(&self, prefix_type: &LuaType) -> Option<Vec<LuaMemberInfo>> {
114+
pub fn get_member_infos(&self, prefix_type: &LuaType) -> Option<Vec<LuaMemberInfo>> {
115115
find_members(self.db, prefix_type)
116116
}
117117

118-
pub fn get_member_map(
118+
pub fn get_member_info_map(
119119
&self,
120120
prefix_type: &LuaType,
121121
) -> Option<HashMap<LuaMemberKey, Vec<LuaMemberInfo>>> {
@@ -154,7 +154,7 @@ impl<'a> SemanticModel<'a> {
154154
&self,
155155
exprs: &[LuaExpr],
156156
var_count: Option<usize>,
157-
) -> Option<Vec<(LuaType, TextRange)>> {
157+
) -> Vec<(LuaType, TextRange)> {
158158
infer_multi_value_adjusted_expression_types(
159159
self.db,
160160
&mut self.infer_cache.borrow_mut(),
@@ -269,6 +269,14 @@ impl<'a> SemanticModel<'a> {
269269
pub fn get_member_key(&self, index_key: &LuaIndexKey) -> Option<LuaMemberKey> {
270270
LuaMemberKey::from_index_key(self.db, &mut self.infer_cache.borrow_mut(), index_key).ok()
271271
}
272+
273+
pub fn infer_member_type(
274+
&self,
275+
prefix_type: &LuaType,
276+
member_key: &LuaMemberKey,
277+
) -> Result<LuaType, InferFailReason> {
278+
member::infer_raw_member_type(self.db, prefix_type, member_key)
279+
}
272280
}
273281

274282
/// Guard to prevent infinite recursion

crates/emmylua_ls/src/handlers/completion/providers/member_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn add_completion(builder: &mut CompletionBuilder) -> Option<()> {
2525

2626
let prefix_expr = index_expr.get_prefix_expr()?;
2727
let prefix_type = builder.semantic_model.infer_expr(prefix_expr.into()).ok()?;
28-
let member_info_map = builder.semantic_model.get_member_map(&prefix_type)?;
28+
let member_info_map = builder.semantic_model.get_member_info_map(&prefix_type)?;
2929
for (_, member_infos) in member_info_map.iter() {
3030
add_resolve_member_infos(builder, &member_infos, completion_status);
3131
}

0 commit comments

Comments
 (0)