Skip to content

Commit

Permalink
fix(formatter): respect IndentWidth in IndentStyle::Tab (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari authored Aug 30, 2023
1 parent 35c41be commit d22ccef
Show file tree
Hide file tree
Showing 237 changed files with 693 additions and 70 deletions.
4 changes: 3 additions & 1 deletion crates/rome_cli/tests/snap_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ impl CliSnapshot {
JsonParserOptions::default(),
);
let formatted = format_node(
JsonFormatOptions::default().with_indent_style(IndentStyle::Space(2)),
JsonFormatOptions::default()
.with_indent_style(IndentStyle::Space)
.with_indent_width(2.into()),
&parsed.syntax(),
)
.expect("formatted JSON")
Expand Down
3 changes: 2 additions & 1 deletion crates/rome_formatter/src/builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,8 @@ where
///
/// # fn main() -> FormatResult<()> {
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
/// indent_style: IndentStyle::Space(4),
/// indent_style: IndentStyle::Space,
/// indent_width: 4.into(),
/// ..SimpleFormatOptions::default()
/// });
///
Expand Down
12 changes: 8 additions & 4 deletions crates/rome_formatter/src/format_element/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::printer::LineEnding;
use crate::{format, write};
use crate::{
BufferExtensions, Format, FormatContext, FormatElement, FormatOptions, FormatResult, Formatter,
IndentStyle, LineWidth, PrinterOptions, TransformSourceMap,
IndentStyle, IndentWidth, LineWidth, PrinterOptions, TransformSourceMap,
};
use rome_rowan::TextSize;
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -153,7 +153,11 @@ struct IrFormatOptions;

impl FormatOptions for IrFormatOptions {
fn indent_style(&self) -> IndentStyle {
IndentStyle::Space(2)
IndentStyle::Space
}

fn indent_width(&self) -> IndentWidth {
IndentWidth::default()
}

fn line_width(&self) -> LineWidth {
Expand All @@ -162,10 +166,10 @@ impl FormatOptions for IrFormatOptions {

fn as_print_options(&self) -> PrinterOptions {
PrinterOptions {
tab_width: 2,
indent_width: self.indent_width(),
print_width: self.line_width().into(),
line_ending: LineEnding::LineFeed,
indent_style: IndentStyle::Space(2),
indent_style: IndentStyle::Space,
}
}
}
Expand Down
51 changes: 44 additions & 7 deletions crates/rome_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ pub enum IndentStyle {
/// Tab
#[default]
Tab,
/// Space, with its quantity
Space(u8),
/// Space
Space,
}

impl IndentStyle {
Expand All @@ -96,7 +96,7 @@ impl IndentStyle {

/// Returns `true` if this is an [IndentStyle::Space].
pub const fn is_space(&self) -> bool {
matches!(self, IndentStyle::Space(_))
matches!(self, IndentStyle::Space)
}
}

Expand All @@ -106,7 +106,7 @@ impl FromStr for IndentStyle {
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"tab" | "Tabs" => Ok(Self::Tab),
"space" | "Spaces" => Ok(Self::Space(IndentStyle::DEFAULT_SPACES)),
"space" | "Spaces" => Ok(Self::Space),
// TODO: replace this error with a diagnostic
_ => Err("Value not supported for IndentStyle"),
}
Expand All @@ -117,11 +117,38 @@ impl std::fmt::Display for IndentStyle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IndentStyle::Tab => std::write!(f, "Tab"),
IndentStyle::Space(size) => std::write!(f, "Spaces, size: {}", size),
IndentStyle::Space => std::write!(f, "Space"),
}
}
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
serde(rename_all = "camelCase")
)]
pub struct IndentWidth(u8);

impl IndentWidth {
/// Return the numeric value for this [IndentWidth]
pub fn value(&self) -> u8 {
self.0
}
}

impl Default for IndentWidth {
fn default() -> Self {
Self(2)
}
}

impl From<u8> for IndentWidth {
fn from(value: u8) -> Self {
Self(value)
}
}

/// Validated value for the `line_width` formatter options
///
/// The allowed range of values is 1..=320
Expand Down Expand Up @@ -234,6 +261,9 @@ pub trait FormatOptions {
/// The indent style.
fn indent_style(&self) -> IndentStyle;

/// The indent width.
fn indent_width(&self) -> IndentWidth;

/// What's the max width of a line. Defaults to 80.
fn line_width(&self) -> LineWidth;

Expand Down Expand Up @@ -282,6 +312,7 @@ impl FormatContext for SimpleFormatContext {
#[derive(Debug, Default, Eq, PartialEq)]
pub struct SimpleFormatOptions {
pub indent_style: IndentStyle,
pub indent_width: IndentWidth,
pub line_width: LineWidth,
}

Expand All @@ -290,13 +321,18 @@ impl FormatOptions for SimpleFormatOptions {
self.indent_style
}

fn indent_width(&self) -> IndentWidth {
self.indent_width
}

fn line_width(&self) -> LineWidth {
self.line_width
}

fn as_print_options(&self) -> PrinterOptions {
PrinterOptions::default()
.with_indent(self.indent_style)
.with_indent_style(self.indent_style)
.with_indent_width(self.indent_width)
.with_print_width(self.line_width.into())
}
}
Expand Down Expand Up @@ -1322,9 +1358,10 @@ pub fn format_sub_tree<L: FormatLanguage>(
// of indentation type detection yet. Unfortunately this
// may not actually match the current content of the file
let length = trivia.text().len() as u16;
let width = language.options().indent_width().value();
match language.options().indent_style() {
IndentStyle::Tab => length,
IndentStyle::Space(width) => length / u16::from(width),
IndentStyle::Space => length / u16::from(width),
}
}
// No whitespace was found between the start of the range
Expand Down
14 changes: 8 additions & 6 deletions crates/rome_formatter/src/printer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl<'a> Printer<'a> {
if !self.state.pending_indent.is_empty() {
let (indent_char, repeat_count) = match self.options.indent_style() {
IndentStyle::Tab => ('\t', 1),
IndentStyle::Space(count) => (' ', count),
IndentStyle::Space => (' ', self.options.indent_width().value()),
};

let indent = std::mem::take(&mut self.state.pending_indent);
Expand Down Expand Up @@ -666,7 +666,7 @@ impl<'a> Printer<'a> {
self.state.generated_column += 1;

let char_width = if char == '\t' {
self.options.tab_width as usize
self.options.indent_width().value() as usize
} else {
char.width().unwrap_or(0)
};
Expand Down Expand Up @@ -1139,7 +1139,8 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {

fn fits_text(&mut self, text: &str) -> Fits {
let indent = std::mem::take(&mut self.state.pending_indent);
self.state.line_width += indent.level() as usize * self.options().indent_width() as usize
self.state.line_width += indent.level() as usize
* self.options().indent_width().value() as usize
+ indent.align() as usize;

if self.state.pending_space {
Expand All @@ -1148,7 +1149,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {

for c in text.chars() {
let char_width = match c {
'\t' => self.options().tab_width as usize,
'\t' => self.options().indent_width.value() as usize,
'\n' => {
return if self.must_be_flat {
Fits::No
Expand Down Expand Up @@ -1266,7 +1267,8 @@ mod tests {
format_with_options(
root,
PrinterOptions {
indent_style: IndentStyle::Space(2),
indent_style: IndentStyle::Space,
indent_width: 2.into(),
..PrinterOptions::default()
},
)
Expand Down Expand Up @@ -1410,7 +1412,7 @@ two lines`,
fn it_use_the_indent_character_specified_in_the_options() {
let options = PrinterOptions {
indent_style: IndentStyle::Tab,
tab_width: 4,
indent_width: 4.into(),
print_width: PrintWidth::new(19),
..PrinterOptions::default()
};
Expand Down
27 changes: 16 additions & 11 deletions crates/rome_formatter/src/printer/printer_options/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{FormatOptions, IndentStyle, LineWidth};
use crate::{FormatOptions, IndentStyle, IndentWidth, LineWidth};

/// Options that affect how the [crate::Printer] prints the format tokens
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PrinterOptions {
/// Width of a single tab character (does it equal 2, 4, ... spaces?)
pub tab_width: u8,
/// Width of an indent in characters.
/// if indent_style is set to IndentStyle::Tab, treat tab visualization width as this value.
pub indent_width: IndentWidth,

/// What's the max width of a line. Defaults to 80
pub print_width: PrintWidth,
Expand Down Expand Up @@ -49,7 +50,8 @@ where
{
fn from(options: &'a O) -> Self {
PrinterOptions::default()
.with_indent(options.indent_style())
.with_indent_style(options.indent_style())
.with_indent_width(options.indent_width())
.with_print_width(options.line_width().into())
}
}
Expand All @@ -60,22 +62,25 @@ impl PrinterOptions {
self
}

pub fn with_indent(mut self, style: IndentStyle) -> Self {
pub fn with_indent_style(mut self, style: IndentStyle) -> Self {
self.indent_style = style;

self
}

pub fn with_indent_width(mut self, width: IndentWidth) -> Self {
self.indent_width = width;

self
}

pub(crate) fn indent_style(&self) -> IndentStyle {
self.indent_style
}

/// Width of an indent in characters.
pub(super) const fn indent_width(&self) -> u8 {
match self.indent_style {
IndentStyle::Tab => self.tab_width,
IndentStyle::Space(count) => count,
}
pub(super) const fn indent_width(&self) -> IndentWidth {
self.indent_width
}
}

Expand Down Expand Up @@ -106,7 +111,7 @@ impl LineEnding {
impl Default for PrinterOptions {
fn default() -> Self {
PrinterOptions {
tab_width: 2,
indent_width: 2.into(),
print_width: PrintWidth::default(),
indent_style: Default::default(),
line_ending: LineEnding::LineFeed,
Expand Down
23 changes: 17 additions & 6 deletions crates/rome_js_formatter/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use rome_deserialize::{DeserializationDiagnostic, VisitNode};
use rome_formatter::printer::PrinterOptions;
use rome_formatter::token::string::Quote;
use rome_formatter::{
CstFormatContext, FormatContext, FormatElement, FormatOptions, IndentStyle, LineWidth,
TransformSourceMap,
CstFormatContext, FormatContext, FormatElement, FormatOptions, IndentStyle, IndentWidth,
LineWidth, TransformSourceMap,
};
use rome_js_syntax::{AnyJsFunctionBody, JsFileSource, JsLanguage};
use rome_json_syntax::JsonLanguage;
Expand Down Expand Up @@ -138,6 +138,9 @@ pub struct JsFormatOptions {
/// The indent style.
indent_style: IndentStyle,

/// The indent width.
indent_width: IndentWidth,

/// What's the max width of a line. Defaults to 80.
line_width: LineWidth,

Expand Down Expand Up @@ -168,6 +171,7 @@ impl JsFormatOptions {
Self {
source_type,
indent_style: IndentStyle::default(),
indent_width: IndentWidth::default(),
line_width: LineWidth::default(),
quote_style: QuoteStyle::default(),
jsx_quote_style: QuoteStyle::default(),
Expand All @@ -188,6 +192,11 @@ impl JsFormatOptions {
self
}

pub fn with_indent_width(mut self, indent_width: IndentWidth) -> Self {
self.indent_width = indent_width;
self
}

pub fn with_line_width(mut self, line_width: LineWidth) -> Self {
self.line_width = line_width;
self
Expand Down Expand Up @@ -247,10 +256,7 @@ impl JsFormatOptions {
}

pub fn tab_width(&self) -> TabWidth {
match self.indent_style {
IndentStyle::Tab => 2.into(),
IndentStyle::Space(quantities) => quantities.into(),
}
self.indent_width.value().into()
}
}

Expand All @@ -259,6 +265,10 @@ impl FormatOptions for JsFormatOptions {
self.indent_style
}

fn indent_width(&self) -> IndentWidth {
self.indent_width
}

fn line_width(&self) -> LineWidth {
self.line_width
}
Expand All @@ -271,6 +281,7 @@ impl FormatOptions for JsFormatOptions {
impl fmt::Display for JsFormatOptions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Indent style: {}", self.indent_style)?;
writeln!(f, "Indent width: {}", self.indent_width.value())?;
writeln!(f, "Line width: {}", self.line_width.value())?;
writeln!(f, "Quote style: {}", self.quote_style)?;
writeln!(f, "JSX quote style: {}", self.jsx_quote_style)?;
Expand Down
Loading

0 comments on commit d22ccef

Please sign in to comment.