@@ -159,16 +159,16 @@ pub struct FormatConfig {
159159 /// - Default: `false`
160160 #[ serde( skip_serializing_if = "Option::is_none" ) ]
161161 pub single_attribute_per_line : Option < bool > ,
162+ /// When expressions wrap lines, print operators at the start of new lines (`"start"`)
163+ /// or at the end of previous lines (`"end"`).
164+ ///
165+ /// - Languages: JS, JSX, TS, TSX
166+ /// - Default: `"end"`
167+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
168+ pub experimental_operator_position : Option < OperatorPositionConfig > ,
162169
163- // NOTE: These experimental options are not yet supported.
170+ // NOTE: This experimental option is not yet supported.
164171 // Reject at deserialize time so all entry paths (base / overrides / NAPI `resolve()`) are covered uniformly.
165- #[ serde(
166- skip_serializing_if = "Option::is_none" ,
167- deserialize_with = "reject_experimental_operator_position" ,
168- default
169- ) ]
170- #[ schemars( skip) ]
171- pub experimental_operator_position : Option < String > ,
172172 #[ serde(
173173 skip_serializing_if = "Option::is_none" ,
174174 deserialize_with = "reject_experimental_ternaries" ,
@@ -354,17 +354,6 @@ impl FormatConfig {
354354
355355// ---
356356
357- fn reject_experimental_operator_position < ' de , D > ( d : D ) -> Result < Option < String > , D :: Error >
358- where
359- D : serde:: Deserializer < ' de > ,
360- {
361- let v = Option :: < String > :: deserialize ( d) ?;
362- if v. is_some ( ) {
363- return Err ( serde:: de:: Error :: custom ( "Unsupported option: `experimentalOperatorPosition`" ) ) ;
364- }
365- Ok ( v)
366- }
367-
368357fn reject_experimental_ternaries < ' de , D > ( d : D ) -> Result < Option < bool > , D :: Error >
369358where
370359 D : serde:: Deserializer < ' de > ,
@@ -416,6 +405,13 @@ pub enum ObjectWrapConfig {
416405 Collapse ,
417406}
418407
408+ #[ derive( Debug , Clone , Copy , Deserialize , Serialize , JsonSchema ) ]
409+ #[ serde( rename_all = "lowercase" ) ]
410+ pub enum OperatorPositionConfig {
411+ Start ,
412+ End ,
413+ }
414+
419415#[ derive( Debug , Clone , Copy , Deserialize , Serialize , JsonSchema ) ]
420416#[ serde( rename_all = "lowercase" ) ]
421417pub enum EmbeddedLanguageFormattingConfig {
@@ -1007,13 +1003,6 @@ mod tests_json_deep_merge {
10071003mod tests_reject_experimental {
10081004 use super :: * ;
10091005
1010- #[ test]
1011- fn test_reject_experimental_operator_position_in_base ( ) {
1012- let json = r#"{ "experimentalOperatorPosition": "start" }"# ;
1013- let err = serde_json:: from_str :: < FormatConfig > ( json) . unwrap_err ( ) ;
1014- assert ! ( err. to_string( ) . contains( "experimentalOperatorPosition" ) ) ;
1015- }
1016-
10171006 #[ test]
10181007 fn test_reject_experimental_ternaries_in_base ( ) {
10191008 let json = r#"{ "experimentalTernaries": true }"# ;
@@ -1024,17 +1013,6 @@ mod tests_reject_experimental {
10241013 #[ test]
10251014 fn test_reject_experimental_in_overrides ( ) {
10261015 // `OxfmtOverrideConfig.options: FormatConfig` so the same deserialize_with applies
1027- let json = r#"{
1028- "overrides": [
1029- {
1030- "files": ["*.ts"],
1031- "options": { "experimentalOperatorPosition": "end" }
1032- }
1033- ]
1034- }"# ;
1035- let err = serde_json:: from_str :: < Oxfmtrc > ( json) . unwrap_err ( ) ;
1036- assert ! ( err. to_string( ) . contains( "experimentalOperatorPosition" ) ) ;
1037-
10381016 let json = r#"{
10391017 "overrides": [
10401018 {
@@ -1046,23 +1024,4 @@ mod tests_reject_experimental {
10461024 let err = serde_json:: from_str :: < Oxfmtrc > ( json) . unwrap_err ( ) ;
10471025 assert ! ( err. to_string( ) . contains( "experimentalTernaries" ) ) ;
10481026 }
1049-
1050- #[ test]
1051- fn test_reject_experimental_via_napi_resolve_path ( ) {
1052- // NAPI `resolve()` does `serde_json::from_value::<FormatConfig>(raw_config)`,
1053- // which goes through the same deserialize_with.
1054- let raw = serde_json:: json!( { "experimentalTernaries" : true } ) ;
1055- let err = serde_json:: from_value :: < FormatConfig > ( raw) . unwrap_err ( ) ;
1056- assert ! ( err. to_string( ) . contains( "experimentalTernaries" ) ) ;
1057- }
1058-
1059- #[ test]
1060- fn test_unset_experimental_does_not_fail ( ) {
1061- // Sanity: omitting both fields parses cleanly
1062- let json = r#"{ "printWidth": 120 }"# ;
1063- let config: FormatConfig = serde_json:: from_str ( json) . unwrap ( ) ;
1064- assert_eq ! ( config. print_width, Some ( 120 ) ) ;
1065- assert ! ( config. experimental_operator_position. is_none( ) ) ;
1066- assert ! ( config. experimental_ternaries. is_none( ) ) ;
1067- }
10681027}
0 commit comments