Centralize nightly compiler flags handling

This commit is contained in:
Guillaume Gomez 2016-03-15 09:09:29 +01:00
parent f34ae3f7ed
commit ded701bf64
4 changed files with 154 additions and 157 deletions

View File

@ -785,12 +785,12 @@ impl RustcOptGroup {
self.stability == OptionStability::Stable
}
fn stable(g: getopts::OptGroup) -> RustcOptGroup {
pub fn stable(g: getopts::OptGroup) -> RustcOptGroup {
RustcOptGroup { opt_group: g, stability: OptionStability::Stable }
}
#[allow(dead_code)] // currently we have no "truly unstable" options
fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
pub fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
RustcOptGroup { opt_group: g, stability: OptionStability::Unstable }
}
@ -926,33 +926,32 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
let mut opts = rustc_short_optgroups();
opts.extend_from_slice(&[
opt::multi_s("", "extern", "Specify where an external rust library is \
located",
"NAME=PATH"),
opt::multi_s("", "extern", "Specify where an external rust library is located",
"NAME=PATH"),
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
opt::opt_ubnr("", "error-format",
"How errors and other messages are produced",
"human|json"),
opt::opt_s("", "color", "Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output", "auto|always|never"),
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output", "auto|always|never"),
opt::flagopt_ubnr("", "pretty",
"Pretty-print the input instead of compiling;
valid types are: `normal` (un-annotated source),
`expanded` (crates expanded), or
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
"TYPE"),
"Pretty-print the input instead of compiling;
valid types are: `normal` (un-annotated source),
`expanded` (crates expanded), or
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
"TYPE"),
opt::flagopt_ubnr("", "unpretty",
"Present the input source, unstable (and less-pretty) variants;
valid types are any of the types for `--pretty`, as well as:
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
`everybody_loops` (all function bodies replaced with `loop {}`),
`hir` (the HIR), `hir,identified`, or
`hir,typed` (HIR with types for each node).",
"TYPE"),
"Present the input source, unstable (and less-pretty) variants;
valid types are any of the types for `--pretty`, as well as:
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
`everybody_loops` (all function bodies replaced with `loop {}`),
`hir` (the HIR), `hir,identified`, or
`hir,typed` (HIR with types for each node).",
"TYPE"),
// new options here should **not** use the `_ubnr` functions, all new
// unstable options should use the short variants to indicate that they
@ -1263,7 +1262,6 @@ pub fn get_unstable_features_setting() -> UnstableFeatures {
}
pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
let mut crate_types: Vec<CrateType> = Vec::new();
for unparsed_crate_type in &list_list {
for part in unparsed_crate_type.split(',') {
@ -1287,6 +1285,72 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
return Ok(crate_types);
}
pub mod nightly_options {
use getopts;
use syntax::feature_gate::UnstableFeatures;
use super::{ErrorOutputType, OptionStability, RustcOptGroup, get_unstable_features_setting};
use session::{early_error, early_warn};
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
is_nightly_build() && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
}
fn is_nightly_build() -> bool {
match get_unstable_features_setting() {
UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
_ => false,
}
}
pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
let really_allows_unstable_options = match get_unstable_features_setting() {
UnstableFeatures::Disallow => false,
_ => true,
};
for opt in flags.iter() {
if opt.stability == OptionStability::Stable {
continue
}
let opt_name = if opt.opt_group.long_name.is_empty() {
&opt.opt_group.short_name
} else {
&opt.opt_group.long_name
};
if !matches.opt_present(opt_name) {
continue
}
if opt_name != "Z" && !has_z_unstable_option {
early_error(ErrorOutputType::default(),
&format!("the `-Z unstable-options` flag must also be passed to enable \
the flag `{}`",
opt_name));
}
if really_allows_unstable_options {
continue
}
match opt.stability {
OptionStability::Unstable => {
let msg = format!("the option `{}` is only accepted on the \
nightly compiler", opt_name);
early_error(ErrorOutputType::default(), &msg);
}
OptionStability::UnstableButNotReally => {
let msg = format!("the option `{}` is is unstable and should \
only be used on the nightly compiler, but \
it is currently accepted for backwards \
compatibility; this will soon change, \
see issue #31847 for more details",
opt_name);
early_warn(ErrorOutputType::default(), &msg);
}
OptionStability::Stable => {}
}
}
}
}
impl fmt::Display for CrateType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {

View File

@ -68,7 +68,7 @@ use rustc_save_analysis as save;
use rustc_trans::back::link;
use rustc::session::{config, Session, build_session, CompileResult};
use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
use rustc::session::config::{get_unstable_features_setting, OptionStability};
use rustc::session::config::{get_unstable_features_setting, nightly_options};
use rustc::middle::cstore::CrateStore;
use rustc::lint::Lint;
use rustc::lint;
@ -89,7 +89,7 @@ use std::str;
use std::sync::{Arc, Mutex};
use std::thread;
use rustc::session::{early_error, early_warn};
use rustc::session::early_error;
use syntax::ast;
use syntax::parse::{self, PResult};
@ -910,51 +910,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
// (unstable option being used on stable)
// * If we're a historically stable-but-should-be-unstable option then we
// emit a warning that we're going to turn this into an error soon.
let has_z_unstable_options = matches.opt_strs("Z")
.iter()
.any(|x| *x == "unstable-options");
let really_allows_unstable_options = match get_unstable_features_setting() {
UnstableFeatures::Disallow => false,
_ => true,
};
for opt in config::rustc_optgroups() {
if opt.stability == OptionStability::Stable {
continue
}
let opt_name = if opt.opt_group.long_name.is_empty() {
&opt.opt_group.short_name
} else {
&opt.opt_group.long_name
};
if !matches.opt_present(opt_name) {
continue
}
if opt_name != "Z" && !has_z_unstable_options {
let msg = format!("the `-Z unstable-options` flag must also be \
passed to enable the flag `{}`", opt_name);
early_error(ErrorOutputType::default(), &msg);
}
if really_allows_unstable_options {
continue
}
match opt.stability {
OptionStability::Unstable => {
let msg = format!("the option `{}` is only accepted on the \
nightly compiler", opt_name);
early_error(ErrorOutputType::default(), &msg);
}
OptionStability::UnstableButNotReally => {
let msg = format!("the option `{}` is is unstable and should \
only be used on the nightly compiler, but \
it is currently accepted for backwards \
compatibility; this will soon change, \
see issue #31847 for more details",
opt_name);
early_warn(ErrorOutputType::default(), &msg);
}
OptionStability::Stable => {}
}
}
nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
if matches.opt_present("h") || matches.opt_present("help") {
// Only show unstable options in --help if we *really* accept unstable
@ -962,12 +918,11 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
// the stable channel of Rust which was accidentally allowed
// historically.
usage(matches.opt_present("verbose"),
has_z_unstable_options && really_allows_unstable_options);
nightly_options::is_unstable_enabled(&matches));
return None;
}
// Don't handle -W help here, because we might first load plugins.
let r = matches.opt_strs("Z");
if r.iter().any(|x| *x == "help") {
describe_debug_flags();

View File

@ -433,10 +433,6 @@ pub fn run(mut krate: clean::Crate,
krate: krate.name.clone(),
playground_url: "".to_string(),
},
include_sources: true,
local_sources: HashMap::new(),
render_redirect_pages: false,
issue_tracker_base_url: None,
css_file_extension: css_file_extension,
};

View File

@ -65,10 +65,8 @@ use std::sync::mpsc::channel;
use externalfiles::ExternalHtml;
use serialize::Decodable;
use serialize::json::{self, Json};
use rustc::session::early_error;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{get_unstable_features_setting, ErrorOutputType};
use syntax::feature_gate::UnstableFeatures;
use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options};
// reexported from `clean` so it can be easily updated with the mod itself
pub use clean::SCHEMA_VERSION;
@ -143,86 +141,87 @@ pub fn main() {
process::exit(res as i32);
}
pub fn opts() -> Vec<getopts::OptGroup> {
fn stable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::stable(g) }
fn unstable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::unstable(g) }
pub fn opts() -> Vec<RustcOptGroup> {
use getopts::*;
vec!(
optflag("h", "help", "show this help message"),
optflag("V", "version", "print rustdoc's version"),
optflag("v", "verbose", "use verbose output"),
optopt("r", "input-format", "the input type of the specified file",
"[rust|json]"),
optopt("w", "output-format", "the output type to write",
"[html|json]"),
optopt("o", "output", "where to place the output", "PATH"),
optopt("", "crate-name", "specify the name of this crate", "NAME"),
optmulti("L", "library-path", "directory to add to crate search path",
"DIR"),
optmulti("", "cfg", "pass a --cfg to rustc", ""),
optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH"),
optmulti("", "plugin-path", "directory to load plugins from", "DIR"),
optmulti("", "passes", "list of passes to also run, you might want \
to pass it multiple times; a value of `list` \
will print available passes",
"PASSES"),
optmulti("", "plugins", "space separated list of plugins to also load",
"PLUGINS"),
optflag("", "no-defaults", "don't run the default passes"),
optflag("", "test", "run code examples as tests"),
optmulti("", "test-args", "arguments to pass to the test runner",
"ARGS"),
optopt("", "target", "target triple to document", "TRIPLE"),
optmulti("", "markdown-css", "CSS files to include via <link> in a rendered Markdown file",
"FILES"),
optmulti("", "html-in-header",
"files to include inline in the <head> section of a rendered Markdown file \
or generated documentation",
"FILES"),
optmulti("", "html-before-content",
"files to include inline between <body> and the content of a rendered \
Markdown file or generated documentation",
"FILES"),
optmulti("", "html-after-content",
"files to include inline between the content and </body> of a rendered \
Markdown file or generated documentation",
"FILES"),
optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL"),
optflag("", "markdown-no-toc", "don't include table of contents"),
optopt("e", "extend-css",
"to redefine some css rules with a given file to generate doc with your \
own theme", "PATH"),
optmulti("Z", "", "internal and debugging options (only on nightly build)", "FLAG"),
stable(optflag("h", "help", "show this help message")),
stable(optflag("V", "version", "print rustdoc's version")),
stable(optflag("v", "verbose", "use verbose output")),
stable(optopt("r", "input-format", "the input type of the specified file",
"[rust|json]")),
stable(optopt("w", "output-format", "the output type to write",
"[html|json]")),
stable(optopt("o", "output", "where to place the output", "PATH")),
stable(optopt("", "crate-name", "specify the name of this crate", "NAME")),
stable(optmulti("L", "library-path", "directory to add to crate search path",
"DIR")),
stable(optmulti("", "cfg", "pass a --cfg to rustc", "")),
stable(optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH")),
stable(optmulti("", "plugin-path", "directory to load plugins from", "DIR")),
stable(optmulti("", "passes",
"list of passes to also run, you might want \
to pass it multiple times; a value of `list` \
will print available passes",
"PASSES")),
stable(optmulti("", "plugins", "space separated list of plugins to also load",
"PLUGINS")),
stable(optflag("", "no-defaults", "don't run the default passes")),
stable(optflag("", "test", "run code examples as tests")),
stable(optmulti("", "test-args", "arguments to pass to the test runner",
"ARGS")),
stable(optopt("", "target", "target triple to document", "TRIPLE")),
stable(optmulti("", "markdown-css",
"CSS files to include via <link> in a rendered Markdown file",
"FILES")),
stable(optmulti("", "html-in-header",
"files to include inline in the <head> section of a rendered Markdown file \
or generated documentation",
"FILES")),
stable(optmulti("", "html-before-content",
"files to include inline between <body> and the content of a rendered \
Markdown file or generated documentation",
"FILES")),
stable(optmulti("", "html-after-content",
"files to include inline between the content and </body> of a rendered \
Markdown file or generated documentation",
"FILES")),
stable(optopt("", "markdown-playground-url",
"URL to send code snippets to", "URL")),
stable(optflag("", "markdown-no-toc", "don't include table of contents")),
unstable(optopt("e", "extend-css",
"to redefine some css rules with a given file to generate doc with your \
own theme", "PATH")),
unstable(optmulti("Z", "",
"internal and debugging options (only on nightly build)", "FLAG")),
)
}
pub fn usage(argv0: &str) {
println!("{}",
getopts::usage(&format!("{} [options] <input>", argv0),
&opts()));
}
fn check_unstable_flag_enabled(nightly_build: bool, has_z_unstable_options: bool,
flag_name: &str) {
// check if unstable for --extend-css option
let e = if !nightly_build {
format!("the option `{}` is only accepted on the nightly compiler", flag_name)
} else if !has_z_unstable_options {
format!("the `-Z unstable-options` flag must also be passed to enable the flag `{}`",
flag_name)
} else {
return
};
early_error(ErrorOutputType::default(), &e)
&opts().into_iter()
.map(|x| x.opt_group)
.collect::<Vec<getopts::OptGroup>>()));
}
pub fn main_args(args: &[String]) -> isize {
let matches = match getopts::getopts(&args[1..], &opts()) {
let all_groups: Vec<getopts::OptGroup> = opts()
.into_iter()
.map(|x| x.opt_group)
.collect();
let matches = match getopts::getopts(&args[1..], &all_groups) {
Ok(m) => m,
Err(err) => {
println!("{}", err);
return 1;
}
};
// Check for unstable options.
nightly_options::check_nightly_options(&matches, &opts());
if matches.opt_present("h") || matches.opt_present("help") {
usage(&args[0]);
return 0;
@ -277,24 +276,7 @@ pub fn main_args(args: &[String]) -> isize {
let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
let cfgs = matches.opt_strs("cfg");
// we now check if unstable options are allowed and if we're in a nightly build
let mut has_z_unstable_options = false;
for flag in matches.opt_strs("Z").iter() {
if *flag != "unstable-options" {
println!("Unknown flag for `Z` option: {}", flag);
return 1;
} else {
has_z_unstable_options = true;
}
}
let nightly_build = get_unstable_features_setting();
let nightly_build = match nightly_build {
UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
_ => false,
};
if let Some(ref p) = css_file_extension {
check_unstable_flag_enabled(nightly_build, has_z_unstable_options, "extend-css");
if !p.is_file() {
println!("{}", "--extend-css option must take a css file as input");
return 1;