diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index 7bc510a2f6c..1789c3513f6 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -1,5 +1,5 @@ use std::collections::BTreeMap; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::{collections::HashMap, future::Future}; use crate::{insert_all_files_for_workspace_into_file_manager, parse_diff, PackageCacheData}; @@ -301,6 +301,10 @@ fn on_formatting_inner( state: &LspState, params: lsp_types::DocumentFormattingParams, ) -> Result>, ResponseError> { + // The file_path might be Err/None if the action runs against an unsaved file + let file_path = params.text_document.uri.to_file_path().ok(); + let directory_path = file_path.as_ref().and_then(|path| path.parent()); + let path = params.text_document.uri.to_string(); if let Some(source) = state.input_files.get(&path) { @@ -310,7 +314,8 @@ fn on_formatting_inner( return Ok(None); } - let new_text = nargo_fmt::format(source, module, &Config::default()); + let config = read_format_config(directory_path); + let new_text = nargo_fmt::format(source, module, &config); let start_position = Position { line: 0, character: 0 }; let end_position = Position { @@ -327,6 +332,19 @@ fn on_formatting_inner( } } +fn read_format_config(file_path: Option<&Path>) -> Config { + match file_path { + Some(file_path) => match Config::read(file_path) { + Ok(config) => config, + Err(err) => { + eprintln!("{}", err); + Config::default() + } + }, + None => Config::default(), + } +} + pub(crate) fn position_to_byte_index<'a, F>( files: &'a F, file_id: F::FileId, diff --git a/tooling/nargo_fmt/build.rs b/tooling/nargo_fmt/build.rs index a95cbe16525..988a7dcc94d 100644 --- a/tooling/nargo_fmt/build.rs +++ b/tooling/nargo_fmt/build.rs @@ -62,7 +62,7 @@ fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { let (parsed_module, _errors) = noirc_frontend::parse_program(input); - let config = nargo_fmt::Config::of("{config}").unwrap(); + let config = nargo_fmt::Config::of("{config}", &std::path::PathBuf::new()).unwrap(); let fmt_text = nargo_fmt::format(input, parsed_module, &config); if std::env::var("UPDATE_EXPECT").is_ok() {{ @@ -84,7 +84,7 @@ fn generate_formatter_tests(test_file: &mut File, test_data_dir: &Path) { let (parsed_module, _errors) = noirc_frontend::parse_program(expected_output); - let config = nargo_fmt::Config::of("{config}").unwrap(); + let config = nargo_fmt::Config::of("{config}", &std::path::PathBuf::new()).unwrap(); let fmt_text = nargo_fmt::format(expected_output, parsed_module, &config); similar_asserts::assert_eq!(fmt_text, expected_output); diff --git a/tooling/nargo_fmt/src/config.rs b/tooling/nargo_fmt/src/config.rs index 488647c0b39..f01afc87af2 100644 --- a/tooling/nargo_fmt/src/config.rs +++ b/tooling/nargo_fmt/src/config.rs @@ -56,21 +56,30 @@ config! { } impl Config { - pub fn read(path: &Path) -> Result { - let config_path = path.join("noirfmt.toml"); + /// Reads a Config starting at the given path and going through the path parents + /// until a `noirfmt.toml` file is found in one of them or the root is reached. + pub fn read(mut path: &Path) -> Result { + loop { + let config_path = path.join("noirfmt.toml"); + if config_path.exists() { + match std::fs::read_to_string(&config_path) { + Ok(input) => return Self::of(&input, &config_path), + Err(cause) => return Err(ConfigError::ReadFailed(config_path, cause)), + }; + } - let input = match std::fs::read_to_string(&config_path) { - Ok(input) => input, - Err(cause) if cause.kind() == std::io::ErrorKind::NotFound => String::new(), - Err(cause) => return Err(ConfigError::ReadFailed(config_path, cause)), - }; + let Some(parent_path) = path.parent() else { + return Ok(Config::default()); + }; - Self::of(&input) + path = parent_path; + } } - pub fn of(s: &str) -> Result { + pub fn of(s: &str, path: &Path) -> Result { let mut config = Self::default(); - let toml = toml::from_str(s).map_err(ConfigError::MalformedFile)?; + let toml = + toml::from_str(s).map_err(|err| ConfigError::MalformedFile(path.to_path_buf(), err))?; config.fill_from_toml(toml); Ok(config) } diff --git a/tooling/nargo_fmt/src/errors.rs b/tooling/nargo_fmt/src/errors.rs index e0a1758ae0f..f766234dcde 100644 --- a/tooling/nargo_fmt/src/errors.rs +++ b/tooling/nargo_fmt/src/errors.rs @@ -7,6 +7,6 @@ pub enum ConfigError { #[error("Cannot read file {0} - {1}")] ReadFailed(PathBuf, std::io::Error), - #[error("noirfmt.toml is badly formed, could not parse.\n\n {0}")] - MalformedFile(#[from] toml::de::Error), + #[error("{0} is badly formed, could not parse.\n\n {1}")] + MalformedFile(PathBuf, toml::de::Error), }