Skip to content

Commit 1c1a332

Browse files
committed
update type check object
1 parent 110c40d commit 1c1a332

File tree

4 files changed

+117
-16
lines changed

4 files changed

+117
-16
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ fn check_table_expr_content(
288288
let Some(member_key) = semantic_model.get_member_key(&field_key) else {
289289
continue;
290290
};
291+
291292
let source_type = match semantic_model.infer_member_type(table_type, &member_key) {
292293
Ok(typ) => typ,
293294
Err(_) => {

crates/emmylua_code_analysis/src/diagnostic/test/assign_type_mismatch_test.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,4 +966,26 @@ return t
966966
"#
967967
));
968968
}
969+
970+
#[test]
971+
fn test_object_table() {
972+
let mut ws = VirtualWorkspace::new();
973+
ws.def(
974+
r#"
975+
---@alias A {[string]: string}
976+
977+
---@param matchers A
978+
function name(matchers)
979+
end
980+
"#,
981+
);
982+
assert!(!ws.check_code_for(
983+
DiagnosticCode::AssignTypeMismatch,
984+
r#"
985+
name({
986+
toBe = 1,
987+
})
988+
"#
989+
));
990+
}
969991
}

crates/emmylua_code_analysis/src/semantic/member/infer_raw_member.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn infer_raw_member_type_guard(
4646
infer_custom_type_raw_member_type(db, type_id, member_key, infer_guard)
4747
}
4848
LuaType::Tuple(tuple) => infer_tuple_raw_member_type(tuple, member_key),
49-
LuaType::Object(object) => infer_object_raw_member_type(object, member_key),
49+
LuaType::Object(object) => infer_object_raw_member_type(db, object, member_key),
5050
LuaType::Array(array_type) => {
5151
infer_array_raw_member_type(db, array_type.get_base(), member_key)
5252
}
@@ -131,27 +131,27 @@ fn infer_tuple_raw_member_type(
131131
}
132132

133133
fn infer_object_raw_member_type(
134+
db: &DbIndex,
134135
object: &LuaObjectType,
135136
member_key: &LuaMemberKey,
136137
) -> RawGetMemberTypeResult {
137138
if let Some(member_type) = object.get_field(member_key) {
138139
return Ok(member_type.clone());
139140
}
140141

141-
// donot support now
142-
// let index_accesses = object.get_index_access();
143-
// for (key, value) in index_accesses {
144-
// let result = infer_index_metamethod(db, &member_key, &key, value);
145-
// match result {
146-
// Ok(typ) => {
147-
// return Ok(typ);
148-
// }
149-
// Err(InferFailReason::FieldNotFound) => {}
150-
// Err(err) => {
151-
// return Err(err);
152-
// }
153-
// }
154-
// }
142+
let index_accesses = object.get_index_access();
143+
for (key, value) in index_accesses {
144+
let access_key_type = match &member_key {
145+
LuaMemberKey::Name(name) => LuaType::StringConst(name.clone().into()),
146+
LuaMemberKey::Integer(i) => LuaType::IntegerConst(*i),
147+
LuaMemberKey::ExprType(lua_type) => lua_type.clone(),
148+
LuaMemberKey::None => continue,
149+
};
150+
151+
if check_type_compact(db, key, &access_key_type).is_ok() {
152+
return Ok(value.clone());
153+
}
154+
}
155155

156156
Err(InferFailReason::FieldNotFound)
157157
}

crates/emmylua_code_analysis/src/semantic/type_check/complex_type/object_type_check.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@ fn check_object_type_compact_member_owner(
101101
check_guard: TypeCheckGuard,
102102
) -> TypeCheckResult {
103103
let member_index = context.db.get_member_index();
104+
let source_fields = source_object.get_fields();
104105

105-
for (key, source_type) in source_object.get_fields() {
106+
// 检查名称字段
107+
for (key, source_type) in source_fields {
106108
let member_item = match member_index.get_member_item(&member_owner, key) {
107109
Some(member_item) => member_item,
108110
None => {
@@ -146,6 +148,82 @@ fn check_object_type_compact_member_owner(
146148
}
147149
}
148150

151+
// 检查索引访问字段
152+
let members = member_index.get_members(&member_owner).unwrap_or_default();
153+
for (key_type, source_type) in source_object.get_index_access() {
154+
for member in &members {
155+
let member = *member;
156+
if source_fields.contains_key(member.get_key()) {
157+
continue;
158+
}
159+
let member_key_type = match member.get_key() {
160+
LuaMemberKey::Integer(i) => LuaType::IntegerConst(*i),
161+
LuaMemberKey::Name(name) => LuaType::StringConst(name.clone().into()),
162+
LuaMemberKey::ExprType(typ) => typ.clone(),
163+
LuaMemberKey::None => continue,
164+
};
165+
166+
let key_match = match check_general_type_compact(
167+
context,
168+
key_type,
169+
&member_key_type,
170+
check_guard.next_level()?,
171+
) {
172+
Ok(_) => true,
173+
Err(err) => {
174+
if err.is_type_not_match() {
175+
false
176+
} else {
177+
return Err(err);
178+
}
179+
}
180+
};
181+
182+
if !key_match {
183+
continue;
184+
}
185+
186+
let member_type = match context
187+
.db
188+
.get_type_index()
189+
.get_type_cache(&member.get_id().into())
190+
{
191+
Some(cache) => cache.as_type().clone(),
192+
None => continue,
193+
};
194+
195+
match check_general_type_compact(
196+
context,
197+
source_type,
198+
&member_type,
199+
check_guard.next_level()?,
200+
) {
201+
Ok(_) => {
202+
break;
203+
}
204+
Err(TypeCheckFailReason::TypeNotMatch) => {
205+
let mut key_display = member.get_key().to_path();
206+
if key_display.is_empty() {
207+
key_display =
208+
humanize_type(context.db, &member_key_type, RenderLevel::Simple);
209+
}
210+
return Err(TypeCheckFailReason::TypeNotMatchWithReason(
211+
t!(
212+
"member %{key} not match, expect %{typ}, but got %{got}",
213+
key = key_display,
214+
typ = humanize_type(context.db, source_type, RenderLevel::Simple),
215+
got = humanize_type(context.db, &member_type, RenderLevel::Simple)
216+
)
217+
.to_string(),
218+
));
219+
}
220+
Err(err) => {
221+
return Err(err);
222+
}
223+
}
224+
}
225+
}
226+
149227
Ok(())
150228
}
151229

0 commit comments

Comments
 (0)