1
+ use std:: collections:: HashMap ;
2
+
1
3
use crate :: config:: file_lines:: FileLines ;
2
4
use crate :: config:: options:: { IgnoreList , WidthHeuristics } ;
3
5
@@ -50,6 +52,78 @@ impl ConfigType for IgnoreList {
50
52
}
51
53
}
52
54
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
+
53
127
macro_rules! create_config {
54
128
( $( $i: ident: $ty: ty, $def: expr, $stb: expr, $( $dstring: expr ) ,+ ) ;+ $( ; ) * ) => (
55
129
#[ cfg( test) ]
@@ -64,6 +138,8 @@ macro_rules! create_config {
64
138
// if a license_template_path has been specified, successfully read, parsed and compiled
65
139
// into a regex, it will be stored here
66
140
pub license_template: Option <Regex >,
141
+ // Unstable Options specified on the stable channel
142
+ configured_unstable_options: UnstableOptions ,
67
143
// For each config item, we store a bool indicating whether it has
68
144
// been accessed and the value, and a bool whether the option was
69
145
// manually initialised, or taken from the default,
@@ -145,21 +221,35 @@ macro_rules! create_config {
145
221
ConfigWasSet ( self )
146
222
}
147
223
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
+
148
247
fn fill_from_parsed_config( mut self , parsed: PartialConfig , dir: & Path ) -> Config {
149
248
$(
150
249
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;
163
253
}
164
254
) +
165
255
self . set_heuristics( ) ;
@@ -220,6 +310,12 @@ macro_rules! create_config {
220
310
}
221
311
}
222
312
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
+
223
319
#[ allow( unreachable_pub) ]
224
320
pub fn override_value( & mut self , key: & str , val: & str )
225
321
{
@@ -232,6 +328,7 @@ macro_rules! create_config {
232
328
stringify!( $i) ,
233
329
val,
234
330
stringify!( $ty) ) ) ;
331
+ self . insert_unstable_options( stringify!( $i) , val. to_owned( ) ) ;
235
332
}
236
333
) +
237
334
_ => panic!( "Unknown config key in override: {}" , key)
@@ -438,6 +535,7 @@ macro_rules! create_config {
438
535
fn default ( ) -> Config {
439
536
Config {
440
537
license_template: None ,
538
+ configured_unstable_options: UnstableOptions :: new( ) ,
441
539
$(
442
540
$i: ( Cell :: new( false ) , false , $def, $stb) ,
443
541
) +
0 commit comments