1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use smallvec::SmallVec;
use std::mem;
use syntax::ast::*;
use syntax::mut_visit::{self, MutVisitor};
use syntax::ptr::P;
use syntax::source_map::{Span, DUMMY_SP};
use syntax_pos::hygiene::SyntaxContext;
use crate::ast_manip::util::extended_span;
use crate::ast_manip::MutVisit;
struct FixFormat {
parent_span: Span,
in_format: bool,
}
impl FixFormat {
fn descend<F, R>(&mut self, in_format: bool, cur_span: Span, f: F) -> R
where
F: FnOnce(&mut Self) -> R,
{
let old_in_format = mem::replace(&mut self.in_format, in_format);
let old_parent_span = mem::replace(&mut self.parent_span, cur_span);
let r = f(self);
self.in_format = old_in_format;
self.parent_span = old_parent_span;
r
}
fn is_format_entry(&self, e: &Expr) -> bool {
if !matches!([e.node] ExprKind::Match(..)) {
return false;
}
if e.span.ctxt() == SyntaxContext::empty() {
return false;
}
e.span.source_callsite().contains(e.span)
}
}
impl MutVisitor for FixFormat {
fn visit_expr(&mut self, e: &mut P<Expr>) {
if self.in_format
&& e.span.ctxt() == SyntaxContext::empty()
&& matches!([e.node] ExprKind::AddrOf(..))
{
trace!("EXITING format! at {:?}", e);
let new_span = self.parent_span;
self.descend(false, e.span, |this| {
mut_visit::noop_visit_expr(e, this);
e.span = new_span;
})
} else if !self.in_format && self.is_format_entry(&e) {
trace!("ENTERING format! at {:?}", e);
self.descend(true, e.span, |this| mut_visit::noop_visit_expr(e, this))
} else {
let in_format = self.in_format;
self.descend(in_format, e.span, |this| {
mut_visit::noop_visit_expr(e, this)
})
}
}
fn visit_mac(&mut self, mac: &mut Mac) {
mut_visit::noop_visit_mac(mac, self)
}
}
struct FixAttrs;
impl MutVisitor for FixAttrs {
fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
let new_span = extended_span(i.span, &i.attrs);
let i = if new_span != i.span {
i.map(|i| Item {
span: new_span,
..i
})
} else {
i
};
mut_visit::noop_flat_map_item(i, self)
}
fn flat_map_foreign_item(&mut self, fi: ForeignItem) -> SmallVec<[ForeignItem; 1]> {
let new_span = extended_span(fi.span, &fi.attrs);
let fi = if new_span != fi.span {
ForeignItem {
span: new_span,
..fi
}
} else {
fi
};
mut_visit::noop_flat_map_foreign_item(fi, self)
}
fn visit_mac(&mut self, mac: &mut Mac) {
mut_visit::noop_visit_mac(mac, self)
}
}
pub fn fix_format<T: MutVisit>(node: &mut T) {
let mut fix_format = FixFormat {
parent_span: DUMMY_SP,
in_format: false,
};
node.visit(&mut fix_format)
}
pub fn fix_attr_spans<T: MutVisit>(node: &mut T) {
node.visit(&mut FixAttrs)
}