1+ use std:: collections:: HashMap ;
2+
13use crate :: config:: file_lines:: FileLines ;
24use crate :: config:: options:: { IgnoreList , WidthHeuristics } ;
35
@@ -58,6 +60,82 @@ impl ConfigType for IgnoreList {
5860 }
5961}
6062
63+ /// Store a map of all Unstable options used in in the configuration.
64+ #[ derive( Clone , Debug ) ]
65+ pub struct UnstableOptions {
66+ pub ( crate ) options : HashMap < & ' static str , String > ,
67+ }
68+
69+ impl std:: fmt:: Display for UnstableOptions {
70+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
71+ if let Some ( message) = self . abort_message ( ) {
72+ write ! ( f, "{}" , message)
73+ } else {
74+ write ! ( f, "No unstable options were used." )
75+ }
76+ }
77+ }
78+
79+ impl UnstableOptions {
80+ /// Create a new UnstableOptions struct
81+ pub ( crate ) fn new ( ) -> Self {
82+ Self {
83+ options : HashMap :: new ( ) ,
84+ }
85+ }
86+
87+ /// Insert an unstable option and a user supplied value for that unstable option
88+ pub ( crate ) fn insert ( & mut self , option : & ' static str , user_supplied_value : String ) {
89+ self . options . insert ( option, user_supplied_value) ;
90+ }
91+
92+ /// Check if any unstable options have been set
93+ pub ( crate ) fn has_unstable_options ( & self ) -> bool {
94+ !self . options . is_empty ( )
95+ }
96+
97+ /// Generate the Warning message
98+ pub ( crate ) fn warning_message ( & self ) -> Option < String > {
99+ if self . options . is_empty ( ) {
100+ return None ;
101+ }
102+ let mut result = String :: new ( ) ;
103+
104+ for ( k, v) in self . options . iter ( ) {
105+ result. push_str ( & format ! (
106+ "Warning: can't set `{} = {}`, unstable features are only \
107+ available in nightly channel.\n ",
108+ k, v,
109+ ) ) ;
110+ }
111+
112+ let upgrade_to_abort_message = "\n Set `abort_on_unrecognised_options = true` \
113+ to convert this warning into an error\n \n ";
114+
115+ result. push_str ( upgrade_to_abort_message) ;
116+
117+ Some ( result)
118+ }
119+
120+ /// Generate the Abort message
121+ pub ( crate ) fn abort_message ( & self ) -> Option < String > {
122+ if self . options . is_empty ( ) {
123+ return None ;
124+ }
125+
126+ let mut result = String :: new ( ) ;
127+ result. push_str ( "Can't set nightly options when using stable rustfmt\n " ) ;
128+
129+ for ( k, v) in self . options . iter ( ) {
130+ result. push_str ( & format ! ( " - `{} = {}`\n " , k, v) ) ;
131+ }
132+ let to_warning_message = "\n Set `abort_on_unrecognised_options = false` \
133+ to convert this error into a warning\n \n ";
134+ result. push_str ( to_warning_message) ;
135+ Some ( result)
136+ }
137+ }
138+
61139macro_rules! create_config {
62140 // Options passed in to the macro.
63141 //
@@ -76,6 +154,8 @@ macro_rules! create_config {
76154 #[ derive( Clone ) ]
77155 #[ allow( unreachable_pub) ]
78156 pub struct Config {
157+ // Unstable Options specified on the stable channel
158+ configured_unstable_options: UnstableOptions ,
79159 // For each config item, we store:
80160 //
81161 // - 0: true if the value has been access
@@ -159,12 +239,41 @@ macro_rules! create_config {
159239 ConfigWasSet ( self )
160240 }
161241
242+ /// Insert all unstable options and their values into the UnstableOptions struct.
243+ /// The only exception is the "abort_on_unrecognised_options", which helps
244+ /// determine if we should abort or warn when using unstable options on stable rustfmt
245+ #[ allow( unreachable_pub) ]
246+ pub fn insert_unstable_options( & mut self , option: & ' static str , value: String ) {
247+ if option == "abort_on_unrecognised_options" {
248+ return
249+ }
250+
251+ match option {
252+ $(
253+ stringify!( $i) => {
254+ // If its an unstable option then add it to the unstable list
255+ if !self . $i. 3 {
256+ self . configured_unstable_options. insert( option, value) ;
257+ }
258+ }
259+ ) +
260+ _ => panic!( "Unknown config key in override: {}" , option)
261+ }
262+
263+ }
264+
162265 fn fill_from_parsed_config( mut self , parsed: PartialConfig , dir: & Path ) -> Config {
163266 $(
164267 if let Some ( option_value) = parsed. $i {
165268 let option_stable = self . $i. 3 ;
269+ if !option_stable || !option_value. stable_variant( ) {
270+ self . insert_unstable_options(
271+ stringify!( $i) , format!( "{:?}" , & option_value)
272+ ) ;
273+ }
274+
166275 if $crate:: config:: config_type:: is_stable_option_and_value(
167- stringify! ( $i ) , option_stable, & option_value
276+ option_stable, & option_value
168277 ) {
169278 self . $i. 1 = true ;
170279 self . $i. 2 = option_value;
@@ -228,6 +337,12 @@ macro_rules! create_config {
228337 }
229338 }
230339
340+ /// Get a reference to the UnstableOptions set on the configuration.
341+ #[ allow( unreachable_pub) ]
342+ pub fn unstable_options( & self ) -> & UnstableOptions {
343+ & self . configured_unstable_options
344+ }
345+
231346 #[ allow( unreachable_pub) ]
232347 pub fn override_value( & mut self , key: & str , val: & str )
233348 {
@@ -439,6 +554,7 @@ macro_rules! create_config {
439554 impl Default for Config {
440555 fn default ( ) -> Config {
441556 Config {
557+ configured_unstable_options: UnstableOptions :: new( ) ,
442558 $(
443559 $i: ( Cell :: new( false ) , false , $def, $stb) ,
444560 ) +
@@ -448,35 +564,17 @@ macro_rules! create_config {
448564 )
449565}
450566
451- pub ( crate ) fn is_stable_option_and_value < T > (
452- option_name : & str ,
453- option_stable : bool ,
454- option_value : & T ,
455- ) -> bool
567+ pub ( crate ) fn is_stable_option_and_value < T > ( option_stable : bool , option_value : & T ) -> bool
456568where
457569 T : PartialEq + std:: fmt:: Debug + ConfigType ,
458570{
459571 let nightly = crate :: is_nightly_channel!( ) ;
460572 let variant_stable = option_value. stable_variant ( ) ;
461573 match ( nightly, option_stable, variant_stable) {
462574 // Stable with an unstable option
463- ( false , false , _) => {
464- eprintln ! (
465- "Warning: can't set `{} = {:?}`, unstable features are only \
466- available in nightly channel.",
467- option_name, option_value
468- ) ;
469- false
470- }
575+ ( false , false , _) => false ,
471576 // Stable with a stable option, but an unstable variant
472- ( false , true , false ) => {
473- eprintln ! (
474- "Warning: can't set `{} = {:?}`, unstable variants are only \
475- available in nightly channel.",
476- option_name, option_value
477- ) ;
478- false
479- }
577+ ( false , true , false ) => false ,
480578 // Nightly: everything allowed
481579 // Stable with stable option and variant: allowed
482580 ( true , _, _) | ( false , true , true ) => true ,
0 commit comments