Skip to content

Commit

Permalink
fix(formatter): fix formatting literal strings
Browse files Browse the repository at this point in the history
Signed-off-by: azjezz <azjezz@protonmail.com>
  • Loading branch information
azjezz committed Dec 18, 2024
1 parent 7f80d83 commit 57b7cd4
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 3 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ wasm-bindgen = "0.2.97"
serde-wasm-bindgen = "0.4"
diffy = "0.4.0"
termcolor = "1.4.1"
indoc = "2"

[dependencies]
mago-cli = { workspace = true }
Expand Down
5 changes: 5 additions & 0 deletions crates/formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ strum = { workspace = true }
serde = { workspace = true }
tracing = { workspace = true }
bitflags = { workspace = true }

[dev-dependencies]
mago-parser = { workspace = true }
indoc = { workspace = true }
pretty_assertions = { workspace = true }
2 changes: 1 addition & 1 deletion crates/formatter/src/format/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl<'a> Format<'a> for Literal {

impl<'a> Format<'a> for LiteralString {
fn format(&'a self, f: &mut Formatter<'a>) -> Document<'a> {
wrap!(f, self, LiteralString, { Document::String(print_string(f, &self.value)) })
wrap!(f, self, LiteralString, { Document::String(print_string(f, &self.kind, &self.value)) })
}
}

Expand Down
9 changes: 7 additions & 2 deletions crates/formatter/src/format/string.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use mago_ast::LiteralStringKind;
use mago_interner::StringIdentifier;

use crate::Formatter;
Expand Down Expand Up @@ -58,12 +59,16 @@ fn make_string(raw_text: &str, enclosing_quote: char) -> String {
result
}

pub(super) fn print_string<'a>(f: &Formatter<'a>, value: &StringIdentifier) -> &'a str {
pub(super) fn print_string<'a>(f: &Formatter<'a>, kind: &LiteralStringKind, value: &StringIdentifier) -> &'a str {
let text = f.lookup(value);

let quote = unsafe { text.chars().next().unwrap_unchecked() };
let raw_text = &text[1..text.len() - 1];
let enclosing_quote = get_preferred_quote(raw_text, quote, f.settings.single_quote);

f.as_str(make_string(raw_text, enclosing_quote))
match kind {
LiteralStringKind::SingleQuoted if enclosing_quote == '\'' => text,
LiteralStringKind::DoubleQuoted if enclosing_quote == '"' => text,
_ => f.as_str(make_string(raw_text, enclosing_quote)),
}
}
1 change: 1 addition & 0 deletions crates/formatter/tests/format/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod string;
68 changes: 68 additions & 0 deletions crates/formatter/tests/format/string.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use indoc::indoc;

use mago_formatter::settings::FormatSettings;
use mago_source::error::SourceError;

use crate::test_format;

#[test]
pub fn test_single_quote() -> Result<(), SourceError> {
let code = indoc! {r#"
<?php
$a = "Hello, world!";
$b = 'Hello, world!';
$c = "Hello, 'world'!";
$d = 'Hello, "world"!';
$e = "Hello, \"world\"!";
$f = 'Hello, \'world\'!';
$g = "Hello, 'world'!";
$h = 'Hello, \"world\"!';
"#};

let expected = indoc! {r#"
<?php
$a = 'Hello, world!';
$b = 'Hello, world!';
$c = "Hello, 'world'!";
$d = 'Hello, "world"!';
$e = "Hello, \"world\"!";
$f = 'Hello, \'world\'!';
$g = "Hello, 'world'!";
$h = 'Hello, \"world\"!';
"#};

test_format(code, expected, FormatSettings { single_quote: true, ..Default::default() })
}

#[test]
pub fn test_double_quote() -> Result<(), SourceError> {
let code = indoc! {r#"
<?php
$a = "Hello, world!";
$b = 'Hello, world!';
$c = "Hello, 'world'!";
$d = 'Hello, "world"!';
$e = "Hello, \"world\"!";
$f = 'Hello, \'world\'!';
$g = "Hello, 'world'!";
$h = 'Hello, \"world\"!';
"#};

let expected = indoc! {r#"
<?php
$a = "Hello, world!";
$b = "Hello, world!";
$c = "Hello, 'world'!";
$d = 'Hello, "world"!';
$e = "Hello, \"world\"!";
$f = 'Hello, \'world\'!';
$g = "Hello, 'world'!";
$h = 'Hello, \"world\"!';
"#};

test_format(code, expected, FormatSettings { single_quote: false, ..Default::default() })
}
20 changes: 20 additions & 0 deletions crates/formatter/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use mago_formatter::settings::FormatSettings;
use mago_interner::ThreadedInterner;
use mago_parser::parse_source;
use mago_source::error::SourceError;
use mago_source::SourceManager;

mod format;

pub fn test_format(code: impl AsRef<str>, expected: &str, settings: FormatSettings) -> Result<(), SourceError> {
let interner = ThreadedInterner::new();
let mut manager = SourceManager::new(interner.clone());
let source_id = manager.insert_content("code.php".to_string(), code.as_ref().to_string(), true);
let source = manager.load(&source_id)?;
let (program, _) = parse_source(&interner, &source);
let formatted = mago_formatter::format(settings, &interner, &source, &program);

pretty_assertions::assert_eq!(expected, formatted, "Formatted code does not match expected");

Ok(())
}

0 comments on commit 57b7cd4

Please sign in to comment.