@@ -5,6 +5,7 @@ use oxc_ast_macros::ast_meta;
55use oxc_estree:: {
66 CompactJSSerializer , CompactTSSerializer , ESTree , JsonSafeString , LoneSurrogatesString ,
77 PrettyJSSerializer , PrettyTSSerializer , SequenceSerializer , Serializer , StructSerializer ,
8+ ser:: AppendToConcat ,
89} ;
910use oxc_span:: GetSpan ;
1011
@@ -37,16 +38,7 @@ const JSON_CAPACITY_RATIO_PRETTY: usize = 80;
3738
3839impl Program < ' _ > {
3940 /// Serialize AST to ESTree JSON, including TypeScript fields.
40- pub fn to_estree_ts_json ( & mut self ) -> String {
41- // Set start span to first token of first directive or statement. This is required because
42- // unlike Acorn, TS-ESLint excludes whitespace and comments from the `Program` start span.
43- // See https://github.com/oxc-project/oxc/pull/10134 for more info.
44- if let Some ( first_directive) = self . directives . first ( ) {
45- self . span . start = first_directive. span . start ;
46- } else if let Some ( first_stmt) = self . body . first ( ) {
47- self . span . start = first_stmt. span ( ) . start ;
48- }
49-
41+ pub fn to_estree_ts_json ( & self ) -> String {
5042 let capacity = self . source_text . len ( ) * JSON_CAPACITY_RATIO_COMPACT ;
5143 let mut serializer = CompactTSSerializer :: with_capacity ( capacity) ;
5244 self . serialize ( & mut serializer) ;
@@ -62,16 +54,7 @@ impl Program<'_> {
6254 }
6355
6456 /// Serialize AST to pretty-printed ESTree JSON, including TypeScript fields.
65- pub fn to_pretty_estree_ts_json ( & mut self ) -> String {
66- // Set start span to first token of first directive or statement. This is required because
67- // unlike Acorn, TS-ESLint excludes whitespace and comments from the `Program` start span.
68- // See https://github.com/oxc-project/oxc/pull/10134 for more info.
69- if let Some ( first_directive) = self . directives . first ( ) {
70- self . span . start = first_directive. span . start ;
71- } else if let Some ( first_stmt) = self . body . first ( ) {
72- self . span . start = first_stmt. span ( ) . start ;
73- }
74-
57+ pub fn to_pretty_estree_ts_json ( & self ) -> String {
7558 let capacity = self . source_text . len ( ) * JSON_CAPACITY_RATIO_PRETTY ;
7659 let mut serializer = PrettyTSSerializer :: with_capacity ( capacity) ;
7760 self . serialize ( & mut serializer) ;
@@ -87,6 +70,65 @@ impl Program<'_> {
8770 }
8871}
8972
73+ // --------------------
74+ // Program
75+ // --------------------
76+
77+ /// Serializer for `Program`.
78+ ///
79+ /// In TS AST, set start span to start of first directive or statement.
80+ /// This is required because unlike Acorn, TS-ESLint excludes whitespace and comments
81+ /// from the `Program` start span.
82+ /// See <https://github.com/oxc-project/oxc/pull/10134> for more info.
83+ #[ ast_meta]
84+ #[ estree( raw_deser = "
85+ const body = DESER[Vec<Directive>](POS_OFFSET.directives);
86+ body.push(...DESER[Vec<Statement>](POS_OFFSET.body));
87+ let start = DESER[u32](POS_OFFSET.span.start);
88+ /* IF_TS */
89+ if (body.length > 0) start = body[0].start;
90+ /* END_IF_TS */
91+ const program = {
92+ type: 'Program',
93+ start,
94+ end: DESER[u32](POS_OFFSET.span.end),
95+ body,
96+ sourceType: DESER[ModuleKind](POS_OFFSET.source_type.module_kind),
97+ hashbang: DESER[Option<Hashbang>](POS_OFFSET.hashbang),
98+ };
99+ program
100+ " ) ]
101+ pub struct ProgramConverter < ' a , ' b > ( pub & ' b Program < ' a > ) ;
102+
103+ impl ESTree for ProgramConverter < ' _ , ' _ > {
104+ fn serialize < S : Serializer > ( & self , serializer : S ) {
105+ let program = self . 0 ;
106+ let span_start = if S :: INCLUDE_TS_FIELDS {
107+ if let Some ( first_directive) = program. directives . first ( ) {
108+ first_directive. span . start
109+ } else if let Some ( first_stmt) = program. body . first ( ) {
110+ first_stmt. span ( ) . start
111+ } else {
112+ program. span . start
113+ }
114+ } else {
115+ program. span . start
116+ } ;
117+
118+ let mut state = serializer. serialize_struct ( ) ;
119+ state. serialize_field ( "type" , & JsonSafeString ( "Program" ) ) ;
120+ state. serialize_field ( "start" , & span_start) ;
121+ state. serialize_field ( "end" , & program. span . end ) ;
122+ state. serialize_field (
123+ "body" ,
124+ & AppendToConcat { array : & program. directives , after : & program. body } ,
125+ ) ;
126+ state. serialize_field ( "sourceType" , & program. source_type . module_kind ( ) ) ;
127+ state. serialize_field ( "hashbang" , & program. hashbang ) ;
128+ state. end ( ) ;
129+ }
130+ }
131+
90132// --------------------
91133// Basic types
92134// --------------------
0 commit comments