@@ -32,8 +32,8 @@ impl<'a> IsolatedDeclarations<'a> {
32
32
}
33
33
34
34
pub fn report_property_key ( & self , key : & PropertyKey < ' a > , computed : bool ) -> bool {
35
- if computed && self . is_literal_key ( key) {
36
- computed_property_name ( key. span ( ) ) ;
35
+ if computed && ! self . is_literal_key ( key) {
36
+ self . error ( computed_property_name ( key. span ( ) ) ) ;
37
37
true
38
38
} else {
39
39
false
@@ -51,7 +51,7 @@ impl<'a> IsolatedDeclarations<'a> {
51
51
}
52
52
}
53
53
54
- pub fn transform_class_property_definition (
54
+ fn transform_class_property_definition (
55
55
& self ,
56
56
property : & PropertyDefinition < ' a > ,
57
57
) -> ClassElement < ' a > {
@@ -95,31 +95,14 @@ impl<'a> IsolatedDeclarations<'a> {
95
95
)
96
96
}
97
97
98
- pub fn transform_class_method_definition (
98
+ fn transform_class_method_definition (
99
99
& self ,
100
100
definition : & MethodDefinition < ' a > ,
101
101
params : Box < ' a , FormalParameters < ' a > > ,
102
102
return_type : Option < Box < ' a , TSTypeAnnotation < ' a > > > ,
103
103
) -> ClassElement < ' a > {
104
104
let function = & definition. value ;
105
105
106
- if definition. accessibility . is_some_and ( |a| a. is_private ( ) ) {
107
- let r#type = match definition. r#type {
108
- MethodDefinitionType :: MethodDefinition => {
109
- PropertyDefinitionType :: PropertyDefinition
110
- }
111
- MethodDefinitionType :: TSAbstractMethodDefinition => {
112
- PropertyDefinitionType :: TSAbstractPropertyDefinition
113
- }
114
- } ;
115
- return self . create_class_property (
116
- r#type,
117
- self . ast . copy ( & definition. key ) ,
118
- definition. r#override ,
119
- self . transform_accessibility ( definition. accessibility ) ,
120
- ) ;
121
- }
122
-
123
106
let value = self . ast . function (
124
107
FunctionType :: TSEmptyBodyFunctionExpression ,
125
108
function. span ,
@@ -149,7 +132,7 @@ impl<'a> IsolatedDeclarations<'a> {
149
132
)
150
133
}
151
134
152
- pub fn create_class_property (
135
+ fn create_class_property (
153
136
& self ,
154
137
r#type : PropertyDefinitionType ,
155
138
key : PropertyKey < ' a > ,
@@ -174,7 +157,7 @@ impl<'a> IsolatedDeclarations<'a> {
174
157
)
175
158
}
176
159
177
- pub fn transform_formal_parameter_to_class_property (
160
+ fn transform_formal_parameter_to_class_property (
178
161
& self ,
179
162
param : & FormalParameter < ' a > ,
180
163
type_annotation : Option < Box < ' a , TSTypeAnnotation < ' a > > > ,
@@ -202,6 +185,69 @@ impl<'a> IsolatedDeclarations<'a> {
202
185
) )
203
186
}
204
187
188
+ fn transform_private_modifier_method ( & self , method : & MethodDefinition < ' a > ) -> ClassElement < ' a > {
189
+ match method. kind {
190
+ MethodDefinitionKind :: Method => {
191
+ let r#type = match method. r#type {
192
+ MethodDefinitionType :: MethodDefinition => {
193
+ PropertyDefinitionType :: PropertyDefinition
194
+ }
195
+ MethodDefinitionType :: TSAbstractMethodDefinition => {
196
+ PropertyDefinitionType :: TSAbstractPropertyDefinition
197
+ }
198
+ } ;
199
+ self . create_class_property (
200
+ r#type,
201
+ self . ast . copy ( & method. key ) ,
202
+ method. r#override ,
203
+ self . transform_accessibility ( method. accessibility ) ,
204
+ )
205
+ }
206
+ MethodDefinitionKind :: Get => {
207
+ let params = self . ast . formal_parameters (
208
+ SPAN ,
209
+ FormalParameterKind :: Signature ,
210
+ self . ast . new_vec ( ) ,
211
+ None ,
212
+ ) ;
213
+ self . transform_class_method_definition ( method, params, None )
214
+ }
215
+ MethodDefinitionKind :: Set => {
216
+ let params = self . create_formal_parameters (
217
+ self . ast . binding_pattern_identifier ( BindingIdentifier :: new (
218
+ SPAN ,
219
+ self . ast . new_atom ( "value" ) ,
220
+ ) ) ,
221
+ None ,
222
+ ) ;
223
+ self . transform_class_method_definition ( method, params, None )
224
+ }
225
+ MethodDefinitionKind :: Constructor => {
226
+ unreachable ! ( )
227
+ }
228
+ }
229
+ }
230
+
231
+ fn transform_constructor_params_to_class_properties (
232
+ & self ,
233
+ function : & Function < ' a > ,
234
+ params : & FormalParameters < ' a > ,
235
+ ) -> oxc_allocator:: Vec < ' a , ClassElement < ' a > > {
236
+ let mut elements = self . ast . new_vec ( ) ;
237
+ for ( index, param) in function. params . items . iter ( ) . enumerate ( ) {
238
+ if param. accessibility . is_some ( ) {
239
+ // transformed params will definitely have type annotation
240
+ let type_annotation = self . ast . copy ( & params. items [ index] . pattern . type_annotation ) ;
241
+ if let Some ( new_element) =
242
+ self . transform_formal_parameter_to_class_property ( param, type_annotation)
243
+ {
244
+ elements. push ( new_element) ;
245
+ }
246
+ }
247
+ }
248
+ elements
249
+ }
250
+
205
251
pub fn transform_class ( & self , decl : & Class < ' a > ) -> Option < Box < ' a , Class < ' a > > > {
206
252
if decl. is_declare ( ) {
207
253
return None ;
@@ -220,89 +266,95 @@ impl<'a> IsolatedDeclarations<'a> {
220
266
}
221
267
}
222
268
223
- let mut elements = self . ast . new_vec ( ) ;
224
- let mut has_private_key = false ;
225
- let mut accessor_return_types: FxHashMap < & Atom < ' a > , Option < Box < ' a , TSTypeAnnotation < ' a > > > > =
269
+ let mut inferred_accessor_type: FxHashMap < Atom < ' a > , Box < ' a , TSTypeAnnotation < ' a > > > =
226
270
FxHashMap :: default ( ) ;
227
271
228
- // Transform get accessor first, and collect return type.
229
- // The return type will be used to infer the type of the set accessor.
272
+ // Infer get accessor return type from set accessor
273
+ // Infer set accessor parameter type from get accessor
230
274
for element in & decl. body . body {
231
275
if let ClassElement :: MethodDefinition ( method) = element {
232
- if method. key . is_private_identifier ( ) {
233
- has_private_key = true ;
276
+ if method. key . is_private_identifier ( )
277
+ || method. accessibility . is_some_and ( |a| a. is_private ( ) )
278
+ || ( method. computed && !self . is_literal_key ( & method. key ) )
279
+ {
234
280
continue ;
235
281
}
236
- if self . report_property_key ( & method. key , method. computed ) {
282
+ let Some ( name) = method. key . static_name ( ) else {
283
+ continue ;
284
+ } ;
285
+ let name = self . ast . new_atom ( & name) ;
286
+ if inferred_accessor_type. contains_key ( & name) {
287
+ // We've inferred that accessor type already
237
288
continue ;
238
289
}
239
-
240
- if method. kind . is_get ( ) {
241
- if let PropertyKey :: StaticIdentifier ( ident) = & method. key {
242
- let function = & method. value ;
243
- let params = self . transform_formal_parameters ( & function. params ) ;
290
+ let function = & method. value ;
291
+ match method. kind {
292
+ MethodDefinitionKind :: Get => {
244
293
let return_type = self . infer_function_return_type ( function) ;
245
- if return_type . is_none ( ) {
246
- self . error ( accessor_must_have_explicit_return_type ( method . key . span ( ) ) ) ;
294
+ if let Some ( return_type ) = return_type {
295
+ inferred_accessor_type . insert ( name , self . ast . copy ( & return_type ) ) ;
247
296
}
248
- accessor_return_types. insert ( & ident. name , self . ast . copy ( & return_type) ) ;
249
- let element =
250
- self . transform_class_method_definition ( method, params, return_type) ;
251
- elements. push ( element) ;
252
- continue ;
253
297
}
298
+ MethodDefinitionKind :: Set => {
299
+ if let Some ( param) = function. params . items . first ( ) {
300
+ let type_annotation =
301
+ param. pattern . type_annotation . as_ref ( ) . map_or_else (
302
+ || {
303
+ self . infer_type_from_formal_parameter ( param)
304
+ . map ( |x| self . ast . ts_type_annotation ( SPAN , x) )
305
+ } ,
306
+ |t| Some ( self . ast . copy ( t) ) ,
307
+ ) ;
308
+ if let Some ( type_annotation) = type_annotation {
309
+ inferred_accessor_type. insert ( name, type_annotation) ;
310
+ }
311
+ }
312
+ }
313
+ _ => { }
254
314
}
255
315
}
256
- elements. push ( self . ast . copy ( element) ) ;
257
316
}
258
317
259
- let mut new_elements = self . ast . new_vec ( ) ;
260
- for element in elements. drain ( ..) {
318
+ let mut has_private_key = false ;
319
+ let mut elements = self . ast . new_vec ( ) ;
320
+ for element in & decl. body . body {
261
321
match element {
262
322
ClassElement :: StaticBlock ( _) => { }
263
323
ClassElement :: MethodDefinition ( ref method) => {
264
- // Transformed in the first loop
265
- if method. kind . is_get ( ) {
266
- new_elements. push ( element) ;
267
- continue ;
268
- }
269
324
if method. key . is_private_identifier ( ) {
270
325
has_private_key = true ;
271
326
continue ;
272
327
}
273
328
if self . report_property_key ( & method. key , method. computed ) {
274
329
continue ;
275
330
}
331
+ if method. accessibility . is_some_and ( |a| a. is_private ( ) ) {
332
+ elements. push ( self . transform_private_modifier_method ( method) ) ;
333
+ continue ;
334
+ }
276
335
let function = & method. value ;
277
336
let params = if method. kind . is_set ( ) {
278
- if let PropertyKey :: StaticIdentifier ( ident) = & method. key {
279
- self . transform_set_accessor_params (
280
- & function. params ,
281
- accessor_return_types. remove ( & ident. name ) . unwrap_or_default ( ) ,
282
- )
283
- } else {
284
- self . transform_formal_parameters ( & function. params )
285
- }
337
+ method. key . static_name ( ) . map_or_else (
338
+ || self . transform_formal_parameters ( & function. params ) ,
339
+ |n| {
340
+ self . transform_set_accessor_params (
341
+ & function. params ,
342
+ inferred_accessor_type
343
+ . get ( & self . ast . new_atom ( & n) )
344
+ . map ( |t| self . ast . copy ( t) ) ,
345
+ )
346
+ } ,
347
+ )
286
348
} else {
287
349
self . transform_formal_parameters ( & function. params )
288
350
} ;
289
351
290
352
if let MethodDefinitionKind :: Constructor = method. kind {
291
- for ( index, param) in function. params . items . iter ( ) . enumerate ( ) {
292
- if param. accessibility . is_some ( ) {
293
- // transformed params will definitely have type annotation
294
- let type_annotation =
295
- self . ast . copy ( & params. items [ index] . pattern . type_annotation ) ;
296
- if let Some ( new_element) = self
297
- . transform_formal_parameter_to_class_property (
298
- param,
299
- type_annotation,
300
- )
301
- {
302
- new_elements. push ( new_element) ;
303
- }
304
- }
305
- }
353
+ elements. extend (
354
+ self . transform_constructor_params_to_class_properties (
355
+ function, & params,
356
+ ) ,
357
+ ) ;
306
358
}
307
359
308
360
let return_type = match method. kind {
@@ -315,14 +367,24 @@ impl<'a> IsolatedDeclarations<'a> {
315
367
}
316
368
rt
317
369
}
318
- MethodDefinitionKind :: Set | MethodDefinitionKind :: Constructor => None ,
319
370
MethodDefinitionKind :: Get => {
320
- unreachable ! ( "get accessor should be transformed in the first loop" )
371
+ let rt = method. key . static_name ( ) . and_then ( |name| {
372
+ inferred_accessor_type
373
+ . get ( & self . ast . new_atom ( & name) )
374
+ . map ( |t| self . ast . copy ( t) )
375
+ } ) ;
376
+ if rt. is_none ( ) {
377
+ self . error ( accessor_must_have_explicit_return_type (
378
+ method. key . span ( ) ,
379
+ ) ) ;
380
+ }
381
+ rt
321
382
}
383
+ MethodDefinitionKind :: Set | MethodDefinitionKind :: Constructor => None ,
322
384
} ;
323
385
let new_element =
324
386
self . transform_class_method_definition ( method, params, return_type) ;
325
- new_elements . push ( new_element) ;
387
+ elements . push ( new_element) ;
326
388
}
327
389
ClassElement :: PropertyDefinition ( property) => {
328
390
if self . report_property_key ( & property. key , property. computed ) {
@@ -332,7 +394,7 @@ impl<'a> IsolatedDeclarations<'a> {
332
394
if property. key . is_private_identifier ( ) {
333
395
has_private_key = true ;
334
396
} else {
335
- new_elements . push ( self . transform_class_property_definition ( & property) ) ;
397
+ elements . push ( self . transform_class_property_definition ( property) ) ;
336
398
}
337
399
}
338
400
ClassElement :: AccessorProperty ( property) => {
@@ -355,9 +417,9 @@ impl<'a> IsolatedDeclarations<'a> {
355
417
property. r#static ,
356
418
self . ast . new_vec ( ) ,
357
419
) ;
358
- new_elements . push ( new_element) ;
420
+ elements . push ( new_element) ;
359
421
}
360
- ClassElement :: TSIndexSignature ( _) => new_elements . push ( element) ,
422
+ ClassElement :: TSIndexSignature ( _) => elements . push ( self . ast . copy ( element) ) ,
361
423
}
362
424
}
363
425
@@ -375,10 +437,10 @@ impl<'a> IsolatedDeclarations<'a> {
375
437
None , decorators,
376
438
) ;
377
439
378
- new_elements . insert ( 0 , element) ;
440
+ elements . insert ( 0 , element) ;
379
441
}
380
442
381
- let body = self . ast . class_body ( decl. body . span , new_elements ) ;
443
+ let body = self . ast . class_body ( decl. body . span , elements ) ;
382
444
383
445
let mut modifiers = self . modifiers_declare ( ) ;
384
446
if decl. modifiers . is_contains_abstract ( ) {
0 commit comments