mago_codex/context/
mod.rs1use mago_atom::Atom;
2
3use crate::identifier::function_like::FunctionLikeIdentifier;
4use crate::metadata::class_like::ClassLikeMetadata;
5use crate::metadata::function_like::FunctionLikeMetadata;
6use crate::metadata::property_hook::PropertyHookMetadata;
7use crate::reference::ReferenceSource;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct ScopeContext<'ctx> {
11 pub(crate) function_like: Option<&'ctx FunctionLikeMetadata>,
12 pub(crate) class_like: Option<&'ctx ClassLikeMetadata>,
13 pub(crate) property_hook: Option<(Atom, &'ctx PropertyHookMetadata)>,
14 pub(crate) is_static: bool,
15}
16
17impl Default for ScopeContext<'_> {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl<'ctx> ScopeContext<'ctx> {
24 #[inline]
26 pub fn new() -> Self {
27 Self { function_like: None, class_like: None, property_hook: None, is_static: true }
28 }
29
30 #[inline]
32 pub const fn is_global(&self) -> bool {
33 self.function_like.is_none() && self.class_like.is_none()
34 }
35
36 #[inline]
38 pub const fn is_pure(&self) -> bool {
39 if let Some(function_like) = self.function_like
40 && function_like.flags.is_pure()
41 {
42 return true;
43 }
44
45 false
46 }
47
48 #[inline]
50 pub fn get_class_like(&self) -> Option<&'ctx ClassLikeMetadata> {
51 self.class_like
52 }
53
54 #[inline]
56 pub fn get_class_like_name(&self) -> Option<Atom> {
57 self.class_like.map(|class| class.name)
58 }
59
60 #[inline]
62 pub fn get_function_like(&self) -> Option<&'ctx FunctionLikeMetadata> {
63 self.function_like
64 }
65
66 #[inline]
68 pub fn get_function_like_identifier(&self) -> Option<FunctionLikeIdentifier> {
69 let function_like = self.function_like?;
70
71 let Some(function_name) = function_like.name else {
72 return Some(FunctionLikeIdentifier::Closure(function_like.span.file_id, function_like.span.start));
73 };
74
75 Some(if function_like.get_kind().is_method() {
76 let Some(class_like) = self.class_like else {
77 return Some(FunctionLikeIdentifier::Function(function_name));
78 };
79
80 FunctionLikeIdentifier::Method(class_like.name, function_name)
81 } else {
82 FunctionLikeIdentifier::Function(function_name)
83 })
84 }
85
86 #[inline]
88 pub const fn is_class_like_final(&self) -> bool {
89 match self.class_like {
90 Some(class) => class.flags.is_final(),
91 None => false,
92 }
93 }
94
95 #[inline]
97 pub const fn is_static(&self) -> bool {
98 self.is_static
99 }
100
101 #[inline]
103 pub fn set_function_like(&mut self, function_like: Option<&'ctx FunctionLikeMetadata>) {
104 self.function_like = function_like;
105 }
106
107 #[inline]
109 pub fn set_class_like(&mut self, class_like: Option<&'ctx ClassLikeMetadata>) {
110 self.class_like = class_like;
111 }
112
113 #[inline]
115 pub fn set_static(&mut self, is_static: bool) {
116 self.is_static = is_static;
117 }
118
119 #[inline]
123 pub fn get_property_hook(&self) -> Option<(Atom, &'ctx PropertyHookMetadata)> {
124 self.property_hook
125 }
126
127 #[inline]
131 pub fn set_property_hook(&mut self, property_hook: Option<(Atom, &'ctx PropertyHookMetadata)>) {
132 self.property_hook = property_hook;
133 }
134
135 #[inline]
138 pub fn get_reference_source(&self) -> Option<ReferenceSource> {
139 if let Some(calling_functionlike_id) = self.get_function_like_identifier() {
140 match calling_functionlike_id {
141 FunctionLikeIdentifier::Function(name) => Some(ReferenceSource::Symbol(false, name)),
142 FunctionLikeIdentifier::Method(class_name, method_name) => {
143 Some(ReferenceSource::ClassLikeMember(false, class_name, method_name))
144 }
145 _ => None,
146 }
147 } else {
148 None
149 }
150 }
151}