Merge pull request #3468 from topecongiro/refactor-create_config
Move some code out of create_config
This commit is contained in:
commit
a5cc780c98
@ -93,19 +93,6 @@ pub struct PartialConfig {
|
||||
$(pub $i: Option<$ty>),+
|
||||
}
|
||||
|
||||
impl PartialConfig {
|
||||
pub fn to_toml(&self) -> Result<String, String> {
|
||||
// Non-user-facing options can't be specified in TOML
|
||||
let mut cloned = self.clone();
|
||||
cloned.file_lines = None;
|
||||
cloned.verbose = None;
|
||||
cloned.width_heuristics = None;
|
||||
|
||||
::toml::to_string(&cloned)
|
||||
.map_err(|e| format!("Could not output config: {}", e))
|
||||
}
|
||||
}
|
||||
|
||||
// Macro hygiene won't allow us to make `set_$i()` methods on Config
|
||||
// for each item, so this struct is used to give the API to set values:
|
||||
// `config.set().option(false)`. It's pretty ugly. Consider replacing
|
||||
@ -139,23 +126,6 @@ pub fn $i(&self) -> bool {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn version_meets_requirement(&self) -> bool {
|
||||
if self.was_set().required_version() {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let required_version = self.required_version();
|
||||
if version != required_version {
|
||||
println!(
|
||||
"Error: rustfmt version ({}) doesn't match the required version ({})",
|
||||
version,
|
||||
required_version,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
$(
|
||||
pub fn $i(&self) -> $ty {
|
||||
self.$i.0.set(true);
|
||||
@ -213,37 +183,6 @@ pub(crate) fn is_valid_name(name: &str) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
|
||||
let parsed: ::toml::Value =
|
||||
toml.parse().map_err(|e| format!("Could not parse TOML: {}", e))?;
|
||||
let mut err: String = String::new();
|
||||
{
|
||||
let table = parsed
|
||||
.as_table()
|
||||
.ok_or(String::from("Parsed config was not table"))?;
|
||||
for key in table.keys() {
|
||||
if !Config::is_valid_name(key) {
|
||||
let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
|
||||
err.push_str(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
match parsed.try_into() {
|
||||
Ok(parsed_config) => {
|
||||
if !err.is_empty() {
|
||||
eprint!("{}", err);
|
||||
}
|
||||
Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
|
||||
}
|
||||
Err(e) => {
|
||||
err.push_str("Error: Decoding config file failed:\n");
|
||||
err.push_str(format!("{}\n", e).as_str());
|
||||
err.push_str("Please check your config file.");
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn used_options(&self) -> PartialConfig {
|
||||
PartialConfig {
|
||||
$(
|
||||
@ -287,82 +226,6 @@ pub fn override_value(&mut self, key: &str, val: &str)
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a `Config` from the toml file specified at `file_path`.
|
||||
///
|
||||
/// This method only looks at the provided path, for a method that
|
||||
/// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`.
|
||||
///
|
||||
/// Returns a `Config` if the config could be read and parsed from
|
||||
/// the file, otherwise errors.
|
||||
pub(super) fn from_toml_path(file_path: &Path) -> Result<Config, Error> {
|
||||
let mut file = File::open(&file_path)?;
|
||||
let mut toml = String::new();
|
||||
file.read_to_string(&mut toml)?;
|
||||
Config::from_toml(&toml, file_path.parent().unwrap())
|
||||
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
|
||||
}
|
||||
|
||||
/// Resolves the config for input in `dir`.
|
||||
///
|
||||
/// Searches for `rustfmt.toml` beginning with `dir`, and
|
||||
/// recursively checking parents of `dir` if no config file is found.
|
||||
/// If no config file exists in `dir` or in any parent, a
|
||||
/// default `Config` will be returned (and the returned path will be empty).
|
||||
///
|
||||
/// Returns the `Config` to use, and the path of the project file if there was
|
||||
/// one.
|
||||
pub(super) fn from_resolved_toml_path(
|
||||
dir: &Path,
|
||||
) -> Result<(Config, Option<PathBuf>), Error> {
|
||||
/// Try to find a project file in the given directory and its parents.
|
||||
/// Returns the path of a the nearest project file if one exists,
|
||||
/// or `None` if no project file was found.
|
||||
fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
|
||||
let mut current = if dir.is_relative() {
|
||||
env::current_dir()?.join(dir)
|
||||
} else {
|
||||
dir.to_path_buf()
|
||||
};
|
||||
|
||||
current = fs::canonicalize(current)?;
|
||||
|
||||
loop {
|
||||
match get_toml_path(¤t) {
|
||||
Ok(Some(path)) => return Ok(Some(path)),
|
||||
Err(e) => return Err(e),
|
||||
_ => ()
|
||||
}
|
||||
|
||||
// If the current directory has no parent, we're done searching.
|
||||
if !current.pop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing was found, check in the home directory.
|
||||
if let Some(home_dir) = dirs::home_dir() {
|
||||
if let Some(path) = get_toml_path(&home_dir)? {
|
||||
return Ok(Some(path));
|
||||
}
|
||||
}
|
||||
|
||||
// If none was found ther either, check in the user's configuration directory.
|
||||
if let Some(mut config_dir) = dirs::config_dir() {
|
||||
config_dir.push("rustfmt");
|
||||
if let Some(path) = get_toml_path(&config_dir)? {
|
||||
return Ok(Some(path));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match resolve_project_file(dir)? {
|
||||
None => Ok((Config::default(), None)),
|
||||
Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_hidden_option(name: &str) -> bool {
|
||||
const HIDE_OPTIONS: [&str; 4] =
|
||||
["verbose", "verbose_diff", "file_lines", "width_heuristics"];
|
||||
|
@ -150,6 +150,142 @@
|
||||
make_backup: bool, false, false, "Backup changed files";
|
||||
}
|
||||
|
||||
impl PartialConfig {
|
||||
pub fn to_toml(&self) -> Result<String, String> {
|
||||
// Non-user-facing options can't be specified in TOML
|
||||
let mut cloned = self.clone();
|
||||
cloned.file_lines = None;
|
||||
cloned.verbose = None;
|
||||
cloned.width_heuristics = None;
|
||||
|
||||
::toml::to_string(&cloned).map_err(|e| format!("Could not output config: {}", e))
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub(crate) fn version_meets_requirement(&self) -> bool {
|
||||
if self.was_set().required_version() {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let required_version = self.required_version();
|
||||
if version != required_version {
|
||||
println!(
|
||||
"Error: rustfmt version ({}) doesn't match the required version ({})",
|
||||
version, required_version,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Constructs a `Config` from the toml file specified at `file_path`.
|
||||
///
|
||||
/// This method only looks at the provided path, for a method that
|
||||
/// searches parents for a `rustfmt.toml` see `from_resolved_toml_path`.
|
||||
///
|
||||
/// Returns a `Config` if the config could be read and parsed from
|
||||
/// the file, otherwise errors.
|
||||
pub(super) fn from_toml_path(file_path: &Path) -> Result<Config, Error> {
|
||||
let mut file = File::open(&file_path)?;
|
||||
let mut toml = String::new();
|
||||
file.read_to_string(&mut toml)?;
|
||||
Config::from_toml(&toml, file_path.parent().unwrap())
|
||||
.map_err(|err| Error::new(ErrorKind::InvalidData, err))
|
||||
}
|
||||
|
||||
/// Resolves the config for input in `dir`.
|
||||
///
|
||||
/// Searches for `rustfmt.toml` beginning with `dir`, and
|
||||
/// recursively checking parents of `dir` if no config file is found.
|
||||
/// If no config file exists in `dir` or in any parent, a
|
||||
/// default `Config` will be returned (and the returned path will be empty).
|
||||
///
|
||||
/// Returns the `Config` to use, and the path of the project file if there was
|
||||
/// one.
|
||||
pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option<PathBuf>), Error> {
|
||||
/// Try to find a project file in the given directory and its parents.
|
||||
/// Returns the path of a the nearest project file if one exists,
|
||||
/// or `None` if no project file was found.
|
||||
fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
|
||||
let mut current = if dir.is_relative() {
|
||||
env::current_dir()?.join(dir)
|
||||
} else {
|
||||
dir.to_path_buf()
|
||||
};
|
||||
|
||||
current = fs::canonicalize(current)?;
|
||||
|
||||
loop {
|
||||
match get_toml_path(¤t) {
|
||||
Ok(Some(path)) => return Ok(Some(path)),
|
||||
Err(e) => return Err(e),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// If the current directory has no parent, we're done searching.
|
||||
if !current.pop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing was found, check in the home directory.
|
||||
if let Some(home_dir) = dirs::home_dir() {
|
||||
if let Some(path) = get_toml_path(&home_dir)? {
|
||||
return Ok(Some(path));
|
||||
}
|
||||
}
|
||||
|
||||
// If none was found ther either, check in the user's configuration directory.
|
||||
if let Some(mut config_dir) = dirs::config_dir() {
|
||||
config_dir.push("rustfmt");
|
||||
if let Some(path) = get_toml_path(&config_dir)? {
|
||||
return Ok(Some(path));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match resolve_project_file(dir)? {
|
||||
None => Ok((Config::default(), None)),
|
||||
Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
|
||||
let parsed: ::toml::Value = toml
|
||||
.parse()
|
||||
.map_err(|e| format!("Could not parse TOML: {}", e))?;
|
||||
let mut err: String = String::new();
|
||||
{
|
||||
let table = parsed
|
||||
.as_table()
|
||||
.ok_or(String::from("Parsed config was not table"))?;
|
||||
for key in table.keys() {
|
||||
if !Config::is_valid_name(key) {
|
||||
let msg = &format!("Warning: Unknown configuration option `{}`\n", key);
|
||||
err.push_str(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
match parsed.try_into() {
|
||||
Ok(parsed_config) => {
|
||||
if !err.is_empty() {
|
||||
eprint!("{}", err);
|
||||
}
|
||||
Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
|
||||
}
|
||||
Err(e) => {
|
||||
err.push_str("Error: Decoding config file failed:\n");
|
||||
err.push_str(format!("{}\n", e).as_str());
|
||||
err.push_str("Please check your config file.");
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a config by checking the client-supplied options and if appropriate, the
|
||||
/// file system (including searching the file system for overrides).
|
||||
pub fn load_config<O: CliOptions>(
|
||||
|
Loading…
Reference in New Issue
Block a user