1#![warn(missing_docs)]
6
7use std::fmt;
8
9use oxc_span::Atom;
10
11use crate::ast::*;
12
13impl<'a> TSEnumMemberName<'a> {
14 pub fn static_name(&self) -> Atom<'a> {
18 match self {
19 Self::Identifier(ident) => ident.name,
20 Self::String(lit) | Self::ComputedString(lit) => lit.value,
21 Self::ComputedTemplateString(template) => template
22 .single_quasi()
23 .expect("`TSEnumMemberName::TemplateString` should have no substitution and at least one quasi"),
24 }
25 }
26}
27
28impl<'a> TSType<'a> {
29 pub fn get_identifier_reference(&self) -> Option<&IdentifierReference<'a>> {
34 match self {
35 TSType::TSTypeReference(reference) => reference.type_name.get_identifier_reference(),
36 TSType::TSTypeQuery(query) => match &query.expr_name {
37 TSTypeQueryExprName::IdentifierReference(ident) => Some(ident),
38 _ => None,
39 },
40 _ => None,
41 }
42 }
43
44 pub fn is_const_type_reference(&self) -> bool {
46 matches!(self, TSType::TSTypeReference(reference) if reference.type_name.is_const())
47 }
48
49 pub fn is_maybe_undefined(&self) -> bool {
51 match self {
52 TSType::TSAnyKeyword(_)
53 | TSType::TSUnknownKeyword(_)
54 | TSType::TSUndefinedKeyword(_) => true,
55 TSType::TSUnionType(un) => un.types.iter().any(Self::is_maybe_undefined),
56 _ => false,
57 }
58 }
59
60 #[rustfmt::skip]
62 pub fn is_keyword(&self) -> bool {
63 matches!(self, TSType::TSAnyKeyword(_) | TSType::TSBigIntKeyword(_) | TSType::TSBooleanKeyword(_)
64 | TSType::TSNeverKeyword(_) | TSType::TSNullKeyword(_) | TSType::TSNumberKeyword(_)
65 | TSType::TSObjectKeyword(_) | TSType::TSStringKeyword(_)| TSType::TSVoidKeyword(_)
66 | TSType::TSIntrinsicKeyword(_) | TSType::TSSymbolKeyword(_) | TSType::TSThisType(_)
67 | TSType::TSUndefinedKeyword(_) | TSType::TSUnknownKeyword(_)
68 )
69 }
70
71 pub fn is_keyword_or_literal(&self) -> bool {
75 self.is_keyword() || matches!(self, TSType::TSLiteralType(_))
76 }
77}
78
79impl<'a> TSTypeName<'a> {
80 pub fn get_identifier_reference(&self) -> Option<&IdentifierReference<'a>> {
88 match self {
89 TSTypeName::IdentifierReference(ident) => Some(ident),
90 TSTypeName::QualifiedName(name) => name.left.get_identifier_reference(),
91 TSTypeName::ThisExpression(_) => None,
92 }
93 }
94
95 pub fn is_const(&self) -> bool {
97 if let TSTypeName::IdentifierReference(ident) = self
98 && ident.name == "const"
99 {
100 return true;
101 }
102 false
103 }
104
105 pub fn is_identifier(&self) -> bool {
107 matches!(self, Self::IdentifierReference(_))
108 }
109
110 pub fn is_qualified_name(&self) -> bool {
113 matches!(self, Self::QualifiedName(_))
114 }
115}
116
117impl fmt::Display for TSTypeName<'_> {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 match self {
120 TSTypeName::IdentifierReference(ident) => ident.fmt(f),
121 TSTypeName::QualifiedName(qualified) => qualified.fmt(f),
122 TSTypeName::ThisExpression(_) => "this".fmt(f),
123 }
124 }
125}
126
127impl fmt::Display for TSQualifiedName<'_> {
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129 write!(f, "{}.{}", self.left, self.right)
130 }
131}
132
133impl TSType<'_> {
134 pub fn without_parenthesized(&self) -> &Self {
136 match self {
137 Self::TSParenthesizedType(expr) => expr.type_annotation.without_parenthesized(),
138 _ => self,
139 }
140 }
141}
142
143impl TSAccessibility {
144 #[inline]
146 pub fn is_private(self) -> bool {
147 matches!(self, Self::Private)
148 }
149
150 pub fn as_str(self) -> &'static str {
152 match self {
153 Self::Public => "public",
154 Self::Private => "private",
155 Self::Protected => "protected",
156 }
157 }
158}
159
160impl From<TSAccessibility> for &'static str {
161 fn from(accessibility: TSAccessibility) -> Self {
162 accessibility.as_str()
163 }
164}
165
166impl fmt::Display for TSAccessibility {
167 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 f.write_str(self.as_str())
169 }
170}
171
172impl TSModuleDeclaration<'_> {
173 pub fn has_use_strict_directive(&self) -> bool {
184 self.body.as_ref().is_some_and(TSModuleDeclarationBody::has_use_strict_directive)
185 }
186}
187
188impl TSModuleDeclarationKind {
189 pub fn as_str(self) -> &'static str {
192 match self {
193 Self::Module => "module",
194 Self::Namespace => "namespace",
195 }
196 }
197}
198
199impl<'a> TSModuleDeclarationName<'a> {
200 pub fn is_string_literal(&self) -> bool {
215 matches!(self, Self::StringLiteral(_))
216 }
217
218 pub fn name(&self) -> Atom<'a> {
220 match self {
221 Self::Identifier(ident) => ident.name,
222 Self::StringLiteral(lit) => lit.value,
223 }
224 }
225}
226
227impl fmt::Display for TSModuleDeclarationName<'_> {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 match self {
230 Self::Identifier(id) => id.fmt(f),
231 Self::StringLiteral(lit) => lit.fmt(f),
232 }
233 }
234}
235
236impl<'a> TSModuleDeclarationBody<'a> {
237 pub fn has_use_strict_directive(&self) -> bool {
248 matches!(self, Self::TSModuleBlock(block) if block.has_use_strict_directive())
249 }
250
251 pub fn is_empty(&self) -> bool {
253 match self {
254 TSModuleDeclarationBody::TSModuleDeclaration(declaration) => declaration.body.is_none(),
255 TSModuleDeclarationBody::TSModuleBlock(block) => block.body.len() == 0,
256 }
257 }
258
259 pub fn as_module_block_mut(&mut self) -> Option<&mut TSModuleBlock<'a>> {
262 let mut body = self;
263 loop {
264 match body {
265 TSModuleDeclarationBody::TSModuleBlock(block) => return Some(block.as_mut()),
266 TSModuleDeclarationBody::TSModuleDeclaration(decl) => {
267 body = decl.body.as_mut()?;
268 }
269 }
270 }
271 }
272}
273
274impl TSModuleBlock<'_> {
275 pub fn has_use_strict_directive(&self) -> bool {
277 self.directives.iter().any(Directive::is_use_strict)
278 }
279}
280
281impl TSModuleReference<'_> {
282 pub fn is_external(&self) -> bool {
284 matches!(self, Self::ExternalModuleReference(_))
285 }
286}
287
288impl<'a> Decorator<'a> {
289 pub fn name(&self) -> Option<&'a str> {
298 match &self.expression {
299 Expression::Identifier(ident) => Some(ident.name.as_str()),
300 expr @ match_member_expression!(Expression) => {
301 expr.to_member_expression().static_property_name()
302 }
303 Expression::CallExpression(call) => {
304 call.callee.get_member_expr().and_then(MemberExpression::static_property_name)
305 }
306 _ => None,
307 }
308 }
309}
310
311impl ImportOrExportKind {
312 pub fn is_value(self) -> bool {
314 matches!(self, Self::Value)
315 }
316
317 pub fn is_type(self) -> bool {
319 matches!(self, Self::Type)
320 }
321}
322
323impl TSTypeOperatorOperator {
324 pub fn to_str(self) -> &'static str {
326 match self {
327 TSTypeOperatorOperator::Keyof => "keyof",
328 TSTypeOperatorOperator::Readonly => "readonly",
329 TSTypeOperatorOperator::Unique => "unique",
330 }
331 }
332}