@@ -3,7 +3,7 @@ use crate::{
3
3
grammar:: DocParseResult ,
4
4
kind:: { LuaOpKind , LuaSyntaxKind , LuaTokenKind , LuaTypeBinaryOperator , LuaTypeUnaryOperator } ,
5
5
lexer:: LuaDocLexerState ,
6
- parser:: { CompleteMarker , LuaDocParser , LuaDocParserState , MarkerEventContainer } ,
6
+ parser:: { CompleteMarker , LuaDocParser , LuaDocParserState , Marker , MarkerEventContainer } ,
7
7
parser_error:: LuaParseError ,
8
8
} ;
9
9
@@ -142,13 +142,7 @@ fn parse_simple_type(p: &mut LuaDocParser) -> DocParseResult {
142
142
143
143
fn parse_primary_type ( p : & mut LuaDocParser ) -> DocParseResult {
144
144
match p. current_token ( ) {
145
- LuaTokenKind :: TkLeftBrace => {
146
- if is_mapped_type_start ( p) {
147
- parse_mapped_type ( p)
148
- } else {
149
- parse_object_type ( p)
150
- }
151
- }
145
+ LuaTokenKind :: TkLeftBrace => parse_object_or_mapped_type ( p) ,
152
146
LuaTokenKind :: TkLeftBracket => parse_tuple_type ( p) ,
153
147
LuaTokenKind :: TkLeftParen => parse_paren_type ( p) ,
154
148
LuaTokenKind :: TkString
@@ -171,87 +165,45 @@ fn parse_primary_type(p: &mut LuaDocParser) -> DocParseResult {
171
165
}
172
166
}
173
167
174
- /// 判断是否是映射类型.
175
- ///
176
- /// 这里与`TS`保持一致, 即第一个 key 必须为`[]` 且内部必须包含 `in`.
177
- fn is_mapped_type_start ( p : & LuaDocParser ) -> bool {
178
- let text = p. origin_text ( ) ;
179
- let start = p. current_token_range ( ) . end_offset ( ) ;
180
- let rest = match text. get ( start..) {
181
- Some ( value) => value,
182
- None => return false ,
183
- } ;
184
-
185
- let mut trimmed = rest. trim_start_matches ( char:: is_whitespace) ;
186
-
187
- if let Some ( after_dashes) = trimmed. strip_prefix ( "---" ) {
188
- trimmed = after_dashes. trim_start_matches ( char:: is_whitespace) ;
189
- }
190
-
191
- if !trimmed. starts_with ( '[' ) {
192
- return false ;
193
- }
194
-
195
- let after_left_bracket = & trimmed[ 1 ..] ;
196
- let rb_pos = match after_left_bracket. find ( ']' ) {
197
- Some ( pos) => pos,
198
- None => return false ,
199
- } ;
200
-
201
- let content = & after_left_bracket[ ..rb_pos] ;
202
- let mut seen_identifier = false ;
203
- let mut token_start: Option < usize > = None ;
168
+ // [Property in Type]: Type;
169
+ // [Property in keyof Type]: Type;
170
+ fn parse_mapped_type ( p : & mut LuaDocParser , m : Marker ) -> DocParseResult {
171
+ p. set_parser_state ( LuaDocParserState :: Mapped ) ;
204
172
205
- for ( idx, ch) in content. char_indices ( ) {
206
- if ch == '_' || ch. is_alphanumeric ( ) {
207
- if token_start. is_none ( ) {
208
- token_start = Some ( idx) ;
209
- }
210
- continue ;
173
+ match p. current_token ( ) {
174
+ LuaTokenKind :: TkPlus | LuaTokenKind :: TkMinus => {
175
+ p. bump ( ) ;
176
+ expect_token ( p, LuaTokenKind :: TkDocReadonly ) ?;
211
177
}
212
-
213
- if let Some ( start_idx) = token_start. take ( ) {
214
- let token = & content[ start_idx..idx] ;
215
- if token == "in" {
216
- return seen_identifier;
217
- }
218
- seen_identifier = true ;
178
+ LuaTokenKind :: TkDocReadonly => {
179
+ p. bump ( ) ;
219
180
}
220
- }
221
-
222
- if let Some ( start_idx) = token_start {
223
- if & content[ start_idx..] == "in" {
224
- return seen_identifier;
181
+ LuaTokenKind :: TkLeftBracket => { }
182
+ _ => {
183
+ return Err ( LuaParseError :: doc_error_from (
184
+ & t ! ( "expect mapped field" ) ,
185
+ p. current_token_range ( ) ,
186
+ ) ) ;
225
187
}
226
188
}
227
189
228
- false
229
- }
230
-
231
- // [Property in Type]: Type;
232
- // [Property in keyof Type]: Type;
233
- fn parse_mapped_type ( p : & mut LuaDocParser ) -> DocParseResult {
234
- p. set_parser_state ( LuaDocParserState :: Mapped ) ;
235
- let m = p. mark ( LuaSyntaxKind :: TypeMapped ) ;
236
- p. bump ( ) ;
237
-
238
- if p. current_token ( ) != LuaTokenKind :: TkLeftBracket {
239
- return Err ( LuaParseError :: doc_error_from (
240
- & t ! ( "expect mapped field" ) ,
241
- p. current_token_range ( ) ,
242
- ) ) ;
243
- }
244
- // key
245
190
parse_mapped_key ( p) ?;
246
- if p. current_token ( ) == LuaTokenKind :: TkDocQuestion {
247
- p. bump ( ) ;
191
+
192
+ match p. current_token ( ) {
193
+ LuaTokenKind :: TkPlus | LuaTokenKind :: TkMinus => {
194
+ p. bump ( ) ;
195
+ expect_token ( p, LuaTokenKind :: TkDocQuestion ) ?;
196
+ }
197
+ LuaTokenKind :: TkDocQuestion => {
198
+ p. bump ( ) ;
199
+ }
200
+ _ => { }
248
201
}
202
+
249
203
expect_token ( p, LuaTokenKind :: TkColon ) ?;
250
204
251
- // value
252
205
parse_type ( p) ?;
253
206
254
- // end
255
207
expect_token ( p, LuaTokenKind :: TkSemicolon ) ?;
256
208
expect_token ( p, LuaTokenKind :: TkRightBrace ) ?;
257
209
@@ -281,11 +233,27 @@ fn parse_mapped_key(p: &mut LuaDocParser) -> DocParseResult {
281
233
282
234
// { <name>: <type>, ... }
283
235
// { <name> : <type>, ... }
284
- fn parse_object_type ( p : & mut LuaDocParser ) -> DocParseResult {
285
- let m = p. mark ( LuaSyntaxKind :: TypeObject ) ;
236
+ fn parse_object_or_mapped_type ( p : & mut LuaDocParser ) -> DocParseResult {
237
+ p. set_lexer_state ( LuaDocLexerState :: Mapped ) ;
238
+ let mut m = p. mark ( LuaSyntaxKind :: TypeObject ) ;
286
239
p. bump ( ) ;
240
+ p. set_lexer_state ( LuaDocLexerState :: Normal ) ;
287
241
288
242
if p. current_token ( ) != LuaTokenKind :: TkRightBrace {
243
+ match p. current_token ( ) {
244
+ LuaTokenKind :: TkPlus | LuaTokenKind :: TkMinus | LuaTokenKind :: TkDocReadonly => {
245
+ m. set_kind ( p, LuaSyntaxKind :: TypeMapped ) ;
246
+ return parse_mapped_type ( p, m) ;
247
+ }
248
+ LuaTokenKind :: TkLeftBracket => {
249
+ if is_mapped_type ( p) {
250
+ m. set_kind ( p, LuaSyntaxKind :: TypeMapped ) ;
251
+ return parse_mapped_type ( p, m) ;
252
+ }
253
+ }
254
+ _ => { }
255
+ }
256
+
289
257
parse_typed_field ( p) ?;
290
258
while p. current_token ( ) == LuaTokenKind :: TkComma {
291
259
p. bump ( ) ;
@@ -301,6 +269,24 @@ fn parse_object_type(p: &mut LuaDocParser) -> DocParseResult {
301
269
Ok ( m. complete ( p) )
302
270
}
303
271
272
+ /// 判断是否为 mapped type
273
+ fn is_mapped_type ( p : & LuaDocParser ) -> bool {
274
+ let mut lexer = p. lexer . clone ( ) ;
275
+
276
+ loop {
277
+ let kind = lexer. lex ( ) ;
278
+ match kind {
279
+ LuaTokenKind :: TkIn => return true ,
280
+ LuaTokenKind :: TkLeftBracket | LuaTokenKind :: TkRightBracket => return false ,
281
+ LuaTokenKind :: TkEof => return false ,
282
+ LuaTokenKind :: TkWhitespace
283
+ | LuaTokenKind :: TkDocContinue
284
+ | LuaTokenKind :: TkEndOfLine => { }
285
+ _ => { }
286
+ }
287
+ }
288
+ }
289
+
304
290
// <name> : <type>
305
291
// [<number>] : <type>
306
292
// [<string>] : <type>
0 commit comments