mago_codex/context/
mod.rs1use mago_word::Word;
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)]
10#[allow(clippy::field_scoped_visibility_modifiers)]
11pub struct ScopeContext<'ctx> {
12 pub(crate) function_like: Option<&'ctx FunctionLikeMetadata>,
13 pub(crate) class_like: Option<&'ctx ClassLikeMetadata>,
14 pub(crate) property_hook: Option<(Word, &'ctx PropertyHookMetadata)>,
15 pub(crate) is_static: bool,
16}
17
18impl Default for ScopeContext<'_> {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl<'ctx> ScopeContext<'ctx> {
25 #[inline]
27 #[must_use]
28 pub fn new() -> Self {
29 Self { function_like: None, class_like: None, property_hook: None, is_static: true }
30 }
31
32 #[inline]
34 #[must_use]
35 pub const fn is_global(&self) -> bool {
36 self.function_like.is_none() && self.class_like.is_none()
37 }
38
39 #[inline]
41 #[must_use]
42 pub const fn is_pure(&self) -> bool {
43 if let Some(function_like) = self.function_like
44 && function_like.flags.is_pure()
45 {
46 return true;
47 }
48
49 false
50 }
51
52 #[inline]
54 #[must_use]
55 pub fn get_class_like(&self) -> Option<&'ctx ClassLikeMetadata> {
56 self.class_like
57 }
58
59 #[inline]
61 #[must_use]
62 pub fn get_class_like_name(&self) -> Option<Word> {
63 self.class_like.map(|class| class.name)
64 }
65
66 #[inline]
68 #[must_use]
69 pub fn get_function_like(&self) -> Option<&'ctx FunctionLikeMetadata> {
70 self.function_like
71 }
72
73 #[inline]
75 #[must_use]
76 pub fn get_function_like_identifier(&self) -> Option<FunctionLikeIdentifier> {
77 let function_like = self.function_like?;
78 let function_name = function_like.name;
79
80 if function_like.get_kind().is_method() {
81 if let Some(class_like) = self.class_like {
82 return Some(FunctionLikeIdentifier::Method(class_like.name, function_name));
83 }
84
85 return Some(FunctionLikeIdentifier::Function(function_name));
86 }
87
88 let kind = function_like.get_kind();
89 if kind.is_closure() || kind.is_arrow_function() {
90 return Some(FunctionLikeIdentifier::Closure(function_name));
91 }
92
93 Some(FunctionLikeIdentifier::Function(function_name))
94 }
95
96 #[inline]
98 #[must_use]
99 pub const fn is_class_like_final(&self) -> bool {
100 match self.class_like {
101 Some(class) => class.flags.is_final(),
102 None => false,
103 }
104 }
105
106 #[inline]
108 #[must_use]
109 pub const fn is_static(&self) -> bool {
110 self.is_static
111 }
112
113 #[inline]
115 pub fn set_function_like(&mut self, function_like: Option<&'ctx FunctionLikeMetadata>) {
116 self.function_like = function_like;
117 }
118
119 #[inline]
121 pub fn set_class_like(&mut self, class_like: Option<&'ctx ClassLikeMetadata>) {
122 self.class_like = class_like;
123 }
124
125 #[inline]
127 pub fn set_static(&mut self, is_static: bool) {
128 self.is_static = is_static;
129 }
130
131 #[inline]
135 #[must_use]
136 pub fn get_property_hook(&self) -> Option<(Word, &'ctx PropertyHookMetadata)> {
137 self.property_hook
138 }
139
140 #[inline]
144 pub fn set_property_hook(&mut self, property_hook: Option<(Word, &'ctx PropertyHookMetadata)>) {
145 self.property_hook = property_hook;
146 }
147
148 #[inline]
151 #[must_use]
152 pub fn get_reference_source(&self) -> Option<ReferenceSource> {
153 if let Some(calling_functionlike_id) = self.get_function_like_identifier() {
154 match calling_functionlike_id {
155 FunctionLikeIdentifier::Function(name) => Some(ReferenceSource::Symbol(false, name)),
156 FunctionLikeIdentifier::Method(class_name, method_name) => {
157 Some(ReferenceSource::ClassLikeMember(false, class_name, method_name))
158 }
159 _ => None,
160 }
161 } else {
162 None
163 }
164 }
165}