-
-
Notifications
You must be signed in to change notification settings - Fork 872
Expand file tree
/
Copy pathsymbol.rs
More file actions
164 lines (133 loc) · 5.94 KB
/
symbol.rs
File metadata and controls
164 lines (133 loc) · 5.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use std::num::NonZeroU32;
use bitflags::bitflags;
#[cfg(feature = "serialize")]
use serde::Serialize;
use oxc_index::Idx;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct SymbolId(NonZeroU32);
impl Idx for SymbolId {
#[allow(clippy::cast_possible_truncation)]
fn from_usize(idx: usize) -> Self {
// SAFETY: + 1 is always non-zero.
unsafe { Self(NonZeroU32::new_unchecked(idx as u32 + 1)) }
}
fn index(self) -> usize {
self.0.get() as usize - 1
}
}
#[cfg(feature = "serialize")]
#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type SymbolId = number;
export type SymbolFlags = unknown;
"#;
bitflags! {
#[derive(Debug, Clone, Copy)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
pub struct SymbolFlags: u32 {
const None = 0;
/// Variable (var) or parameter
const FunctionScopedVariable = 1 << 0;
/// A block-scoped variable (let or const)
const BlockScopedVariable = 1 << 1;
/// A const variable (const)
const ConstVariable = 1 << 2;
/// Is this symbol inside an export declaration
const Export = 1 << 4;
const Class = 1 << 5;
const CatchVariable = 1 << 6; // try {} catch(catch_variable) {}
const Function = 1 << 7;
const Import = 1 << 8; // Imported ESM binding
const TypeImport = 1 << 9; // Imported ESM type-only binding
// Type specific symbol flags
const TypeAlias = 1 << 10;
const Interface = 1 << 11;
const RegularEnum = 1 << 12;
const ConstEnum = 1 << 13;
const EnumMember = 1 << 14;
const TypeLiteral = 1 << 15;
const TypeParameter = 1 << 16;
const NameSpaceModule = 1 << 17;
const ValueModule = 1 << 18;
// In a dts file or there is a declare flag
const Ambient = 1 << 19;
const Enum = Self::ConstEnum.bits() | Self::RegularEnum.bits();
const Variable = Self::FunctionScopedVariable.bits() | Self::BlockScopedVariable.bits();
const Value = Self::Variable.bits() | Self::Class.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::ValueModule.bits();
const Type = Self::Class.bits() | Self::Interface.bits() | Self::Enum.bits() | Self::EnumMember.bits() | Self::TypeLiteral.bits() | Self::TypeParameter.bits() | Self::TypeAlias.bits();
/// Variables can be redeclared, but can not redeclare a block-scoped declaration with the
/// same name, or any other value that is not a variable, e.g. ValueModule or Class
const FunctionScopedVariableExcludes = Self::Value.bits() - Self::FunctionScopedVariable.bits();
/// Block-scoped declarations are not allowed to be re-declared
/// they can not merge with anything in the value space
const BlockScopedVariableExcludes = Self::Value.bits();
const ClassExcludes = (Self::Value.bits() | Self::TypeAlias.bits()) & !Self::ValueModule.bits() ;
const ImportBindingExcludes = Self::Import.bits() | Self::TypeImport.bits();
// Type specific excludes
const TypeAliasExcludes = Self::Type.bits();
const InterfaceExcludes = Self::Type.bits() & !(Self::Interface.bits() | Self::Class.bits());
const TypeParameterExcludes = Self::Type.bits() & !Self::TypeParameter.bits();
const ConstEnumExcludes = (Self::Type.bits() | Self::Value.bits()) & !Self::ConstEnum.bits();
// TODO: include value module in regular enum excludes
const RegularEnumExcludes = (Self::Value.bits() | Self::Type.bits()) & !(Self::RegularEnum.bits() | Self::ValueModule.bits() );
const EnumMemberExcludes = Self::EnumMember.bits();
}
}
impl SymbolFlags {
pub fn is_variable(&self) -> bool {
self.intersects(Self::Variable)
}
pub fn is_type_parameter(&self) -> bool {
self.contains(Self::TypeParameter)
}
/// If true, then the symbol is a type, such as a TypeAlias, Interface, or Enum
pub fn is_type(&self) -> bool {
self.intersects((Self::TypeImport | Self::Type) - Self::Value)
}
/// If true, then the symbol is a value, such as a Variable, Function, or Class
pub fn is_value(&self) -> bool {
self.intersects(Self::Value | Self::Import | Self::Function)
}
pub fn is_const_variable(&self) -> bool {
self.contains(Self::ConstVariable)
}
pub fn is_function(&self) -> bool {
self.contains(Self::Function)
}
pub fn is_class(&self) -> bool {
self.contains(Self::Class)
}
pub fn is_interface(&self) -> bool {
self.contains(Self::Interface)
}
pub fn is_type_alias(&self) -> bool {
self.contains(Self::TypeAlias)
}
pub fn is_enum(&self) -> bool {
self.intersects(Self::Enum)
}
pub fn is_catch_variable(&self) -> bool {
self.contains(Self::CatchVariable)
}
pub fn is_function_scoped_declaration(&self) -> bool {
self.contains(Self::FunctionScopedVariable)
}
pub fn is_export(&self) -> bool {
self.contains(Self::Export)
}
pub fn is_import(&self) -> bool {
self.intersects(Self::Import | Self::TypeImport)
}
pub fn is_type_import(&self) -> bool {
self.contains(Self::TypeImport)
}
/// If true, then the symbol can be referenced by a type
pub fn can_be_referenced_by_type(&self) -> bool {
self.intersects(Self::Type | Self::TypeImport | Self::Import)
}
/// If true, then the symbol can be referenced by a value
pub fn can_be_referenced_by_value(&self) -> bool {
self.intersects(Self::Value | Self::Import | Self::Function)
}
}