1+ #[ cfg( feature = "napi" ) ]
2+ use std:: borrow:: Cow ;
13use std:: path:: Path ;
24
35use oxc_allocator:: AllocatorPool ;
@@ -17,6 +19,8 @@ pub struct SourceFormatter {
1719 allocator_pool : AllocatorPool ,
1820 format_options : FormatOptions ,
1921 #[ cfg( feature = "napi" ) ]
22+ pub is_sort_package_json : bool ,
23+ #[ cfg( feature = "napi" ) ]
2024 external_formatter : Option < super :: ExternalFormatter > ,
2125}
2226
@@ -26,6 +30,8 @@ impl SourceFormatter {
2630 allocator_pool : AllocatorPool :: new ( num_of_threads) ,
2731 format_options,
2832 #[ cfg( feature = "napi" ) ]
33+ is_sort_package_json : false ,
34+ #[ cfg( feature = "napi" ) ]
2935 external_formatter : None ,
3036 }
3137 }
@@ -35,25 +41,47 @@ impl SourceFormatter {
3541 pub fn with_external_formatter (
3642 mut self ,
3743 external_formatter : Option < super :: ExternalFormatter > ,
44+ sort_package_json : bool ,
3845 ) -> Self {
3946 self . external_formatter = external_formatter;
47+ self . is_sort_package_json = sort_package_json;
4048 self
4149 }
4250
4351 /// Format a file based on its source type.
4452 pub fn format ( & self , entry : & FormatFileSource , source_text : & str ) -> FormatResult {
45- match entry {
53+ let result = match entry {
4654 FormatFileSource :: OxcFormatter { path, source_type } => {
4755 self . format_by_oxc_formatter ( source_text, path, * source_type)
4856 }
4957 #[ cfg( feature = "napi" ) ]
5058 FormatFileSource :: ExternalFormatter { path, parser_name } => {
51- self . format_by_external_formatter ( source_text, path, parser_name)
59+ let text_to_format: Cow < ' _ , str > =
60+ if self . is_sort_package_json && entry. is_package_json ( ) {
61+ match sort_package_json:: sort_package_json ( source_text) {
62+ Ok ( sorted) => Cow :: Owned ( sorted) ,
63+ Err ( err) => {
64+ return FormatResult :: Error ( vec ! [ OxcDiagnostic :: error( format!(
65+ "Failed to sort package.json: {}\n {err}" ,
66+ path. display( )
67+ ) ) ] ) ;
68+ }
69+ }
70+ } else {
71+ Cow :: Borrowed ( source_text)
72+ } ;
73+
74+ self . format_by_external_formatter ( & text_to_format, path, parser_name)
5275 }
5376 #[ cfg( not( feature = "napi" ) ) ]
5477 FormatFileSource :: ExternalFormatter { .. } => {
5578 unreachable ! ( "If `napi` feature is disabled, this should not be passed here" )
5679 }
80+ } ;
81+
82+ match result {
83+ Ok ( code) => FormatResult :: Success { is_changed : source_text != code, code } ,
84+ Err ( err) => FormatResult :: Error ( vec ! [ err] ) ,
5785 }
5886 }
5987
@@ -63,15 +91,16 @@ impl SourceFormatter {
6391 source_text : & str ,
6492 path : & Path ,
6593 source_type : SourceType ,
66- ) -> FormatResult {
94+ ) -> Result < String , OxcDiagnostic > {
6795 let source_type = enable_jsx_source_type ( source_type) ;
6896 let allocator = self . allocator_pool . get ( ) ;
6997
7098 let ret = Parser :: new ( & allocator, source_text, source_type)
7199 . with_options ( get_parse_options ( ) )
72100 . parse ( ) ;
73101 if !ret. errors . is_empty ( ) {
74- return FormatResult :: Error ( ret. errors ) ;
102+ // Return the first error for simplicity
103+ return Err ( ret. errors . into_iter ( ) . next ( ) . unwrap ( ) ) ;
75104 }
76105
77106 let base_formatter = Formatter :: new ( & allocator, self . format_options . clone ( ) ) ;
@@ -92,25 +121,23 @@ impl SourceFormatter {
92121 #[ cfg( not( feature = "napi" ) ) ]
93122 let formatted = base_formatter. format ( & ret. program ) ;
94123
95- let code = match formatted. print ( ) {
96- Ok ( printed) => printed. into_code ( ) ,
97- Err ( err) => {
98- return FormatResult :: Error ( vec ! [ OxcDiagnostic :: error( format!(
99- "Failed to print formatted code: {}\n {err}" ,
100- path. display( )
101- ) ) ] ) ;
102- }
103- } ;
124+ let code = formatted. print ( ) . map_err ( |err| {
125+ OxcDiagnostic :: error ( format ! (
126+ "Failed to print formatted code: {}\n {err}" ,
127+ path. display( )
128+ ) )
129+ } ) ?;
104130
105131 #[ cfg( feature = "detect_code_removal" ) ]
106132 {
107- if let Some ( diff) = oxc_formatter:: detect_code_removal ( source_text, & code, source_type)
133+ if let Some ( diff) =
134+ oxc_formatter:: detect_code_removal ( source_text, code. as_code ( ) , source_type)
108135 {
109136 unreachable ! ( "Code removal detected in `{}`:\n {diff}" , path. to_string_lossy( ) ) ;
110137 }
111138 }
112139
113- FormatResult :: Success { is_changed : source_text != code, code }
140+ Ok ( code. into_code ( ) )
114141 }
115142
116143 /// Format non-JS/TS file using external formatter (Prettier).
@@ -120,7 +147,7 @@ impl SourceFormatter {
120147 source_text : & str ,
121148 path : & Path ,
122149 parser_name : & str ,
123- ) -> FormatResult {
150+ ) -> Result < String , OxcDiagnostic > {
124151 let external_formatter = self
125152 . external_formatter
126153 . as_ref ( )
@@ -136,12 +163,11 @@ impl SourceFormatter {
136163 // (without supporting `overrides` in config file)
137164 let file_name = path. file_name ( ) . and_then ( |s| s. to_str ( ) ) . unwrap_or ( "" ) ;
138165
139- match external_formatter. format_file ( parser_name, file_name, source_text) {
140- Ok ( code) => FormatResult :: Success { is_changed : source_text != code, code } ,
141- Err ( err) => FormatResult :: Error ( vec ! [ OxcDiagnostic :: error( format!(
166+ external_formatter. format_file ( parser_name, file_name, source_text) . map_err ( |err| {
167+ OxcDiagnostic :: error ( format ! (
142168 "Failed to format file with external formatter: {}\n {err}" ,
143169 path. display( )
144- ) ) ] ) ,
145- }
170+ ) )
171+ } )
146172 }
147173}
0 commit comments