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
79 let Some(function_name) = function_like.name else {
80 return Some(FunctionLikeIdentifier::Closure(function_like.span.file_id, function_like.span.start));
81 };
82
83 Some(if function_like.get_kind().is_method() {
84 let Some(class_like) = self.class_like else {
85 return Some(FunctionLikeIdentifier::Function(function_name));
86 };
87
88 FunctionLikeIdentifier::Method(class_like.name, function_name)
89 } else {
90 FunctionLikeIdentifier::Function(function_name)
91 })
92 }
93
94 #[inline]
96 #[must_use]
97 pub const fn is_class_like_final(&self) -> bool {
98 match self.class_like {
99 Some(class) => class.flags.is_final(),
100 None => false,
101 }
102 }
103
104 #[inline]
106 #[must_use]
107 pub const fn is_static(&self) -> bool {
108 self.is_static
109 }
110
111 #[inline]
113 pub fn set_function_like(&mut self, function_like: Option<&'ctx FunctionLikeMetadata>) {
114 self.function_like = function_like;
115 }
116
117 #[inline]
119 pub fn set_class_like(&mut self, class_like: Option<&'ctx ClassLikeMetadata>) {
120 self.class_like = class_like;
121 }
122
123 #[inline]
125 pub fn set_static(&mut self, is_static: bool) {
126 self.is_static = is_static;
127 }
128
129 #[inline]
133 #[must_use]
134 pub fn get_property_hook(&self) -> Option<(Word, &'ctx PropertyHookMetadata)> {
135 self.property_hook
136 }
137
138 #[inline]
142 pub fn set_property_hook(&mut self, property_hook: Option<(Word, &'ctx PropertyHookMetadata)>) {
143 self.property_hook = property_hook;
144 }
145
146 #[inline]
149 #[must_use]
150 pub fn get_reference_source(&self) -> Option<ReferenceSource> {
151 if let Some(calling_functionlike_id) = self.get_function_like_identifier() {
152 match calling_functionlike_id {
153 FunctionLikeIdentifier::Function(name) => Some(ReferenceSource::Symbol(false, name)),
154 FunctionLikeIdentifier::Method(class_name, method_name) => {
155 Some(ReferenceSource::ClassLikeMember(false, class_name, method_name))
156 }
157 _ => None,
158 }
159 } else {
160 None
161 }
162 }
163}