]> git.lizzy.rs Git - rust.git/blob - src/config.rs
Remove BlockIndentStyle::Inherit
[rust.git] / src / config.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 extern crate toml;
12
13 use file_lines::FileLines;
14 use lists::{SeparatorTactic, ListTactic};
15 use std::io::Write;
16
17 macro_rules! configuration_option_enum{
18     ($e:ident: $( $x:ident ),+ $(,)*) => {
19         #[derive(Copy, Clone, Eq, PartialEq, Debug)]
20         pub enum $e {
21             $( $x ),+
22         }
23
24         impl_enum_decodable!($e, $( $x ),+);
25     }
26 }
27
28 configuration_option_enum! { Style:
29     Rfc, // Follow the style RFCs style.
30     Default, // Follow the traditional Rustfmt style.
31 }
32
33 configuration_option_enum! { NewlineStyle:
34     Windows, // \r\n
35     Unix, // \n
36     Native, // \r\n in Windows, \n on other platforms
37 }
38
39 configuration_option_enum! { BraceStyle:
40     AlwaysNextLine,
41     PreferSameLine,
42     // Prefer same line except where there is a where clause, in which case force
43     // the brace to the next line.
44     SameLineWhere,
45 }
46
47 configuration_option_enum! { ControlBraceStyle:
48     // K&R style, Rust community default
49     AlwaysSameLine,
50     // Stroustrup style
51     ClosingNextLine,
52     // Allman style
53     AlwaysNextLine,
54 }
55
56 // How to indent a function's return type.
57 configuration_option_enum! { ReturnIndent:
58     // Aligned with the arguments
59     WithArgs,
60     // Aligned with the where clause
61     WithWhereClause,
62 }
63
64 // How to style a struct literal.
65 configuration_option_enum! { StructLitStyle:
66     // First line on the same line as the opening brace, all lines aligned with
67     // the first line.
68     Visual,
69     // First line is on a new line and all lines align with block indent.
70     Block,
71     // FIXME Maybe we should also have an option to align types.
72 }
73
74 // How to style fn args.
75 configuration_option_enum! { FnArgLayoutStyle:
76     // First line on the same line as the opening brace, all lines aligned with
77     // the first line.
78     Visual,
79     // Put args on one line if they fit, or start a new line with block indent.
80     Block,
81     // First line is on a new line and all lines align with block indent.
82     BlockAlways,
83 }
84
85 configuration_option_enum! { BlockIndentStyle:
86     // One level deeper than parent.
87     Tabbed,
88     // Aligned with block open.
89     Visual,
90 }
91
92 configuration_option_enum! { Density:
93     // Fit as much on one line as possible.
94     Compressed,
95     // Use more lines.
96     Tall,
97     // Try to compress if the body is empty.
98     CompressedIfEmpty,
99     // Place every item on a separate line.
100     Vertical,
101 }
102
103 configuration_option_enum! { TypeDensity:
104     // No spaces around "=" and "+"
105     Compressed,
106     // Spaces around " = " and " + "
107     Wide,
108 }
109
110
111 impl Density {
112     pub fn to_list_tactic(self) -> ListTactic {
113         match self {
114             Density::Compressed => ListTactic::Mixed,
115             Density::Tall |
116             Density::CompressedIfEmpty => ListTactic::HorizontalVertical,
117             Density::Vertical => ListTactic::Vertical,
118         }
119     }
120 }
121
122 configuration_option_enum! { LicensePolicy:
123     // Do not place license text at top of files
124     NoLicense,
125     // Use the text in "license" field as the license
126     TextLicense,
127     // Use a text file as the license text
128     FileLicense,
129 }
130
131 configuration_option_enum! { MultilineStyle:
132     // Use horizontal layout if it fits in one line, fall back to vertical
133     PreferSingle,
134     // Use vertical layout
135     ForceMulti,
136 }
137
138 impl MultilineStyle {
139     pub fn to_list_tactic(self) -> ListTactic {
140         match self {
141             MultilineStyle::PreferSingle => ListTactic::HorizontalVertical,
142             MultilineStyle::ForceMulti => ListTactic::Vertical,
143         }
144     }
145 }
146
147 configuration_option_enum! { ReportTactic:
148     Always,
149     Unnumbered,
150     Never,
151 }
152
153 configuration_option_enum! { WriteMode:
154     // Backs the original file up and overwrites the original.
155     Replace,
156     // Overwrites original file without backup.
157     Overwrite,
158     // Writes the output to stdout.
159     Display,
160     // Writes the diff to stdout.
161     Diff,
162     // Displays how much of the input file was processed
163     Coverage,
164     // Unfancy stdout
165     Plain,
166     // Outputs a checkstyle XML file.
167     Checkstyle,
168 }
169
170 /// Trait for types that can be used in `Config`.
171 pub trait ConfigType: Sized {
172     /// Returns hint text for use in `Config::print_docs()`. For enum types, this is a
173     /// pipe-separated list of variants; for other types it returns "<type>".
174     fn doc_hint() -> String;
175 }
176
177 impl ConfigType for bool {
178     fn doc_hint() -> String {
179         String::from("<boolean>")
180     }
181 }
182
183 impl ConfigType for usize {
184     fn doc_hint() -> String {
185         String::from("<unsigned integer>")
186     }
187 }
188
189 impl ConfigType for isize {
190     fn doc_hint() -> String {
191         String::from("<signed integer>")
192     }
193 }
194
195 impl ConfigType for String {
196     fn doc_hint() -> String {
197         String::from("<string>")
198     }
199 }
200
201 impl ConfigType for FileLines {
202     fn doc_hint() -> String {
203         String::from("<json>")
204     }
205 }
206
207 pub struct ConfigHelpItem {
208     option_name: &'static str,
209     doc_string: &'static str,
210     variant_names: String,
211     default: &'static str,
212 }
213
214 impl ConfigHelpItem {
215     pub fn option_name(&self) -> &'static str {
216         self.option_name
217     }
218
219     pub fn doc_string(&self) -> &'static str {
220         self.doc_string
221     }
222
223     pub fn variant_names(&self) -> &String {
224         &self.variant_names
225     }
226
227     pub fn default(&self) -> &'static str {
228         self.default
229     }
230 }
231
232 macro_rules! create_config {
233     ($($i:ident: $ty:ty, $def:expr, $( $dstring:expr ),+ );+ $(;)*) => (
234         #[derive(RustcDecodable, Clone)]
235         pub struct Config {
236             $(pub $i: $ty),+
237         }
238
239         // Just like the Config struct but with each property wrapped
240         // as Option<T>. This is used to parse a rustfmt.toml that doesn't
241         // specity all properties of `Config`.
242         // We first parse into `ParsedConfig`, then create a default `Config`
243         // and overwrite the properties with corresponding values from `ParsedConfig`
244         #[derive(RustcDecodable, Clone)]
245         pub struct ParsedConfig {
246             $(pub $i: Option<$ty>),+
247         }
248
249         impl Config {
250
251             fn fill_from_parsed_config(mut self, parsed: ParsedConfig) -> Config {
252             $(
253                 if let Some(val) = parsed.$i {
254                     self.$i = val;
255                 }
256             )+
257                 self
258             }
259
260             pub fn from_toml(toml: &str) -> Config {
261                 let parsed = toml.parse().expect("Could not parse TOML");
262                 let parsed_config:ParsedConfig = match toml::decode(parsed) {
263                     Some(decoded) => decoded,
264                     None => {
265                         msg!("Decoding config file failed. Config:\n{}", toml);
266                         let parsed: toml::Value = toml.parse().expect("Could not parse TOML");
267                         msg!("\n\nParsed:\n{:?}", parsed);
268                         panic!();
269                     }
270                 };
271                 Config::default().fill_from_parsed_config(parsed_config)
272             }
273
274             pub fn override_value(&mut self, key: &str, val: &str) {
275                 match key {
276                     $(
277                         stringify!($i) => {
278                             self.$i = val.parse::<$ty>()
279                                 .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
280                                                  stringify!($i),
281                                                  val,
282                                                  stringify!($ty)));
283                         }
284                     )+
285                     _ => panic!("Unknown config key in override: {}", key)
286                 }
287             }
288
289             pub fn print_docs() {
290                 use std::cmp;
291                 let max = 0;
292                 $( let max = cmp::max(max, stringify!($i).len()+1); )+
293                 let mut space_str = String::with_capacity(max);
294                 for _ in 0..max {
295                     space_str.push(' ');
296                 }
297                 println!("Configuration Options:");
298                 $(
299                     let name_raw = stringify!($i);
300                     let mut name_out = String::with_capacity(max);
301                     for _ in name_raw.len()..max-1 {
302                         name_out.push(' ')
303                     }
304                     name_out.push_str(name_raw);
305                     name_out.push(' ');
306                     println!("{}{} Default: {:?}",
307                              name_out,
308                              <$ty>::doc_hint(),
309                              $def);
310                     $(
311                         println!("{}{}", space_str, $dstring);
312                     )+
313                     println!("");
314                 )+
315             }
316         }
317
318         // Template for the default configuration
319         impl Default for Config {
320             fn default() -> Config {
321                 Config {
322                     $(
323                         $i: $def,
324                     )+
325                 }
326             }
327         }
328     )
329 }
330
331 create_config! {
332     verbose: bool, false, "Use verbose output";
333     disable_all_formatting: bool, false, "Don't reformat anything";
334     skip_children: bool, false, "Don't reformat out of line modules";
335     file_lines: FileLines, FileLines::all(),
336         "Lines to format; this is not supported in rustfmt.toml, and can only be specified \
337          via the --file-lines option";
338     max_width: usize, 100, "Maximum width of each line";
339     error_on_line_overflow: bool, true, "Error if unable to get all lines within max_width";
340     tab_spaces: usize, 4, "Number of spaces per tab";
341     fn_call_width: usize, 60,
342         "Maximum width of the args of a function call before falling back to vertical formatting";
343     struct_lit_width: usize, 16,
344         "Maximum width in the body of a struct lit before falling back to vertical formatting";
345     struct_variant_width: usize, 35,
346         "Maximum width in the body of a struct variant before falling back to vertical formatting";
347     force_explicit_abi: bool, true, "Always print the abi for extern items";
348     newline_style: NewlineStyle, NewlineStyle::Unix, "Unix or Windows line endings";
349     fn_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for functions";
350     item_brace_style: BraceStyle, BraceStyle::SameLineWhere, "Brace style for structs and enums";
351     control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine,
352         "Brace style for control flow constructs";
353     impl_empty_single_line: bool, true, "Put empty-body implementations on a single line";
354     trailing_comma: SeparatorTactic, SeparatorTactic::Vertical,
355         "How to handle trailing commas for lists";
356     fn_empty_single_line: bool, true, "Put empty-body functions on a single line";
357     fn_single_line: bool, false, "Put single-expression functions on a single line";
358     fn_return_indent: ReturnIndent, ReturnIndent::WithArgs,
359         "Location of return type in function declaration";
360     fn_args_paren_newline: bool, true, "If function argument parenthesis goes on a newline";
361     fn_args_density: Density, Density::Tall, "Argument density in functions";
362     fn_args_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual,
363         "Layout of function arguments and tuple structs";
364     fn_arg_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indent on function arguments";
365     array_layout: FnArgLayoutStyle, FnArgLayoutStyle::Visual, "Indent on arrays";
366     type_punctuation_density: TypeDensity, TypeDensity::Wide,
367         "Determines if '+' or '=' are wrapped in spaces in the punctuation of types";
368     where_style: Style, Style::Default, "Overall strategy for where clauses";
369     // Should we at least try to put the where clause on the same line as the rest of the
370     // function decl?
371     where_density: Density, Density::CompressedIfEmpty, "Density of a where clause";
372     // Visual will be treated like Tabbed
373     where_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of a where clause";
374     where_layout: ListTactic, ListTactic::Vertical, "Element layout inside a where clause";
375     where_pred_indent: BlockIndentStyle, BlockIndentStyle::Visual,
376         "Indentation style of a where predicate";
377     generics_style: Style, Style::Default, "Overall strategy for generics";
378     generics_indent: BlockIndentStyle, BlockIndentStyle::Visual, "Indentation of generics";
379     struct_lit_style: StructLitStyle, StructLitStyle::Block, "Style of struct definition";
380     struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle,
381         "Multiline style on literal structs";
382     report_todo: ReportTactic, ReportTactic::Never,
383         "Report all, none or unnumbered occurrences of TODO in source file comments";
384     report_fixme: ReportTactic, ReportTactic::Never,
385         "Report all, none or unnumbered occurrences of FIXME in source file comments";
386     chain_indent: BlockIndentStyle, BlockIndentStyle::Tabbed, "Indentation of chain";
387     chain_one_line_max: usize, 4, "Maximum number of elements in a chain to fit on a single line";
388     reorder_imports: bool, false, "Reorder import statements alphabetically";
389     reorder_imported_names: bool, false,
390         "Reorder lists of names in import statements alphabetically";
391     single_line_if_else_max_width: usize, 50, "Maximum line length for single line if-else \
392                                                 expressions. A value of zero means always break \
393                                                 if-else expressions.";
394     format_strings: bool, false, "Format string literals where necessary";
395     force_format_strings: bool, false, "Always format string literals";
396     take_source_hints: bool, false, "Retain some formatting characteristics from the source code";
397     hard_tabs: bool, false, "Use tab characters for indentation, spaces for alignment";
398     wrap_comments: bool, false, "Break comments to fit on the line";
399     comment_width: usize, 80, "Maximum length of comments. No effect unless wrap_comments = true";
400     normalize_comments: bool, false, "Convert /* */ comments to // comments where possible";
401     wrap_match_arms: bool, true, "Wrap multiline match arms in blocks";
402     match_block_trailing_comma: bool, false,
403         "Put a trailing comma after a block based match arm (non-block arms are not affected)";
404     closure_block_indent_threshold: isize, 5, "How many lines a closure must have before it is \
405                                                block indented. -1 means never use block indent.";
406     space_before_type_annotation: bool, false,
407         "Leave a space before the colon in a type annotation";
408     space_after_type_annotation_colon: bool, true,
409         "Leave a space after the colon in a type annotation";
410     space_before_bound: bool, false, "Leave a space before the colon in a trait or lifetime bound";
411     space_after_bound_colon: bool, true,
412         "Leave a space after the colon in a trait or lifetime bound";
413     spaces_around_ranges: bool, false, "Put spaces around the  .. and ... range operators";
414     spaces_within_angle_brackets: bool, false, "Put spaces within non-empty generic arguments";
415     spaces_within_square_brackets: bool, false, "Put spaces within non-empty square brackets";
416     spaces_within_parens: bool, false, "Put spaces within non-empty parentheses";
417     use_try_shorthand: bool, false, "Replace uses of the try! macro by the ? shorthand";
418     write_mode: WriteMode, WriteMode::Replace,
419         "What Write Mode to use when none is supplied: Replace, Overwrite, Display, Diff, Coverage";
420     condense_wildcard_suffices: bool, false, "Replace strings of _ wildcards by a single .. in \
421                                               tuple patterns"
422 }