Skip to content

Commit 11ef5f0

Browse files
committed
Improve handling for multiline strings
This change always breaks before a multiline string and ensures the surrounding code is appropriately broken too.
1 parent 91d3b22 commit 11ef5f0

File tree

6 files changed

+114
-9
lines changed

6 files changed

+114
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1616
### Changed
1717

1818
- Unterminated string literals will never mangle other tokens.
19+
- Improved support for multiline strings.
1920

2021
## [0.5.1] - 2025-06-02
2122

core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
- Conditional directive parsing now uses a greedy algorithm that avoids the exponential
2828
performance issues with the old algorithm.
2929
- Unterminated string literals will never mangle other tokens by always breaking after.
30+
- Improved support for multiline strings. They will now always break before, and
31+
break surrounding contexts.
3032

3133
## 0.5.1 - 2025-06-02
3234

core/datatests/generators/optimising_line_formatter.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4672,6 +4672,78 @@ mod expressions {
46724672
'
46734673
;
46744674
",
4675+
multiline = "
4676+
A :=
4677+
'''
4678+
''';
4679+
A :=
4680+
'''
4681+
'''
4682+
+ BB
4683+
+ CC;
4684+
A :=
4685+
'''
4686+
'''[11111 + 11111 + 1111];
4687+
A :=
4688+
'''
4689+
'''[
4690+
11111 + 11111 + 11111
4691+
];
4692+
A :=
4693+
'''
4694+
'''.B(1111 + 1111 + 1111);
4695+
A :=
4696+
'''
4697+
'''.B(
4698+
11111 + 11111 + 11111
4699+
);
4700+
A :=
4701+
B(
4702+
'''
4703+
'''
4704+
);
4705+
A :=
4706+
B(
4707+
C,
4708+
'''
4709+
''',
4710+
D
4711+
);
4712+
A :=
4713+
B(
4714+
C,
4715+
'''
4716+
'''
4717+
+
4718+
'''
4719+
''',
4720+
D
4721+
);
4722+
",
4723+
multiline_diff = {
4724+
"
4725+
A :=
4726+
'''
4727+
''';
4728+
A := '''
4729+
'''.B(11 + 11 + 11);
4730+
A :=
4731+
'''
4732+
'''.B(11 + 11 + 11);
4733+
",
4734+
"
4735+
A :=
4736+
'''
4737+
''';
4738+
A :=
4739+
'''
4740+
'''.B(11 + 11 + 11);
4741+
A :=
4742+
'''
4743+
'''
4744+
.B(11 + 11 + 11);
4745+
"
4746+
}
46754747
);
46764748
}
46774749
}

core/src/defaults/reconstructor.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::cmp::Ordering;
22

3+
use itertools::Itertools;
4+
35
use crate::{
46
formatter::Cursor,
57
lang::*,
@@ -17,6 +19,7 @@ impl DelphiLogicalLinesReconstructor {
1719
}
1820
}
1921

22+
#[derive(Debug)]
2023
struct InternalCursor<'cursor> {
2124
cursor: &'cursor mut Cursor,
2225
tok_idx: usize,
@@ -28,6 +31,7 @@ struct CursorTrackerImpl<'cursor> {
2831
cursors: Vec<InternalCursor<'cursor>>,
2932
}
3033

34+
#[derive(Debug)]
3135
enum TokPos {
3236
/// Position of a cursor inside a token
3337
InContent {
@@ -265,6 +269,7 @@ impl CursorTracker for CursorTrackerImpl<'_> {
265269
}
266270

267271
fn relocate_cursors(&mut self, formatted_tokens: &FormattedTokens) {
272+
dbg!(&self.cursors);
268273
for cursor in &mut self.cursors {
269274
let token = match formatted_tokens.get_token(cursor.tok_idx) {
270275
Some(t) => t,
@@ -698,8 +703,11 @@ A = 1 + {
698703
699704
} | | | | | | | | A;
700705
701-
A = 1 + '''
702-
''' + | | | | Spaces;",
706+
A := 1 + '''
707+
''' + | | | | |Spaces;
708+
709+
A := 1 + '''
710+
''' + | | | | | Spaces;",
703711
"\
704712
A
705713
= 1
@@ -709,8 +717,19 @@ A
709717
}
710718
| | | | | | ||A;
711719
712-
A = 1 + '''
713-
''' + | | | | Spaces;",
720+
A :=
721+
1
722+
+
723+
'''
724+
'''
725+
+||| | |Spaces;
726+
727+
A :=
728+
1
729+
+
730+
'''
731+
'''
732+
+ | | | | |Spaces;",
714733
);
715734
}
716735
}

core/src/rules/optimising_line_formatter/contexts.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,14 @@ impl<'a> SpecificContextStack<'a> {
445445

446446
let curr_token_type = self.get_token_type_from_line_index(line_index);
447447
match (last_real_token_type, curr_token_type) {
448+
(_, Some(TT::TextLiteral(TextLiteralKind::MultiLine))) => {
449+
// There is necessarily a break within a multiline string
450+
// literal so contexts must be updated accordingly
451+
self.update_last_matching_context(node, context_matches!(_), |_, data| {
452+
data.is_broken = true;
453+
});
454+
self.update_operator_precedences(node, true);
455+
}
448456
(_, Some(TT::Comment(CommentKind::InlineBlock | CommentKind::InlineLine))) => {
449457
/*
450458
When formatting comments, there are some considerations to be made:

core/src/rules/optimising_line_formatter/requirements.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,14 @@ impl InternalOptimisingLineFormatter<'_, '_> {
339339
}
340340
(
341341
_,
342-
Some(TT::Comment(
343-
CommentKind::IndividualLine
344-
| CommentKind::IndividualBlock
345-
| CommentKind::MultilineBlock,
346-
)),
342+
Some(
343+
TT::Comment(
344+
CommentKind::IndividualLine
345+
| CommentKind::IndividualBlock
346+
| CommentKind::MultilineBlock,
347+
)
348+
| TT::TextLiteral(TextLiteralKind::MultiLine),
349+
),
347350
) => Some(DR::MustBreak),
348351
(
349352
Some(

0 commit comments

Comments
 (0)