diff --git a/src/dreamchecker/lib.rs b/src/dreamchecker/lib.rs index dbaf666e0..7824066a8 100644 --- a/src/dreamchecker/lib.rs +++ b/src/dreamchecker/lib.rs @@ -1718,6 +1718,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { | "winget") { self.env.sleeping_procs.insert_violator(self.proc_ref, unscoped_name, location); } + self.check_type_sleepers(self.ty, location, unscoped_name); let src = self.ty; if let Some(proc) = self.ty.get_proc(unscoped_name) { self.visit_call(location, src, proc, args, false, local_vars) @@ -1873,6 +1874,23 @@ impl<'o, 's> AnalyzeProc<'o, 's> { } } + fn check_type_sleepers(&mut self, ty: TypeRef<'o>, location: Location, unscoped_name: &Ident) { + println!("{}, {}", ty, unscoped_name); + match ty.get().path.as_str() { + "/client" => if self.inside_newcontext == 0 && matches!(unscoped_name.as_str(), + "SoundQuery" + | "MeasureText") { + self.env.sleeping_procs.insert_violator(self.proc_ref, format!("client.{}", unscoped_name).as_str(), location); + }, + "/world" => if self.inside_newcontext == 0 && matches!(unscoped_name.as_str(), + "Import" + | "Export") { + self.env.sleeping_procs.insert_violator(self.proc_ref, format!("world.{}", unscoped_name).as_str(), location); + }, + _ => {}, + } + } + fn visit_follow(&mut self, location: Location, lhs: Analysis<'o>, rhs: &'o Follow, local_vars: &mut HashMap>) -> Analysis<'o> { match rhs { Follow::Field(IndexKind::Colon, _) => Analysis::empty(), @@ -1945,6 +1963,7 @@ impl<'o, 's> AnalyzeProc<'o, 's> { }, Follow::Call(kind, name, arguments) => { if let Some(ty) = lhs.static_ty.basic_type() { + self.check_type_sleepers(ty, location, name); if let Some(proc) = ty.get_proc(name) { if let Some((privateproc, true, decllocation)) = self.env.private.get_self_or_parent(proc) { if ty != privateproc.ty() { @@ -1963,13 +1982,6 @@ impl<'o, 's> AnalyzeProc<'o, 's> { .register(self.context); } } - if ty.get().path.as_str() == "/world" { - if self.inside_newcontext == 0 && matches!(name.as_str(), - "Import" - | "Export") { - self.env.sleeping_procs.insert_violator(self.proc_ref, format!("world.{}", name).as_str(), location); - } - } self.visit_call(location, ty, proc, arguments, false, local_vars) } else { error(location, format!("undefined proc: {:?} on {}", name, ty)) diff --git a/src/dreamchecker/tests/sleep_pure_tests.rs b/src/dreamchecker/tests/sleep_pure_tests.rs index 2cc3638d1..9a023b6b7 100644 --- a/src/dreamchecker/tests/sleep_pure_tests.rs +++ b/src/dreamchecker/tests/sleep_pure_tests.rs @@ -114,6 +114,11 @@ fn sleep3() { pub const SLEEP_ERROR4: &[(u32, u16, &str)] = &[ (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking built-in(s)"), + (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking proc /mob/proc/test2"), + (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking proc /client/proc/checksoundquery"), + (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking proc /client/proc/checkmeasuretext"), + (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking proc /world/proc/checkimport"), + (1, 16, "/mob/proc/test1 sets SpacemanDMM_should_not_sleep but calls blocking proc /world/proc/checkexport"), ]; #[test] @@ -123,6 +128,23 @@ fn sleep4() { set SpacemanDMM_should_not_sleep = TRUE world.Export() world.Import() + var/client/C = new /client + test2() + C.checksoundquery() + C.checkmeasuretext() + world.checkimport() + world.checkexport() +/client/proc/checksoundquery() + SoundQuery() +/client/proc/checkmeasuretext() + MeasureText() +/world/proc/checkimport() + Import() +/world/proc/checkexport() + Export() +/mob/proc/test2() + var/client/C = new /client + C.MeasureText() "##.trim(); check_errors_match(code, SLEEP_ERROR4); }