From b8c65f3a49e19a672b21f7248726d843e46a5296 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Thu, 30 Mar 2023 16:47:23 +0100 Subject: [PATCH] Format line endings in multiline strings and comments (#666) * Add test case * Convert line endings * Update changelog --- CHANGELOG.md | 1 + src/context.rs | 2 +- src/formatters/general.rs | 20 +++++++++++++++++--- tests/tests.rs | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4153cf9..91269d9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bumped internal parser dependency which should fix parsing problems for comments with Chinese characters, and multiline string escapes - Fixed comments in punctuated lists for return statements or assignments being incorrectly formatted leading to syntax errors ([#662](https://github.com/JohnnyMorganz/StyLua/issues/662)) +- Fixed line endings not being correctly formatted in multiline string literals and comments ([#665](https://github.com/JohnnyMorganz/StyLua/issues/665)) ## [0.17.0] - 2023-03-11 diff --git a/src/context.rs b/src/context.rs index 757c2f86..a44371c6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -155,7 +155,7 @@ impl Context { } /// Returns the relevant line ending string from the [`LineEndings`] enum -fn line_ending_character(line_endings: LineEndings) -> String { +pub fn line_ending_character(line_endings: LineEndings) -> String { match line_endings { LineEndings::Unix => String::from("\n"), LineEndings::Windows => String::from("\r\n"), diff --git a/src/formatters/general.rs b/src/formatters/general.rs index f00650a4..885eb0f9 100644 --- a/src/formatters/general.rs +++ b/src/formatters/general.rs @@ -1,5 +1,7 @@ use crate::{ - context::{create_indent_trivia, create_newline_trivia, Context, FormatNode}, + context::{ + create_indent_trivia, create_newline_trivia, line_ending_character, Context, FormatNode, + }, formatters::{ trivia::{FormatTriviaType, UpdateLeadingTrivia, UpdateTrailingTrivia, UpdateTrivia}, trivia_util::{ @@ -121,8 +123,14 @@ pub fn format_token( } => { // If we have a brackets string, don't mess with it if let StringLiteralQuoteType::Brackets = quote_type { + // Convert the string to the correct line endings, by first normalising to LF + // then converting LF to output + let literal = literal + .replace("\r\n", "\n") + .replace('\n', &line_ending_character(ctx.config().line_endings)); + TokenType::StringLiteral { - literal: literal.to_owned(), + literal: literal.into(), multi_line: *multi_line, quote_type: StringLiteralQuoteType::Brackets, } @@ -209,9 +217,15 @@ pub fn format_token( trailing_trivia = Some(vec![create_newline_trivia(ctx)]); } + // Convert the comment to the correct line endings, by first normalising to LF + // then converting LF to output + let comment = comment + .replace("\r\n", "\n") + .replace('\n', &line_ending_character(ctx.config().line_endings)); + TokenType::MultiLineComment { blocks: *blocks, - comment: comment.to_owned(), + comment: comment.into(), } } TokenType::Whitespace { characters } => TokenType::Whitespace { diff --git a/tests/tests.rs b/tests/tests.rs index 19ad42ba..03eda6c3 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -127,3 +127,40 @@ fn test_sort_requires() { .unwrap()); }) } + +#[test] +fn test_crlf_in_multiline_comments() { + // We need to do this outside of insta since it normalises line endings to LF + let code = r###" +local a = "testing" +--[[ + This comment + is multiline + and we want to ensure the line endings + convert to CRLF +]] +local x = 1 +"###; + + let code_crlf = code.lines().collect::>().join("\r\n"); + let output = format(&code_crlf); + assert_eq!(output.find("\r\n"), None); +} + +#[test] +fn test_crlf_in_multiline_strings() { + // We need to do this outside of insta since it normalises line endings to LF + let code = r###" +local a = [[ + This string + is multiline + and we want to ensure the line endings + convert to CRLF +]] +local x = 1 +"###; + + let code_crlf = code.lines().collect::>().join("\r\n"); + let output = format(&code_crlf); + assert_eq!(output.find("\r\n"), None); +}