parse_js/parse/
class_or_object.rs1use super::expr::Asi;
2use super::pattern::is_valid_pattern_identifier;
3use super::pattern::ParsePatternRules;
4use super::ParseCtx;
5use super::Parser;
6use crate::ast::ClassOrObjectMemberKey;
7use crate::ast::ClassOrObjectMemberValue;
8use crate::ast::Node;
9use crate::ast::Syntax;
10use crate::error::SyntaxResult;
11use crate::lex::KEYWORDS_MAPPING;
12use crate::loc::Loc;
13use crate::token::TokenType;
14
15pub struct ParseClassBodyResult {
16 pub members: Vec<Node>, pub end: Loc,
18}
19
20pub struct ParseClassOrObjectMemberResult {
21 pub key: ClassOrObjectMemberKey,
22 pub key_loc: Loc,
23 pub value: ClassOrObjectMemberValue,
24 pub value_loc: Loc,
25}
26
27impl<'a> Parser<'a> {
28 pub fn parse_class_body(&mut self, ctx: ParseCtx) -> SyntaxResult<ParseClassBodyResult> {
29 self.require(TokenType::BraceOpen)?;
30 let mut members = Vec::new();
31 while self.peek()?.typ != TokenType::BraceClose {
32 let static_ = self.consume_if(TokenType::KeywordStatic)?.match_loc();
34 let ParseClassOrObjectMemberResult {
35 key,
36 key_loc,
37 value,
38 value_loc,
39 } = self.parse_class_or_object_member(
40 ctx,
41 TokenType::Equals,
42 TokenType::Semicolon,
43 &mut Asi::can(),
44 )?;
45 self.consume_if(TokenType::Semicolon)?;
46 members.push(Node::new(
47 key_loc.add_option(static_) + value_loc,
48 Syntax::ClassMember {
49 key,
50 static_: static_.is_some(),
51 value,
52 },
53 ));
54 }
55 let end = self.require(TokenType::BraceClose)?.loc;
56 Ok(ParseClassBodyResult { members, end })
57 }
58
59 pub fn parse_class_or_object_member(
65 &mut self,
66 ctx: ParseCtx,
67 value_delimiter: TokenType,
68 statement_delimiter: TokenType,
69 property_initialiser_asi: &mut Asi,
70 ) -> SyntaxResult<ParseClassOrObjectMemberResult> {
71 let checkpoint = self.checkpoint();
72 let mut is_getter = false;
73 let mut is_setter = false;
74 let mut is_async = false;
75 if self.consume_if(TokenType::KeywordGet)?.is_match() {
76 is_getter = true;
77 } else if self.consume_if(TokenType::KeywordSet)?.is_match() {
78 is_setter = true;
79 } else if self.consume_if(TokenType::KeywordAsync)?.is_match() {
80 is_async = true;
81 }
82 if is_getter || is_setter || is_async {
83 let next_tok = self.peek()?.typ;
84 if next_tok == value_delimiter || next_tok == TokenType::ParenthesisOpen {
85 self.restore_checkpoint(checkpoint);
87 is_getter = false;
88 is_setter = false;
89 is_async = false;
90 };
91 }
92 let is_generator = self.consume_if(TokenType::Asterisk)?.is_match();
93 let (key_loc, key) = if self.consume_if(TokenType::BracketOpen)?.is_match() {
94 let key = self.parse_expr(ctx, TokenType::BracketClose)?;
95 self.require(TokenType::BracketClose)?;
96 (key.loc, ClassOrObjectMemberKey::Computed(key))
97 } else {
98 let loc = if let Some(str) = self.consume_if(TokenType::LiteralString)?.match_loc() {
99 str
101 } else if let Some(num) = self.consume_if(TokenType::LiteralNumber)?.match_loc() {
102 num
104 } else if let Some(loc) = self.consume_if(TokenType::PrivateMember)?.match_loc() {
105 loc
106 } else if let Some(loc) = self
107 .consume_if_pred(|t| is_valid_pattern_identifier(t.typ, ctx.rules))?
108 .match_loc()
109 {
110 loc
111 } else {
112 self
113 .require_predicate(
114 |t| KEYWORDS_MAPPING.contains_key(&t),
115 "keyword or identifier",
116 )?
117 .loc
118 };
119 (loc, ClassOrObjectMemberKey::Direct(self.string(loc)))
120 };
121 let (value_loc, value) =
123 if is_generator || is_async || self.peek()?.typ == TokenType::ParenthesisOpen {
124 let parameters = self.parse_function_parameters(ctx)?;
125 let body = self.parse_function_body(ctx.with_rules(ParsePatternRules {
126 await_allowed: !is_async && ctx.rules.await_allowed,
127 yield_allowed: !is_generator && ctx.rules.yield_allowed,
128 }))?;
129 (body.loc, ClassOrObjectMemberValue::Method {
130 function: Node::new(body.loc, Syntax::Function {
131 arrow: false,
132 async_: is_async,
133 generator: is_generator,
134 parameters,
135 body,
136 }),
137 })
138 } else if is_getter {
139 let mut loc = self.require(TokenType::ParenthesisOpen)?.loc;
140 self.require(TokenType::ParenthesisClose)?;
141 let body = self.parse_function_body(ctx)?;
142 loc += body.loc;
143 (loc, ClassOrObjectMemberValue::Getter {
144 function: Node::new(loc, Syntax::Function {
145 arrow: false,
146 async_: false,
147 body,
148 generator: false,
149 parameters: Vec::new(),
150 }),
151 })
152 } else if is_setter {
153 let mut loc = self.require(TokenType::ParenthesisOpen)?.loc;
154 let param = self.parse_pattern(ctx)?;
155 self.require(TokenType::ParenthesisClose)?;
156 let body = self.parse_function_body(ctx)?;
157 loc += body.loc;
158 (loc, ClassOrObjectMemberValue::Setter {
159 function: Node::new(loc, Syntax::Function {
160 arrow: false,
161 async_: false,
162 generator: false,
163 body,
164 parameters: vec![Node::new(param.loc, Syntax::ParamDecl {
165 rest: false,
166 pattern: param,
167 default_value: None,
168 })],
169 }),
170 })
171 } else if match key {
172 ClassOrObjectMemberKey::Direct(_) => match self.peek()? {
173 t if t.typ == TokenType::BraceClose => true,
175 t if t.typ == statement_delimiter => true,
177 t if property_initialiser_asi.can_end_with_asi && t.preceded_by_line_terminator => true,
179 _ => false,
180 },
181 _ => false,
182 } {
183 (key_loc, ClassOrObjectMemberValue::Property {
184 initializer: None,
185 })
186 } else {
187 let loc_start = self.require(value_delimiter)?.loc;
188 let value = self.parse_expr_until_either_with_asi(
189 ctx,
190 statement_delimiter,
191 TokenType::BraceClose,
192 property_initialiser_asi,
193 )?;
194 (loc_start + value.loc, ClassOrObjectMemberValue::Property {
195 initializer: Some(value),
196 })
197 };
198 Ok(ParseClassOrObjectMemberResult {
199 key,
200 key_loc,
201 value,
202 value_loc,
203 })
204 }
205}