diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index 8d42f79fae..1e86e52594 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -3382,48 +3382,34 @@ fn extractStringSegments(self: *Self, parts: []const AST.Expr.Idx) std.mem.Alloc return try self.env.store.exprSpanFrom(start); } -/// Extract string segments from parsed string parts, combining consecutive string parts with newlines +/// Extract string segments from parsed multiline string parts, adding newlines between consecutive string parts fn extractMultilineStringSegments(self: *Self, parts: []const AST.Expr.Idx) std.mem.Allocator.Error!Expr.Span { const start = self.env.store.scratchExprTop(); - var combined_text: []const u8 = ""; - var combined_region: ?AST.TokenizedRegion = null; + var last_string_part_end: ?Token.Idx = null; for (parts) |part| { const part_node = self.parse_ir.store.getExpr(part); switch (part_node) { .string_part => |sp| { - // get the raw text of the string part - const part_text = self.parse_ir.resolve(sp.token); - if (combined_text.len == 0) { - combined_text = part_text; - combined_region = part_node.to_tokenized_region(); - } else { - // TODO: should this be \n or \\n or even different depending on file encoding - combined_text = try std.fmt.allocPrint(self.env.gpa, "{s}\\n{s}", .{ combined_text, part_text }); - combined_region = combined_region.?.spanAcross(part_node.to_tokenized_region()); + // Add newline between consecutive string parts + if (last_string_part_end != null) { + try self.addStringLiteralToScratch("\\n", .{ .start = last_string_part_end.?, .end = part_node.to_tokenized_region().start }); } + + // Get and process the raw text of the string part + const part_text = self.parse_ir.resolve(sp.token); + if (part_text.len != 0) { + try self.addStringLiteralToScratch(part_text, part_node.to_tokenized_region()); + } + last_string_part_end = part_node.to_tokenized_region().end; }, else => { - // First add any accumulated string parts - if (combined_region != null) { - try self.addStringLiteralToScratch(combined_text, combined_region.?); - - // reset combined state - combined_text = ""; - combined_region = null; - } - - // Then handle the interpolation + last_string_part_end = null; try self.addInterpolationToScratch(part, part_node); }, } } - // add any remaining combined string at the end - if (combined_text.len > 0) { - try self.addStringLiteralToScratch(combined_text, combined_region.?); - } - return try self.env.store.exprSpanFrom(start); } diff --git a/test/snapshots/multiline_string_complex.md b/test/snapshots/multiline_string_complex.md index 5f6ce18b2b..2887a90440 100644 --- a/test/snapshots/multiline_string_complex.md +++ b/test/snapshots/multiline_string_complex.md @@ -97,13 +97,19 @@ NO CHANGE (d-let (p-assign @8.1-8.7 (ident "value3")) (e-string @8.10-10.14 - (e-literal @8.13-10.5 (string "This is a string\nWith multiple lines\n")) + (e-literal @8.13-8.29 (string "This is a string")) + (e-literal @9.2-9.5 (string "\n")) + (e-literal @9.5-9.24 (string "With multiple lines")) + (e-literal @10.2-10.5 (string "\n")) (e-lookup-local @10.7-10.13 (p-assign @3.1-3.7 (ident "value1"))))) (d-let (p-assign @12.1-12.7 (ident "value4")) (e-string @13.2-16.14 - (e-literal @13.5-16.5 (string "This is a string\nWith multiple lines\n")) + (e-literal @13.5-13.21 (string "This is a string")) + (e-literal @15.2-15.5 (string "\n")) + (e-literal @15.5-15.24 (string "With multiple lines")) + (e-literal @16.2-16.5 (string "\n")) (e-lookup-local @16.7-16.13 (p-assign @5.1-5.7 (ident "value2")))))) ~~~ diff --git a/test/snapshots/multiline_string_expr.md b/test/snapshots/multiline_string_expr.md index d34c4dd31b..81f68c024c 100644 --- a/test/snapshots/multiline_string_expr.md +++ b/test/snapshots/multiline_string_expr.md @@ -30,7 +30,9 @@ NO CHANGE # CANONICALIZE ~~~clojure (e-string @1.1-2.23 - (e-literal @1.4-2.23 (string "This is a string\nWith multiple lines"))) + (e-literal @1.4-1.20 (string "This is a string")) + (e-literal @2.1-2.4 (string "\n")) + (e-literal @2.4-2.23 (string "With multiple lines"))) ~~~ # TYPES ~~~clojure