Skip to content

Commit 5225fb8

Browse files
committed
fix: bad escape hatch in corner cases
1 parent 4dc61ef commit 5225fb8

File tree

12 files changed

+788
-12
lines changed

12 files changed

+788
-12
lines changed

crates/typstyle-core/src/attr.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,18 +149,25 @@ impl AttrStore {
149149
SyntaxKind::LineComment | SyntaxKind::BlockComment => {
150150
commented = true;
151151
// @typstyle off affects the whole next block
152-
if child.text().contains("@typstyle off") {
153-
disable_next = true;
154-
}
152+
disable_next = child.text().contains("@typstyle off");
155153
}
156154
SyntaxKind::Space | SyntaxKind::Hash => {}
155+
SyntaxKind::Code | SyntaxKind::Math if disable_next => {
156+
// no format nodes with @typstyle off
157+
self.disable_first_nontrivial_child(child);
158+
disable_next = false;
159+
}
157160
_ if disable_next => {
158161
// no format nodes with @typstyle off
159-
self.attrs_mut_of(child).is_format_disabled = true;
162+
if !child.kind().is_trivia() {
163+
self.attrs_mut_of(child).is_format_disabled = true;
164+
}
160165
disable_next = false;
161166
}
162167
_ => {
163-
self.compute_no_format_impl(child);
168+
if !child.kind().is_trivia() {
169+
self.compute_no_format_impl(child);
170+
}
164171
}
165172
}
166173
}
@@ -169,20 +176,29 @@ impl AttrStore {
169176
}
170177
}
171178

179+
fn disable_first_nontrivial_child(&mut self, node: &SyntaxNode) {
180+
node.children()
181+
.find(|it| !matches!(it.kind(), SyntaxKind::Space | SyntaxKind::Hash))
182+
.inspect(|it| self.attrs_mut_of(it).is_format_disabled = true);
183+
}
184+
172185
fn compute_math_align_point(&mut self, root: &SyntaxNode) {
173186
self.compute_math_align_point_impl(root);
174187
}
175188

176189
fn compute_math_align_point_impl(&mut self, node: &SyntaxNode) -> bool {
177-
if node.kind() == SyntaxKind::MathAlignPoint {
190+
let node_kind = node.kind();
191+
if node_kind == SyntaxKind::MathAlignPoint {
178192
return true;
179193
}
194+
if node_kind.is_trivia() {
195+
return false;
196+
}
180197
let mut has_math_align_point = false;
181198
for child in node.children() {
182199
has_math_align_point |= self.compute_math_align_point_impl(child);
183200
}
184-
if has_math_align_point
185-
&& matches!(node.kind(), SyntaxKind::Math | SyntaxKind::MathDelimited)
201+
if has_math_align_point && matches!(node_kind, SyntaxKind::Math | SyntaxKind::MathDelimited)
186202
{
187203
self.attrs_mut_of(node).has_math_align_point = true;
188204
true

crates/typstyle-core/src/pretty/code_misc.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ impl<'a> PrettyPrinter<'a> {
1212
ctx: Context,
1313
array_item: ArrayItem<'a>,
1414
) -> ArenaDoc<'a> {
15+
if let Some(res) = self.check_disabled(array_item.to_untyped()) {
16+
return res;
17+
}
1518
match array_item {
1619
ArrayItem::Pos(p) => self.convert_expr(ctx, p),
1720
ArrayItem::Spread(s) => self.convert_spread(ctx, s),
@@ -23,6 +26,9 @@ impl<'a> PrettyPrinter<'a> {
2326
ctx: Context,
2427
dict_item: DictItem<'a>,
2528
) -> ArenaDoc<'a> {
29+
if let Some(res) = self.check_disabled(dict_item.to_untyped()) {
30+
return res;
31+
}
2632
match dict_item {
2733
DictItem::Named(n) => self.convert_named(ctx, n),
2834
DictItem::Keyed(k) => self.convert_keyed(ctx, k),
@@ -31,6 +37,9 @@ impl<'a> PrettyPrinter<'a> {
3137
}
3238

3339
pub(super) fn convert_param(&'a self, ctx: Context, param: Param<'a>) -> ArenaDoc<'a> {
40+
if let Some(res) = self.check_disabled(param.to_untyped()) {
41+
return res;
42+
}
3443
match param {
3544
Param::Pos(p) => self.convert_pattern(ctx, p),
3645
Param::Named(n) => self.convert_named(ctx, n),
@@ -55,6 +64,9 @@ impl<'a> PrettyPrinter<'a> {
5564
ctx: Context,
5665
destructuring_item: DestructuringItem<'a>,
5766
) -> ArenaDoc<'a> {
67+
if let Some(res) = self.check_disabled(destructuring_item.to_untyped()) {
68+
return res;
69+
}
5870
match destructuring_item {
5971
DestructuringItem::Spread(s) => self.convert_spread(ctx, s),
6072
DestructuringItem::Named(n) => self.convert_named(ctx, n),

tests/fixtures/unit/off/complex.typ

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
#let complex_structure = (
3+
// Arrays with multiple ugly sections
4+
arrays: (
5+
/* @typstyle off */ 4- 3,5 + 8,6*2/3,
6+
7, 8, /* @typstyle off */ .. (16 -9, ),11*1,12/1
7+
),
8+
9+
// Dictionary with inline off directives
10+
dict: (
11+
name: "Alice", /* @typstyle off */city:"Paris"+""+"", age:25,
12+
/* @typstyle off */ id:123*1,status:"active"+""
13+
),
14+
15+
// Destructuring patterns with off
16+
patterns: {
17+
let (first, /* @typstyle off */ .. rest,last) = (1, 2, 3 , )
18+
},
19+
20+
// Code blocks with mid-line off directives
21+
code: {
22+
let x = 1; /* @typstyle off */ let y=2;let z=3;
23+
24+
// Function definition with off mid-parameter list
25+
let my_func(
26+
param2, /* @typstyle off */ param3: 1*4 + 2,param4:none,
27+
) = {
28+
// Text styling with off between attributes
29+
text(
30+
size: 12pt, /* @typstyle off */ weight:"bold",fill:red,
31+
)[Styled text]
32+
}
33+
34+
// Show rule with off in unexpected places
35+
show heading: it => [
36+
#set text(blue); /* @typstyle off */ #set text(size:14pt,weight:"bold")
37+
#it.body; /* @typstyle off */ #h( 5pt )#text(red)[*x*]
38+
]
39+
40+
my_func
41+
},
42+
43+
// Complex content with lists and alignment
44+
content: [
45+
// List with multiple ugly sections
46+
- Normal item 1
47+
- Normal item 2
48+
/* @typstyle off */ - #{"Ugly" +"item" + "3"}
49+
/* @typstyle off */ #{"Another" + "ugly"+ "item" +"4"}
50+
- Normal item 5
51+
52+
// List with off after dashes
53+
- Normal item 1
54+
- Normal item 2; /* @typstyle off */ - #{[Ugly] ; [item] ; [3]}
55+
- Normal item 4; /* @typstyle off */ #{[Another] ;[ugly] ; [item]; [5]}
56+
- Normal item 6
57+
58+
// Complex nesting with off at various depths
59+
#align(
60+
center, /* @typstyle off */ box(width:100%,height:50pt, /* @typstyle off */ fill:blue,stroke:red)[
61+
Nested content with /* @typstyle off */ #stack(dir:ttb,spacing:5pt, [A], [B])
62+
]
63+
)
64+
],
65+
)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
source: tests/src/unit.rs
3+
input_file: tests/fixtures/unit/off/complex.typ
4+
---
5+
// DUMMY
6+
7+
#let complex_structure = (
8+
// Arrays with multiple ugly sections
9+
arrays: (
10+
/* @typstyle off */
11+
4- 3,
12+
5
13+
+ 8,
14+
6
15+
* 2
16+
/ 3,
17+
7,
18+
8,
19+
/* @typstyle off */
20+
.. (16 -9, ),
21+
11
22+
* 1,
23+
12
24+
/ 1,
25+
),
26+
// Dictionary with inline off directives
27+
dict: (
28+
name: "Alice",
29+
/* @typstyle off */
30+
city:"Paris"+""+"",
31+
age: 25,
32+
/* @typstyle off */
33+
id:123*1,
34+
status: "active"
35+
+ "",
36+
),
37+
// Destructuring patterns with off
38+
patterns: {
39+
let (
40+
first,
41+
/* @typstyle off */
42+
.. rest,
43+
last,
44+
) = (
45+
1,
46+
2,
47+
3,
48+
)
49+
},
50+
// Code blocks with mid-line off directives
51+
code: {
52+
let x = 1
53+
/* @typstyle off */
54+
let y=2
55+
let z = 3
56+
57+
// Function definition with off mid-parameter list
58+
let my_func(
59+
param2,
60+
/* @typstyle off */
61+
param3: 1*4 + 2,
62+
param4: none,
63+
) = {
64+
// Text styling with off between attributes
65+
text(
66+
size: 12pt,
67+
/* @typstyle off */
68+
weight: "bold",
69+
fill: red,
70+
)[Styled text]
71+
}
72+
73+
// Show rule with off in unexpected places
74+
show heading: it => [
75+
#set text(
76+
blue,
77+
); /* @typstyle off */ #set text(size:14pt,weight:"bold")
78+
#it.body; /* @typstyle off */ #h( 5pt )#text(
79+
red,
80+
)[*x*]
81+
]
82+
83+
my_func
84+
},
85+
// Complex content with lists and alignment
86+
content: [
87+
// List with multiple ugly sections
88+
- Normal item 1
89+
- Normal item 2
90+
/* @typstyle off */ - #{"Ugly" +"item" + "3"}
91+
/* @typstyle off */ #{"Another" + "ugly"+ "item" +"4"}
92+
- Normal item 5
93+
94+
// List with off after dashes
95+
- Normal item 1
96+
- Normal item 2; /* @typstyle off */ - #{
97+
[Ugly]
98+
[item]
99+
[3]
100+
}
101+
- Normal item 4; /* @typstyle off */ #{[Another] ;[ugly] ; [item]; [5]}
102+
- Normal item 6
103+
104+
// Complex nesting with off at various depths
105+
#align(
106+
center,
107+
/* @typstyle off */
108+
box(width:100%,height:50pt, /* @typstyle off */ fill:blue,stroke:red)[
109+
Nested content with /* @typstyle off */ #stack(dir:ttb,spacing:5pt, [A], [B])
110+
],
111+
)
112+
],
113+
)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
---
2+
source: tests/src/unit.rs
3+
input_file: tests/fixtures/unit/off/complex.typ
4+
---
5+
// DUMMY
6+
7+
#let complex_structure = (
8+
// Arrays with multiple ugly sections
9+
arrays: (
10+
/* @typstyle off */ 4- 3,
11+
5 + 8,
12+
6 * 2 / 3,
13+
7,
14+
8,
15+
/* @typstyle off */ .. (16 -9, ),
16+
11 * 1,
17+
12 / 1,
18+
),
19+
// Dictionary with inline off directives
20+
dict: (
21+
name: "Alice",
22+
/* @typstyle off */ city:"Paris"+""+"",
23+
age: 25,
24+
/* @typstyle off */ id:123*1,
25+
status: "active" + "",
26+
),
27+
// Destructuring patterns with off
28+
patterns: {
29+
let (first, /* @typstyle off */ .. rest, last) = (1, 2, 3)
30+
},
31+
// Code blocks with mid-line off directives
32+
code: {
33+
let x = 1
34+
/* @typstyle off */
35+
let y=2
36+
let z = 3
37+
38+
// Function definition with off mid-parameter list
39+
let my_func(
40+
param2,
41+
/* @typstyle off */ param3: 1*4 + 2,
42+
param4: none,
43+
) = {
44+
// Text styling with off between attributes
45+
text(size: 12pt, /* @typstyle off */ weight: "bold", fill: red)[Styled text]
46+
}
47+
48+
// Show rule with off in unexpected places
49+
show heading: it => [
50+
#set text(blue); /* @typstyle off */ #set text(size:14pt,weight:"bold")
51+
#it.body; /* @typstyle off */ #h( 5pt )#text(red)[*x*]
52+
]
53+
54+
my_func
55+
},
56+
// Complex content with lists and alignment
57+
content: [
58+
// List with multiple ugly sections
59+
- Normal item 1
60+
- Normal item 2
61+
/* @typstyle off */ - #{"Ugly" +"item" + "3"}
62+
/* @typstyle off */ #{"Another" + "ugly"+ "item" +"4"}
63+
- Normal item 5
64+
65+
// List with off after dashes
66+
- Normal item 1
67+
- Normal item 2; /* @typstyle off */ - #{
68+
[Ugly]
69+
[item]
70+
[3]
71+
}
72+
- Normal item 4; /* @typstyle off */ #{[Another] ;[ugly] ; [item]; [5]}
73+
- Normal item 6
74+
75+
// Complex nesting with off at various depths
76+
#align(
77+
center,
78+
/* @typstyle off */
79+
box(width:100%,height:50pt, /* @typstyle off */ fill:blue,stroke:red)[
80+
Nested content with /* @typstyle off */ #stack(dir:ttb,spacing:5pt, [A], [B])
81+
],
82+
)
83+
],
84+
)

0 commit comments

Comments
 (0)