Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read air.toml and use in air format #109

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 90 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ line_ending = { path = "./crates/line_ending" }
lsp = { path = "./crates/lsp" }
lsp_test = { path = "./crates/lsp_test" }
tests_macros = { path = "./crates/tests_macros" }
workspace = { path = "./crates/workspace" }

anyhow = "1.0.89"
assert_matches = "1.5.0"
Expand All @@ -56,17 +57,22 @@ ignore = "0.4.23"
insta = "1.40.0"
itertools = "0.13.0"
line-index = "0.1.2"
matchit = "0.8.5"
memchr = "2.7.4"
path-absolutize = "3.1.1"
path-slash = "0.2.1"
proc-macro2 = "1.0.86"
serde = { version = "1.0.215", features = ["derive"] }
rustc-hash = "2.1.0"
serde = "1.0.215"
serde_json = "1.0.132"
struct-field-names-as-array = "0.3.0"
strum = "0.26"
tempfile = "3.9.0"
time = "0.3.37"
thiserror = "2.0.5"
tokio = { version = "1.41.1" }
tokio-util = "0.7.12"
toml = "0.8.19"
# For https://github.com/ebkalderon/tower-lsp/pull/428
tower-lsp = { git = "https://github.com/lionel-/tower-lsp", branch = "bugfix/patches" }
tracing = { version = "0.1.40", default-features = false, features = ["std"] }
Expand Down
3 changes: 2 additions & 1 deletion crates/air/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ lsp = { workspace = true }
thiserror = { workspace = true }
tokio = "1.41.1"
tracing = { workspace = true }
workspace = { workspace = true }

[dev-dependencies]
tempfile = "3.9.0"
tempfile = { workspace = true }

[lints]
workspace = true
82 changes: 13 additions & 69 deletions crates/air/src/commands/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@ use std::path::PathBuf;
use air_r_formatter::context::RFormatOptions;
use air_r_parser::RParserOptions;
use fs::relativize_path;
use ignore::DirEntry;
use itertools::Either;
use itertools::Itertools;
use line_ending::LineEnding;
use thiserror::Error;
use workspace::resolve::resolve_paths;
use workspace::settings::FormatSettings;

use crate::args::FormatCommand;
use crate::ExitStatus;

pub(crate) fn format(command: FormatCommand) -> anyhow::Result<ExitStatus> {
let mode = FormatMode::from_command(&command);
let paths = resolve_paths(&command.paths);
let (paths, resolver) = resolve_paths(&command.paths)?;

let (actions, errors): (Vec<_>, Vec<_>) = paths
.into_iter()
.map(|path| match path {
Ok(path) => format_file(path, mode),
Ok(path) => {
let settings = resolver.resolve(&path);
format_file(path, mode, &settings.format)
}
Err(err) => Err(err.into()),
})
.partition_map(|result| match result {
Expand Down Expand Up @@ -99,62 +102,6 @@ fn write_changed(actions: &[FormatFileAction], f: &mut impl Write) -> io::Result
Ok(())
}

fn resolve_paths(paths: &[PathBuf]) -> Vec<Result<PathBuf, ignore::Error>> {
let paths: Vec<PathBuf> = paths.iter().map(fs::normalize_path).collect();

let (first_path, paths) = paths
.split_first()
.expect("Clap should ensure at least 1 path is supplied.");

// TODO: Parallel directory visitor
let mut builder = ignore::WalkBuilder::new(first_path);

for path in paths {
builder.add(path);
}

let mut out = Vec::new();

for path in builder.build() {
match path {
Ok(entry) => {
if let Some(path) = is_valid_path(entry) {
out.push(Ok(path));
}
}
Err(err) => {
out.push(Err(err));
}
}
}

out
}

// Decide whether or not to accept an `entry` based on include/exclude rules.
fn is_valid_path(entry: DirEntry) -> Option<PathBuf> {
// Ignore directories
if entry.file_type().map_or(true, |ft| ft.is_dir()) {
return None;
}

// Accept all files that are passed-in directly, even non-R files
if entry.depth() == 0 {
let path = entry.into_path();
return Some(path);
}

// Otherwise check if we should accept this entry
// TODO: Many other checks based on user exclude/includes
let path = entry.into_path();

if !fs::has_r_extension(&path) {
return None;
}

Some(path)
}

pub(crate) enum FormatFileAction {
Formatted(PathBuf),
Unchanged,
Expand All @@ -166,18 +113,15 @@ impl FormatFileAction {
}
}

// TODO: Take workspace `FormatOptions` that get resolved to `RFormatOptions`
// for the formatter here. Respect user specified `LineEnding` option too, and
// only use inferred endings when `FormatOptions::LineEnding::Auto` is used.
fn format_file(path: PathBuf, mode: FormatMode) -> Result<FormatFileAction, FormatCommandError> {
fn format_file(
path: PathBuf,
mode: FormatMode,
settings: &FormatSettings,
) -> Result<FormatFileAction, FormatCommandError> {
let source = std::fs::read_to_string(&path)
.map_err(|err| FormatCommandError::Read(path.clone(), err))?;

let line_ending = match line_ending::infer(&source) {
LineEnding::Lf => biome_formatter::LineEnding::Lf,
LineEnding::Crlf => biome_formatter::LineEnding::Crlf,
};
let options = RFormatOptions::default().with_line_ending(line_ending);
let options = settings.to_format_options(&source);

let source = line_ending::normalize(source);
let formatted = match format_source(source.as_str(), options) {
Expand Down
14 changes: 14 additions & 0 deletions crates/air_r_formatter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use biome_formatter::TransformSourceMap;
use crate::comments::FormatRLeadingComment;
use crate::comments::RCommentStyle;
use crate::comments::RComments;
use crate::options::MagicLineBreak;

pub struct RFormatContext {
options: RFormatOptions,
Expand Down Expand Up @@ -77,6 +78,10 @@ pub struct RFormatOptions {

/// The max width of a line. Defaults to 80.
line_width: LineWidth,

// TODO: Actually use this internally!
/// The behavior of magic line breaks.
magic_line_break: MagicLineBreak,
}

impl RFormatOptions {
Expand Down Expand Up @@ -106,6 +111,11 @@ impl RFormatOptions {
self
}

pub fn with_magic_line_break(mut self, magic_line_break: MagicLineBreak) -> Self {
self.magic_line_break = magic_line_break;
self
}

pub fn set_indent_style(&mut self, indent_style: IndentStyle) {
self.indent_style = indent_style;
}
Expand All @@ -121,6 +131,10 @@ impl RFormatOptions {
pub fn set_line_width(&mut self, line_width: LineWidth) {
self.line_width = line_width;
}

pub fn set_magic_line_break(&mut self, magic_line_break: MagicLineBreak) {
self.magic_line_break = magic_line_break;
}
}

impl FormatOptions for RFormatOptions {
Expand Down
1 change: 1 addition & 0 deletions crates/air_r_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::cst::FormatRSyntaxNode;
pub mod comments;
pub mod context;
mod cst;
pub mod options;
mod prelude;
mod r;
pub(crate) mod separated;
Expand Down
3 changes: 3 additions & 0 deletions crates/air_r_formatter/src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod magic_line_break;

pub use magic_line_break::*;
Loading
Loading