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) ]
@@ -65,7 +139,7 @@ macro_rules! create_config {
65139 // into a regex, it will be stored here
66140 pub license_template: Option <Regex >,
67141 // Unstable Options specified on the stable channel
68- configured_unstable_options: std :: collections :: HashMap < String , String > ,
142+ configured_unstable_options: UnstableOptions ,
69143 // For each config item, we store a bool indicating whether it has
70144 // been accessed and the value, and a bool whether the option was
71145 // manually initialised, or taken from the default,
@@ -147,103 +221,33 @@ macro_rules! create_config {
147221 ConfigWasSet ( self )
148222 }
149223
150- /// Returns None if using nightly or if no unstable options were set.
151- /// Otherwise, return all unstable options set by the user.
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
152227 #[ allow( unreachable_pub) ]
153- pub fn unstable_options_set_on_stable_channel( & self ) -> Option <Vec <String >> {
154- if crate :: is_nightly_channel!( ) {
155- return None ;
156- }
157-
158- if self . using_unstable_options_on_stable_channel( ) {
159- Some ( self . configured_unstable_options. iter( )
160- . map( |( k, v) | format!( "{} = {}" , k, v) )
161- . collect:: <Vec <_>>( )
162- )
163- } else {
164- None
165- }
166- }
167-
168- /// Gather all unstable options specified by the user
169- #[ allow( unreachable_pub) ]
170- pub fn collect_unstable_options( & mut self ) {
171- if crate :: is_nightly_channel!( ) {
228+ pub fn insert_unstable_options( & mut self , option: & ' static str , value: String ) {
229+ if option == "abort_on_unrecognised_options" {
172230 return
173231 }
174232
175- let abort_option = "abort_on_unrecognised_options" ;
176-
177- $( {
178- // self.$i.3 = 'is this a stable options'
179- // self.$1.1 = 'was this set by the user'
180- // the abort option is currently unstable so it needs to be special cased
181- // otherwise we would abort when using it.
182- if !( self . $i. 3 ) && self . $i. 1 && stringify!( $i) != abort_option {
183- self . configured_unstable_options. insert(
184- stringify!( $i) . to_owned( ) , format!( "{:?}" , self . $i. 2 )
185- ) ;
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+ }
186240 }
187-
188- } ) +
189- }
190-
191- /// Returns true if any unstable options were set while on the stable channel
192- #[ allow( unreachable_pub) ]
193- pub fn using_unstable_options_on_stable_channel( & self ) -> bool {
194- !self . configured_unstable_options. is_empty( )
195- }
196-
197- /// Return a String warning users about all unstable options used on the stable channel
198- #[ allow( unreachable_pub) ]
199- pub fn unstable_options_warning_message( & self ) -> Option <String > {
200- let unstable_options = self . unstable_options_set_on_stable_channel( ) ?;
201- let upgrade_to_abort_message = "\n Set `abort_on_unrecognised_options = true` \
202- to convert this warning into an error\n \n ";
203- // Capacity of 120 * len should be enough space for all options.
204- // the Warning string below is ~80 characters long so there is
205- // ~40 char buffer for option name and value
206- let mut output = String :: with_capacity(
207- upgrade_to_abort_message. len( ) + unstable_options. len( ) * 120
208- ) ;
209-
210- for option in unstable_options {
211- output. push_str(
212- & format!( "Warning: can't set `{}`, unstable features are only \
213- available in nightly channel.\n ", option
214- )
215- ) ;
241+ ) +
242+ _ => panic!( "Unknown config key in override: {}" , option)
216243 }
217244
218- output. push_str( upgrade_to_abort_message) ;
219-
220- Some ( output)
221- }
222-
223- /// Returns a String explaining why rustfmt exited early when using unstable options
224- /// on the stable channel
225- #[ allow( unreachable_pub) ]
226- pub fn unstable_options_abort_message( & self ) -> Option <String > {
227- let unstable_options = self . unstable_options_set_on_stable_channel( ) ?;
228- let first_line = "Can't set nightly options when using stable rustfmt\n " ;
229- let to_warning_message = "\n Set `abort_on_unrecognised_options = false` \
230- to convert this error into a warning\n \n ";
231- // 40 = buffer we'll use for all options. Most will be less than 40 char long
232- let mut output = String :: with_capacity(
233- to_warning_message. len( ) + first_line. len( ) + unstable_options. len( ) * 40
234- ) ;
235- output. push_str( first_line) ;
236-
237- for option in unstable_options {
238- output. push_str( & format!( " - `{}`\n " , option) ) ;
239- }
240- output. push_str( to_warning_message) ;
241- Some ( output)
242245 }
243246
244247 fn fill_from_parsed_config( mut self , parsed: PartialConfig , dir: & Path ) -> Config {
245248 $(
246249 if let Some ( val) = parsed. $i {
250+ self . insert_unstable_options( stringify!( $i) , format!( "{:?}" , & val) ) ;
247251 self . $i. 1 = true ;
248252 self . $i. 2 = val;
249253 }
@@ -252,7 +256,6 @@ macro_rules! create_config {
252256 self . set_license_template( ) ;
253257 self . set_ignore( dir) ;
254258 self . set_merge_imports( ) ;
255- self . collect_unstable_options( ) ;
256259 self
257260 }
258261
@@ -307,6 +310,12 @@ macro_rules! create_config {
307310 }
308311 }
309312
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+
310319 #[ allow( unreachable_pub) ]
311320 pub fn override_value( & mut self , key: & str , val: & str )
312321 {
@@ -319,6 +328,7 @@ macro_rules! create_config {
319328 stringify!( $i) ,
320329 val,
321330 stringify!( $ty) ) ) ;
331+ self . insert_unstable_options( stringify!( $i) , val. to_owned( ) ) ;
322332 }
323333 ) +
324334 _ => panic!( "Unknown config key in override: {}" , key)
@@ -525,7 +535,7 @@ macro_rules! create_config {
525535 fn default ( ) -> Config {
526536 Config {
527537 license_template: None ,
528- configured_unstable_options: std :: collections :: HashMap :: new( ) ,
538+ configured_unstable_options: UnstableOptions :: new( ) ,
529539 $(
530540 $i: ( Cell :: new( false ) , false , $def, $stb) ,
531541 ) +
0 commit comments