use crate::functions::emit_warning::emit_warning;
use crate::records::lint_table_literal::LintTableLiteral;
use alloc::collections::BTreeMap;
use luaur_ast::enums::ast_table_access::AstTableAccess;
use luaur_ast::records::ast_name::AstName;
use luaur_ast::records::ast_type_table::AstTypeTable;
use luaur_ast::records::location::Location;
use luaur_config::enums::code::Code;
impl LintTableLiteral {
pub fn visit_ast_type_table(&mut self, node: *mut AstTypeTable) -> bool {
let node = unsafe { &*node };
let checked_in_new_solver = unsafe {
!(*self.context).module.is_null() && (*(*self.context).module).checked_in_new_solver
};
if checked_in_new_solver {
#[derive(Clone, Copy)]
struct Rec {
access: AstTableAccess,
location: Location,
}
let mut names: BTreeMap<AstName, Rec> = BTreeMap::new();
for item in node.props.iter() {
let name = unsafe { core::ffi::CStr::from_ptr(item.name.value).to_string_lossy() };
if let Some(rec) = names.get_mut(&item.name) {
if (rec.access as u8 & item.access as u8) != 0 {
if rec.access == item.access {
emit_warning(
unsafe { &mut *self.context },
Code::Code_TableLiteral,
item.location,
format_args!(
"Table type field '{}' is a duplicate; previously defined at line {}",
name,
rec.location.begin.line + 1
),
);
} else if rec.access == AstTableAccess::ReadWrite {
emit_warning(
unsafe { &mut *self.context },
Code::Code_TableLiteral,
item.location,
format_args!(
"Table type field '{}' is already read-write; previously defined at line {}",
name,
rec.location.begin.line + 1
),
);
} else if rec.access == AstTableAccess::Read {
emit_warning(
unsafe { &mut *self.context },
Code::Code_TableLiteral,
rec.location,
format_args!(
"Table type field '{}' already has a read type defined at line {}",
name,
rec.location.begin.line + 1
),
);
} else if rec.access == AstTableAccess::Write {
emit_warning(
unsafe { &mut *self.context },
Code::Code_TableLiteral,
rec.location,
format_args!(
"Table type field '{}' already has a write type defined at line {}",
name,
rec.location.begin.line + 1
),
);
}
} else {
rec.access = match rec.access as u8 | item.access as u8 {
1 => AstTableAccess::Read,
2 => AstTableAccess::Write,
_ => AstTableAccess::ReadWrite,
};
}
} else {
names.insert(
item.name,
Rec {
access: item.access,
location: item.location,
},
);
}
}
return true;
}
let mut names: BTreeMap<AstName, u32> = BTreeMap::new();
for item in node.props.iter() {
let name = unsafe { core::ffi::CStr::from_ptr(item.name.value).to_string_lossy() };
if let Some(line) = names.get(&item.name).copied() {
emit_warning(
unsafe { &mut *self.context },
Code::Code_TableLiteral,
item.location,
format_args!(
"Table type field '{}' is a duplicate; previously defined at line {}",
name, line
),
);
} else {
names.insert(item.name, item.location.begin.line + 1);
}
}
true
}
}