1+ use std:: collections:: HashMap ;
2+
13use crate :: config:: file_lines:: FileLines ;
24use crate :: config:: options:: { IgnoreList , WidthHeuristics } ;
35
@@ -50,6 +52,78 @@ impl ConfigType for IgnoreList {
5052 }
5153}
5254
55+ /// Store a map of all Unstable options used in in the configuration.
56+ #[ derive( Clone , Debug ) ]
57+ pub struct UnstableOptions {
58+ options : HashMap < & ' static str , String > ,
59+ }
60+
61+ impl UnstableOptions {
62+ /// Create a new UnstableOptions struct
63+ pub ( crate ) fn new ( ) -> Self {
64+ Self {
65+ options : HashMap :: new ( ) ,
66+ }
67+ }
68+
69+ /// Insert an unstable option and a user supplied value for that unstable option
70+ pub ( crate ) fn insert ( & mut self , option : & ' static str , user_supplied_value : String ) {
71+ self . options . insert ( option, user_supplied_value) ;
72+ }
73+
74+ /// Check if any unstable options have been set
75+ pub ( crate ) fn has_unstable_options ( & self ) -> bool {
76+ !self . options . is_empty ( )
77+ }
78+
79+ // primarily used for testing
80+ #[ allow( dead_code) ]
81+ pub ( crate ) fn options ( & self ) -> & HashMap < & ' static str , String > {
82+ & self . options
83+ }
84+
85+ /// Generate the Warning message
86+ pub fn warning_message ( & self ) -> Option < String > {
87+ if self . options . is_empty ( ) {
88+ return None ;
89+ }
90+ let mut result = String :: new ( ) ;
91+
92+ for ( k, v) in self . options . iter ( ) {
93+ result. push_str ( & format ! (
94+ "Warning: can't set `{} = {}`, unstable features are only \
95+ available in nightly channel.\n ",
96+ k, v,
97+ ) ) ;
98+ }
99+
100+ let upgrade_to_abort_message = "\n Set `abort_on_unrecognised_options = true` \
101+ to convert this warning into an error\n \n ";
102+
103+ result. push_str ( upgrade_to_abort_message) ;
104+
105+ Some ( result)
106+ }
107+
108+ /// Generate the Abort message
109+ pub fn abort_message ( & self ) -> Option < String > {
110+ if self . options . is_empty ( ) {
111+ return None ;
112+ }
113+
114+ let mut result = String :: new ( ) ;
115+ result. push_str ( "Can't set nightly options when using stable rustfmt\n " ) ;
116+
117+ for ( k, v) in self . options . iter ( ) {
118+ result. push_str ( & format ! ( " - `{} = {}`\n " , k, v) ) ;
119+ }
120+ let to_warning_message = "\n Set `abort_on_unrecognised_options = false` \
121+ to convert this error into a warning\n \n ";
122+ result. push_str ( to_warning_message) ;
123+ Some ( result)
124+ }
125+ }
126+
53127macro_rules! create_config {
54128 ( $( $i: ident: $ty: ty, $def: expr, $stb: expr, $( $dstring: expr ) ,+ ) ;+ $( ; ) * ) => (
55129 #[ cfg( test) ]
@@ -64,6 +138,8 @@ macro_rules! create_config {
64138 // if a license_template_path has been specified, successfully read, parsed and compiled
65139 // into a regex, it will be stored here
66140 pub license_template: Option <Regex >,
141+ // Unstable Options specified on the stable channel
142+ configured_unstable_options: UnstableOptions ,
67143 // For each config item, we store a bool indicating whether it has
68144 // been accessed and the value, and a bool whether the option was
69145 // manually initialised, or taken from the default,
@@ -145,21 +221,35 @@ macro_rules! create_config {
145221 ConfigWasSet ( self )
146222 }
147223
224+ /// Insert all unstable options and their values into the UnstableOptions struct.
225+ /// The only exception is the "abort_on_unrecognised_options", which helps
226+ /// determine if we should abort or warn when using unstable options on stable rustfmt
227+ #[ allow( unreachable_pub) ]
228+ pub fn insert_unstable_options( & mut self , option: & ' static str , value: String ) {
229+ if option == "abort_on_unrecognised_options" {
230+ return
231+ }
232+
233+ match option {
234+ $(
235+ stringify!( $i) => {
236+ // If its an unstable option then add it to the unstable list
237+ if !self . $i. 3 {
238+ self . configured_unstable_options. insert( option, value) ;
239+ }
240+ }
241+ ) +
242+ _ => panic!( "Unknown config key in override: {}" , option)
243+ }
244+
245+ }
246+
148247 fn fill_from_parsed_config( mut self , parsed: PartialConfig , dir: & Path ) -> Config {
149248 $(
150249 if let Some ( val) = parsed. $i {
151- if self . $i. 3 {
152- self . $i. 1 = true ;
153- self . $i. 2 = val;
154- } else {
155- if crate :: is_nightly_channel!( ) {
156- self . $i. 1 = true ;
157- self . $i. 2 = val;
158- } else {
159- eprintln!( "Warning: can't set `{} = {:?}`, unstable features are only \
160- available in nightly channel.", stringify!( $i) , val) ;
161- }
162- }
250+ self . insert_unstable_options( stringify!( $i) , format!( "{:?}" , & val) ) ;
251+ self . $i. 1 = true ;
252+ self . $i. 2 = val;
163253 }
164254 ) +
165255 self . set_heuristics( ) ;
@@ -220,6 +310,12 @@ macro_rules! create_config {
220310 }
221311 }
222312
313+ /// Get a reference to the UnstableOptions set on the configuration.
314+ #[ allow( unreachable_pub) ]
315+ pub fn unstable_options( & self ) -> & UnstableOptions {
316+ & self . configured_unstable_options
317+ }
318+
223319 #[ allow( unreachable_pub) ]
224320 pub fn override_value( & mut self , key: & str , val: & str )
225321 {
@@ -232,6 +328,7 @@ macro_rules! create_config {
232328 stringify!( $i) ,
233329 val,
234330 stringify!( $ty) ) ) ;
331+ self . insert_unstable_options( stringify!( $i) , val. to_owned( ) ) ;
235332 }
236333 ) +
237334 _ => panic!( "Unknown config key in override: {}" , key)
@@ -438,6 +535,7 @@ macro_rules! create_config {
438535 fn default ( ) -> Config {
439536 Config {
440537 license_template: None ,
538+ configured_unstable_options: UnstableOptions :: new( ) ,
441539 $(
442540 $i: ( Cell :: new( false ) , false , $def, $stb) ,
443541 ) +
0 commit comments