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 #[must_use]
27 pub fn new() -> Self {
28 Self { function_like: None, class_like: None, property_hook: None, is_static: true }
29 }
30
31 #[inline]
33 #[must_use]
34 pub const fn is_global(&self) -> bool {
35 self.function_like.is_none() && self.class_like.is_none()
36 }
37
38 #[inline]
40 #[must_use]
41 pub const fn is_pure(&self) -> bool {
42 if let Some(function_like) = self.function_like
43 && function_like.flags.is_pure()
44 {
45 return true;
46 }
47
48 false
49 }
50
51 #[inline]
53 #[must_use]
54 pub fn get_class_like(&self) -> Option<&'ctx ClassLikeMetadata> {
55 self.class_like
56 }
57
58 #[inline]
60 #[must_use]
61 pub fn get_class_like_name(&self) -> Option<Atom> {
62 self.class_like.map(|class| class.name)
63 }
64
65 #[inline]
67 #[must_use]
68 pub fn get_function_like(&self) -> Option<&'ctx FunctionLikeMetadata> {
69 self.function_like
70 }
71
72 #[inline]
74 #[must_use]
75 pub fn get_function_like_identifier(&self) -> Option<FunctionLikeIdentifier> {
76 let function_like = self.function_like?;
77
78 let Some(function_name) = function_like.name else {
79 return Some(FunctionLikeIdentifier::Closure(function_like.span.file_id, function_like.span.start));
80 };
81
82 Some(if function_like.get_kind().is_method() {
83 let Some(class_like) = self.class_like else {
84 return Some(FunctionLikeIdentifier::Function(function_name));
85 };
86
87 FunctionLikeIdentifier::Method(class_like.name, function_name)
88 } else {
89 FunctionLikeIdentifier::Function(function_name)
90 })
91 }
92
93 #[inline]
95 #[must_use]
96 pub const fn is_class_like_final(&self) -> bool {
97 match self.class_like {
98 Some(class) => class.flags.is_final(),
99 None => false,
100 }
101 }
102
103 #[inline]
105 #[must_use]
106 pub const fn is_static(&self) -> bool {
107 self.is_static
108 }
109
110 #[inline]
112 pub fn set_function_like(&mut self, function_like: Option<&'ctx FunctionLikeMetadata>) {
113 self.function_like = function_like;
114 }
115
116 #[inline]
118 pub fn set_class_like(&mut self, class_like: Option<&'ctx ClassLikeMetadata>) {
119 self.class_like = class_like;
120 }
121
122 #[inline]
124 pub fn set_static(&mut self, is_static: bool) {
125 self.is_static = is_static;
126 }
127
128 #[inline]
132 #[must_use]
133 pub fn get_property_hook(&self) -> Option<(Atom, &'ctx PropertyHookMetadata)> {
134 self.property_hook
135 }
136
137 #[inline]
141 pub fn set_property_hook(&mut self, property_hook: Option<(Atom, &'ctx PropertyHookMetadata)>) {
142 self.property_hook = property_hook;
143 }
144
145 #[inline]
148 #[must_use]
149 pub fn get_reference_source(&self) -> Option<ReferenceSource> {
150 if let Some(calling_functionlike_id) = self.get_function_like_identifier() {
151 match calling_functionlike_id {
152 FunctionLikeIdentifier::Function(name) => Some(ReferenceSource::Symbol(false, name)),
153 FunctionLikeIdentifier::Method(class_name, method_name) => {
154 Some(ReferenceSource::ClassLikeMember(false, class_name, method_name))
155 }
156 _ => None,
157 }
158 } else {
159 None
160 }
161 }
162}