php_lsp/db/
method_returns.rs1use std::sync::Arc;
11
12use salsa::Database;
13
14use crate::ast::MethodReturnsMap;
15use crate::db::input::SourceFile;
16use crate::db::parse::parsed_doc;
17use crate::type_map::build_method_returns;
18
19#[derive(Clone)]
20pub struct MethodReturnsArc(pub Arc<MethodReturnsMap>);
21
22impl MethodReturnsArc {
23 pub fn get(&self) -> &MethodReturnsMap {
24 &self.0
25 }
26}
27
28crate::impl_arc_update!(MethodReturnsArc);
30
31#[salsa::tracked(no_eq)]
32pub fn method_returns(db: &dyn Database, file: SourceFile) -> MethodReturnsArc {
33 let doc = parsed_doc(db, file);
34 MethodReturnsArc(Arc::new(build_method_returns(doc.get())))
35}
36
37#[cfg(test)]
38mod tests {
39 use std::sync::Arc;
40
41 use super::*;
42 use crate::db::analysis::AnalysisHost;
43 use crate::db::input::{FileId, SourceFile};
44 use salsa::Setter;
45
46 #[test]
47 fn method_returns_captures_factory_return() {
48 let host = AnalysisHost::new();
49 let file = SourceFile::new(
50 host.db(),
51 FileId(0),
52 Arc::<str>::from("file:///t.php"),
53 Arc::<str>::from(
54 "<?php\nclass Foo {\n public function make(): Bar { return new Bar(); }\n}\nclass Bar {}",
55 ),
56 None,
57 );
58 let m = method_returns(host.db(), file);
59 let foo = m.get().get("Foo").expect("class Foo in map");
60 assert_eq!(foo.get("make").map(String::as_str), Some("Bar"));
61 }
62
63 #[test]
64 fn method_returns_reruns_after_edit() {
65 let mut host = AnalysisHost::new();
66 let file = SourceFile::new(
67 host.db(),
68 FileId(1),
69 Arc::<str>::from("file:///t.php"),
70 Arc::<str>::from(
71 "<?php\nclass F {\n public function m(): A { return new A(); }\n}\nclass A {}\nclass B {}",
72 ),
73 None,
74 );
75 let a1 = method_returns(host.db(), file);
76 let first = Arc::as_ptr(&a1.0);
77
78 file.set_text(host.db_mut()).to(Arc::<str>::from(
79 "<?php\nclass F {\n public function m(): B { return new B(); }\n}\nclass A {}\nclass B {}",
80 ));
81 let a2 = method_returns(host.db(), file);
82 assert_ne!(
83 first,
84 Arc::as_ptr(&a2.0),
85 "editing the source should produce a new map"
86 );
87 assert_eq!(
88 a2.get()
89 .get("F")
90 .and_then(|m| m.get("m"))
91 .map(String::as_str),
92 Some("B")
93 );
94 }
95}