1use crate::{
2 derive_ASTNode,
3 visiting::{Chain, VisitOptions, Visitable},
4 Quoted, TSXToken,
5};
6use get_field_by_type::GetFieldByType;
7use source_map::Span;
8use std::fmt::Debug;
9use temporary_annex::Annex;
10use tokenizer_lib::{sized_tokens::TokenReaderWithTokenEnds, Token, TokenReader};
11
12use crate::{
13 errors::parse_lexing_error, number::NumberRepresentation, tokens::token_as_identifier, ASTNode,
14 Expression, ParseOptions, ParseResult,
15};
16
17pub trait PropertyKeyKind: Debug + PartialEq + Eq + Clone + Sized + Send + Sync + 'static {
18 fn parse_identifier(
19 first: Token<TSXToken, crate::TokenStart>,
20 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
21 ) -> ParseResult<(String, Span, Self)>;
22
23 fn is_private(&self) -> bool;
24
25 fn new_public() -> Self;
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30#[apply(derive_ASTNode)]
31pub struct AlwaysPublic;
32
33#[allow(dead_code)]
35impl PropertyKeyKind for AlwaysPublic {
40 fn parse_identifier(
41 first: Token<TSXToken, crate::TokenStart>,
42 _reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
43 ) -> ParseResult<(String, Span, Self)> {
44 token_as_identifier(first, "property key")
45 .map(|(name, position)| (name, position, Self::new_public()))
46 }
47
48 fn is_private(&self) -> bool {
49 false
50 }
51
52 fn new_public() -> Self {
53 AlwaysPublic
54 }
55}
56
57#[derive(Debug, Clone, PartialEq, Eq)]
58#[apply(derive_ASTNode)]
59pub enum PublicOrPrivate {
60 Public,
61 Private,
62}
63
64#[allow(dead_code)]
66impl PropertyKeyKind for PublicOrPrivate {
71 fn parse_identifier(
72 first: Token<TSXToken, crate::TokenStart>,
73 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
74 ) -> ParseResult<(String, Span, Self)> {
75 if matches!(first.0, TSXToken::HashTag) {
76 token_as_identifier(reader.next().ok_or_else(parse_lexing_error)?, "property key")
77 .map(|(name, position)| (name, position, Self::Private))
78 } else {
79 token_as_identifier(first, "property key")
80 .map(|(name, position)| (name, position, Self::Public))
81 }
82 }
83
84 fn is_private(&self) -> bool {
85 matches!(self, Self::Private)
86 }
87
88 fn new_public() -> Self {
89 Self::Public
90 }
91}
92
93#[apply(derive_ASTNode)]
95#[derive(Debug, PartialEq, Eq, Clone, get_field_by_type::GetFieldByType)]
96#[get_field_by_type_target(Span)]
97pub enum PropertyKey<T: PropertyKeyKind> {
98 Identifier(String, Span, T),
99 StringLiteral(String, Quoted, Span),
100 NumberLiteral(NumberRepresentation, Span),
101 Computed(Box<Expression>, Span),
103}
104
105impl<U: PropertyKeyKind> PropertyKey<U> {
106 pub fn is_private(&self) -> bool {
107 match self {
108 PropertyKey::Identifier(_, _, p) => U::is_private(p),
109 _ => false,
110 }
111 }
112}
113
114impl<U: PropertyKeyKind> PartialEq<str> for PropertyKey<U> {
115 fn eq(&self, other: &str) -> bool {
116 match self {
117 PropertyKey::Identifier(name, _, _) | PropertyKey::StringLiteral(name, _, _) => {
118 name == other
119 }
120 PropertyKey::NumberLiteral(_, _) | PropertyKey::Computed(_, _) => false,
121 }
122 }
123}
124
125impl<U: PropertyKeyKind> ASTNode for PropertyKey<U> {
126 fn get_position(&self) -> Span {
127 *self.get()
128 }
129
130 fn from_reader(
131 reader: &mut impl TokenReader<TSXToken, crate::TokenStart>,
132 state: &mut crate::ParsingState,
133 options: &ParseOptions,
134 ) -> ParseResult<Self> {
135 match reader.next().ok_or_else(parse_lexing_error)? {
136 Token(TSXToken::StringLiteral(content, quoted), start) => {
137 let position = start.with_length(content.len() + 2);
138 Ok(Self::StringLiteral(content, quoted, position))
139 }
140 Token(TSXToken::NumberLiteral(value), start) => {
141 let position = start.with_length(value.len());
142 match value.parse::<NumberRepresentation>() {
143 Ok(number) => Ok(Self::NumberLiteral(number, position)),
144 Err(_) => {
145 Err(crate::ParseError::new(
147 crate::ParseErrors::InvalidNumberLiteral,
148 position,
149 ))
150 }
151 }
152 }
153 Token(TSXToken::OpenBracket, start) => {
154 let expression = Expression::from_reader(reader, state, options)?;
155 let end = reader.expect_next_get_end(TSXToken::CloseBracket)?;
156 Ok(Self::Computed(Box::new(expression), start.union(end)))
157 }
158 token => {
159 if token.0.is_comment() {
160 Self::from_reader(reader, state, options)
162 } else {
163 let (name, position, private) = U::parse_identifier(token, reader)?;
164 Ok(Self::Identifier(name, position, private))
165 }
166 }
167 }
168 }
169
170 fn to_string_from_buffer<T: source_map::ToString>(
171 &self,
172 buf: &mut T,
173 options: &crate::ToStringOptions,
174 local: crate::LocalToStringInformation,
175 ) {
176 match self {
177 Self::Identifier(ident, _pos, _) => buf.push_str(ident.as_str()),
178 Self::NumberLiteral(number, _) => buf.push_str(&number.to_string()),
179 Self::StringLiteral(string, quoted, _) => {
180 buf.push(quoted.as_char());
181 buf.push_str(string.as_str());
182 buf.push(quoted.as_char());
183 }
184 Self::Computed(expression, _) => {
185 buf.push('[');
186 expression.to_string_from_buffer(buf, options, local);
187 buf.push(']');
188 }
189 }
190 }
191}
192
193impl Visitable for PropertyKey<PublicOrPrivate> {
195 fn visit<TData>(
196 &self,
197 visitors: &mut (impl crate::VisitorReceiver<TData> + ?Sized),
198 data: &mut TData,
199 _options: &VisitOptions,
200 chain: &mut Annex<Chain>,
201 ) {
202 visitors.visit_variable(
203 &crate::visiting::ImmutableVariableOrProperty::ClassPropertyKey(self),
204 data,
205 chain,
206 );
207 }
208
209 fn visit_mut<TData>(
210 &mut self,
211 visitors: &mut (impl crate::VisitorMutReceiver<TData> + ?Sized),
212 data: &mut TData,
213 _options: &VisitOptions,
214 chain: &mut Annex<Chain>,
215 ) {
216 visitors.visit_variable_mut(
217 &mut crate::visiting::MutableVariableOrProperty::ClassPropertyKey(self),
218 data,
219 chain,
220 );
221 }
222}
223
224impl Visitable for PropertyKey<AlwaysPublic> {
225 fn visit<TData>(
226 &self,
227 visitors: &mut (impl crate::VisitorReceiver<TData> + ?Sized),
228 data: &mut TData,
229 _options: &VisitOptions,
230 chain: &mut Annex<Chain>,
231 ) {
232 visitors.visit_variable(
233 &crate::visiting::ImmutableVariableOrProperty::ObjectPropertyKey(self),
234 data,
235 chain,
236 );
237 }
238
239 fn visit_mut<TData>(
240 &mut self,
241 visitors: &mut (impl crate::VisitorMutReceiver<TData> + ?Sized),
242 data: &mut TData,
243 _options: &VisitOptions,
244 chain: &mut Annex<Chain>,
245 ) {
246 visitors.visit_variable_mut(
247 &mut crate::visiting::MutableVariableOrProperty::ObjectPropertyKey(self),
248 data,
249 chain,
250 );
251 }
252}