1use bitflags::bitflags;
2use oxc_allocator::{Allocator, CloneIn, CloneInSemanticIds};
3use oxc_index::define_nonmax_u32_index_type;
4#[cfg(feature = "serialize")]
5use serde::Serialize;
6
7use oxc_ast_macros::ast;
8
9use crate::semantic_id::SemanticId;
10
11define_nonmax_u32_index_type! {
12 #[ast]
13 #[builder(default)]
14 #[clone_in(semantic_id)]
15 #[content_eq(skip)]
16 #[estree(skip)]
17 pub struct SymbolId;
18}
19
20impl<'alloc> CloneIn<'alloc> for SymbolId {
21 type Cloned = Self;
22
23 #[expect(clippy::inline_always)]
24 #[inline(always)] fn clone_in_impl(&self, with_semantic_ids: CloneInSemanticIds, _: &'alloc Allocator) -> Self {
26 self.clone_id(with_semantic_ids)
27 }
28}
29
30impl SemanticId for SymbolId {}
31
32define_nonmax_u32_index_type! {
33 pub struct RedeclarationId;
34}
35
36bitflags! {
37 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
38 #[cfg_attr(feature = "serialize", derive(Serialize))]
39 pub struct SymbolFlags: u32 {
40 const None = 0;
41 const FunctionScopedVariable = 1 << 0;
43 const BlockScopedVariable = 1 << 1;
45 const ConstVariable = 1 << 2;
47 const Class = 1 << 3;
48 const CatchVariable = 1 << 4;
50 const Function = 1 << 5;
52 const Import = 1 << 6;
54 const TypeImport = 1 << 7;
56 const TypeAlias = 1 << 8;
58 const Interface = 1 << 9;
59 const RegularEnum = 1 << 10;
60 const ConstEnum = 1 << 11;
61 const EnumMember = 1 << 12;
62 const TypeParameter = 1 << 13;
63 const NamespaceModule = 1 << 14;
65 const ValueModule = 1 << 15;
67 const Ambient = 1 << 16;
74
75 const FunctionExpression = 1 << 17;
82 const AsyncOrGeneratorFunction = 1 << 18;
84
85 const Enum = Self::ConstEnum.bits() | Self::RegularEnum.bits();
86 const Variable = Self::FunctionScopedVariable.bits() | Self::BlockScopedVariable.bits();
87
88 const BlockScoped = Self::BlockScopedVariable.bits() | Self::Enum.bits() | Self::Class.bits();
89
90 const Value = Self::Variable.bits() | Self::Class.bits() | Self::Function.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::ValueModule.bits();
91 const Type = Self::Class.bits() | Self::Interface.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::TypeParameter.bits() | Self::TypeAlias.bits();
92 const Namespace = Self::ValueModule.bits() | Self::NamespaceModule.bits() | Self::Enum.bits();
93
94
95 const FunctionScopedVariableExcludes = Self::Value.bits() - Self::FunctionScopedVariable.bits() - Self::Function.bits();
98
99 const BlockScopedVariableExcludes = Self::Value.bits();
102 const FunctionExcludes = Self::Value.bits() & !(Self::Function.bits() | Self::ValueModule.bits() | Self::Class.bits());
103 const ClassExcludes = (Self::Value.bits() | Self::Type.bits()) & !(Self::ValueModule.bits() | Self::Function.bits() | Self::Interface.bits());
104
105 const ImportBindingExcludes = Self::Import.bits() | Self::TypeImport.bits();
106 const TypeAliasExcludes = Self::Type.bits();
108 const InterfaceExcludes = Self::Type.bits() & !(Self::Interface.bits() | Self::Class.bits());
109 const TypeParameterExcludes = Self::Type.bits() & !Self::TypeParameter.bits();
110 const ConstEnumExcludes = (Self::Type.bits() | Self::Value.bits()) & !Self::ConstEnum.bits();
111 const ValueModuleExcludes = Self::Value.bits() & !(Self::Function.bits() | Self::Class.bits() | Self::RegularEnum.bits() | Self::ValueModule.bits());
112 const NamespaceModuleExcludes = 0;
113 const RegularEnumExcludes = (Self::Value.bits() | Self::Type.bits()) & !(Self::RegularEnum.bits() | Self::ValueModule.bits() );
115 const EnumMemberExcludes = Self::EnumMember.bits();
116
117 }
118}
119
120impl SymbolFlags {
121 #[inline]
122 pub fn is_variable(self) -> bool {
123 self.intersects(Self::Variable)
124 }
125
126 #[inline]
127 pub fn is_type_parameter(self) -> bool {
128 self.contains(Self::TypeParameter)
129 }
130
131 #[inline]
133 pub fn is_type(self) -> bool {
134 self.intersects((Self::TypeImport | Self::Type) - Self::Value)
135 }
136
137 #[inline]
139 pub fn is_value(self) -> bool {
140 self.intersects(Self::Value | Self::Import)
141 }
142
143 #[inline]
144 pub fn is_const_variable(self) -> bool {
145 self.contains(Self::ConstVariable)
146 }
147
148 #[inline]
150 pub fn is_function(self) -> bool {
151 self.contains(Self::Function)
152 }
153
154 #[inline]
155 pub fn is_class(self) -> bool {
156 self.contains(Self::Class)
157 }
158
159 #[inline]
163 pub fn is_block_scoped(self) -> bool {
164 self.intersects(Self::BlockScoped)
165 }
166
167 #[inline]
168 pub fn is_interface(self) -> bool {
169 self.contains(Self::Interface)
170 }
171
172 #[inline]
173 pub fn is_type_alias(self) -> bool {
174 self.contains(Self::TypeAlias)
175 }
176
177 #[inline]
178 pub fn is_enum(self) -> bool {
179 self.intersects(Self::Enum)
180 }
181
182 #[inline]
183 pub fn is_const_enum(self) -> bool {
184 self.intersects(Self::ConstEnum)
185 }
186
187 #[inline]
188 pub fn is_enum_member(self) -> bool {
189 self.contains(Self::EnumMember)
190 }
191
192 #[inline]
193 pub fn is_catch_variable(self) -> bool {
194 self.contains(Self::CatchVariable)
195 }
196
197 #[inline]
198 pub fn is_function_scoped_declaration(self) -> bool {
199 self.contains(Self::FunctionScopedVariable)
200 }
201
202 #[inline]
203 pub fn is_import(self) -> bool {
204 self.intersects(Self::Import | Self::TypeImport)
205 }
206
207 #[inline]
208 pub fn is_type_import(self) -> bool {
209 self.contains(Self::TypeImport)
210 }
211
212 #[inline]
213 pub fn is_ambient(self) -> bool {
214 self.contains(Self::Ambient)
215 }
216
217 #[inline]
218 pub fn is_namespace_module(self) -> bool {
219 self.contains(Self::NamespaceModule)
220 }
221
222 #[inline]
223 pub fn is_value_module(self) -> bool {
224 self.contains(Self::ValueModule)
225 }
226
227 #[inline]
229 pub fn can_be_referenced_by_type(self) -> bool {
230 self.intersects(Self::Type | Self::TypeImport | Self::Import | Self::Namespace)
231 }
232
233 #[inline]
235 pub fn can_be_referenced_by_value(self) -> bool {
236 self.is_value()
237 }
238
239 #[inline]
241 pub fn can_be_referenced_by_value_as_type(self) -> bool {
242 self.intersects(Self::Value | Self::Import | Self::Function | Self::TypeImport)
243 }
244
245 #[inline]
250 pub fn can_be_referenced_as_namespace(self) -> bool {
251 self.intersects(Self::Namespace | Self::Import | Self::TypeImport)
252 }
253}