-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
--------- Co-authored-by: John-John Tedro <[email protected]>
- Loading branch information
Showing
30 changed files
with
2,852 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use anyhow::{Context, Result}; | ||
use clap::Parser; | ||
use std::io::Write; | ||
use std::path::PathBuf; | ||
|
||
use crate::cli::{ExitCode, Io, SharedFlags}; | ||
use crate::termcolor::WriteColor; | ||
use crate::Source; | ||
|
||
#[derive(Parser, Debug, Clone)] | ||
pub(super) struct Flags { | ||
/// Exit with a non-zero exit-code even for warnings | ||
#[arg(long)] | ||
warnings_are_errors: bool, | ||
|
||
#[command(flatten)] | ||
pub(super) shared: SharedFlags, | ||
|
||
#[arg(long)] | ||
check: bool, | ||
} | ||
|
||
pub(super) fn run(io: &mut Io<'_>, paths: &[PathBuf], flags: &Flags) -> Result<ExitCode> { | ||
let mut red = crate::termcolor::ColorSpec::new(); | ||
red.set_fg(Some(crate::termcolor::Color::Red)); | ||
|
||
let mut green = crate::termcolor::ColorSpec::new(); | ||
green.set_fg(Some(crate::termcolor::Color::Green)); | ||
|
||
let mut yellow = crate::termcolor::ColorSpec::new(); | ||
yellow.set_fg(Some(crate::termcolor::Color::Yellow)); | ||
|
||
let mut succeeded = 0; | ||
let mut failed = 0; | ||
let mut unchanged = 0; | ||
|
||
for path in paths { | ||
let source = | ||
Source::from_path(path).with_context(|| format!("reading file: {}", path.display()))?; | ||
|
||
match crate::fmt::layout_source(&source) { | ||
Ok(val) => { | ||
if val == source.as_str() { | ||
if !flags.check { | ||
io.stdout.set_color(&yellow)?; | ||
write!(io.stdout, "== ")?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, "{}", path.display())?; | ||
} | ||
|
||
unchanged += 1; | ||
} else { | ||
succeeded += 1; | ||
io.stdout.set_color(&green)?; | ||
write!(io.stdout, "++ ")?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, "{}", path.display())?; | ||
if !flags.check { | ||
std::fs::write(path, &val)?; | ||
} | ||
} | ||
} | ||
Err(err) => { | ||
failed += 1; | ||
io.stdout.set_color(&red)?; | ||
write!(io.stdout, "!! ")?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, "{}: {}", path.display(), err)?; | ||
} | ||
} | ||
} | ||
|
||
io.stdout.set_color(&yellow)?; | ||
write!(io.stdout, "{}", unchanged)?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, " unchanged")?; | ||
io.stdout.set_color(&green)?; | ||
write!(io.stdout, "{}", succeeded)?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, " succeeded")?; | ||
io.stdout.set_color(&red)?; | ||
write!(io.stdout, "{}", failed)?; | ||
io.stdout.reset()?; | ||
writeln!(io.stdout, " failed")?; | ||
|
||
if flags.check && succeeded > 0 { | ||
io.stdout.set_color(&red)?; | ||
write!( | ||
io.stdout, | ||
"Exiting with failure due to `--check` flag and unformatted files." | ||
)?; | ||
io.stdout.reset()?; | ||
return Ok(ExitCode::Failure); | ||
} | ||
|
||
if failed > 0 { | ||
return Ok(ExitCode::Failure); | ||
} | ||
|
||
Ok(ExitCode::Success) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
//! Helper to format Rune code. | ||
mod comments; | ||
mod error; | ||
mod indent_writer; | ||
mod printer; | ||
mod whitespace; | ||
|
||
use crate::ast; | ||
use crate::parse::{Parse, Parser}; | ||
use crate::{Source, SourceId}; | ||
|
||
use self::error::FormattingError; | ||
use self::printer::Printer; | ||
|
||
/// Format the given contents. | ||
pub fn layout_string(contents: String) -> Result<String, FormattingError> { | ||
let s = Source::new("<memory>", contents); | ||
layout_source(&s) | ||
} | ||
|
||
/// Format the given source. | ||
pub fn layout_source(source: &Source) -> Result<String, FormattingError> { | ||
let mut parser = Parser::new(source.as_str(), SourceId::new(0), true); | ||
|
||
let ast = ast::File::parse(&mut parser)?; | ||
let mut printer: Printer = Printer::new(source)?; | ||
|
||
printer.visit_file(&ast)?; | ||
|
||
let res = printer.commit().trim().to_owned() + "\n"; | ||
|
||
Ok(res) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
//! Extract comments from source code. | ||
#[cfg(test)] | ||
mod tests; | ||
|
||
use std::str::CharIndices; | ||
|
||
use crate::ast::Span; | ||
|
||
use super::error::FormattingError; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub(super) enum CommentKind { | ||
Line, | ||
Block, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
pub(super) struct Comment { | ||
pub(super) kind: CommentKind, | ||
pub(super) span: Span, | ||
pub(super) on_new_line: bool, | ||
} | ||
|
||
pub(super) fn parse_comments(input: &str) -> Result<Vec<Comment>, FormattingError> { | ||
let mut comments = Vec::new(); | ||
|
||
let mut chars = input.char_indices(); | ||
|
||
let mut in_string = false; | ||
let mut in_char = false; | ||
let mut in_template = false; | ||
let mut on_new_line = true; | ||
|
||
while let Some((idx, c)) = chars.next() { | ||
match c { | ||
'/' if !in_string && !in_char && !in_template => match chars.clone().next() { | ||
Some((_, '/')) => { | ||
let end = parse_line_comment(&mut chars); | ||
|
||
if !input[idx..end].starts_with("///") && !input[idx..end].starts_with("//!") { | ||
comments.push(Comment { | ||
on_new_line, | ||
kind: CommentKind::Line, | ||
span: Span::new(idx, end), | ||
}); | ||
} | ||
} | ||
Some((_, '*')) => { | ||
let end = parse_block_comment(&mut chars).ok_or(FormattingError::Eof)?; | ||
|
||
if !input[idx..end].starts_with("/**") && !input[idx..end].starts_with("/*!") { | ||
comments.push(Comment { | ||
on_new_line, | ||
kind: CommentKind::Block, | ||
span: Span::new(idx, end), | ||
}); | ||
} | ||
} | ||
_ => {} | ||
}, | ||
'"' => { | ||
on_new_line = false; | ||
if !in_char && !in_template { | ||
in_string = !in_string; | ||
} | ||
} | ||
'\'' => { | ||
on_new_line = false; | ||
if !in_string && !in_template { | ||
in_char = !in_char; | ||
} | ||
} | ||
'`' => { | ||
on_new_line = false; | ||
if !in_string && !in_char { | ||
in_template = !in_template; | ||
} | ||
} | ||
'\n' => { | ||
on_new_line = true; | ||
} | ||
c if c.is_whitespace() => {} | ||
_ => { | ||
on_new_line = false; | ||
} | ||
} | ||
} | ||
|
||
Ok(comments) | ||
} | ||
|
||
fn parse_line_comment(chars: &mut CharIndices<'_>) -> usize { | ||
let mut last_i = 0; | ||
|
||
for (i, c) in chars.by_ref() { | ||
match c { | ||
'\n' => return i, | ||
_ => { | ||
last_i = i; | ||
} | ||
} | ||
} | ||
|
||
last_i + 1 | ||
} | ||
|
||
fn parse_block_comment(chars: &mut CharIndices<'_>) -> Option<usize> { | ||
while let Some((_, c)) = chars.next() { | ||
if c == '*' { | ||
if let Some((_, '/')) = chars.clone().next() { | ||
return Some(chars.next()?.0); | ||
} | ||
} | ||
} | ||
|
||
None | ||
} |
Oops, something went wrong.