1
- use crate :: { CowStr , MagicString } ;
1
+ use rustc_hash:: FxHashSet ;
2
+
3
+ use crate :: { CowStr , MagicString , TextSize } ;
2
4
3
5
fn guess_indent_str ( source : & str ) -> Option < String > {
4
6
let mut tabbed_count = 0 ;
@@ -36,6 +38,7 @@ fn guess_indent_str(source: &str) -> Option<String> {
36
38
pub struct IndentOptions < ' a > {
37
39
/// MagicString will guess the `indent_str`` from lines of the source if passed `None`.
38
40
pub indent_str : Option < & ' a str > ,
41
+ pub exclude : Vec < TextSize > ,
39
42
}
40
43
41
44
impl < ' text > MagicString < ' text > {
@@ -48,13 +51,17 @@ impl<'text> MagicString<'text> {
48
51
}
49
52
50
53
pub fn indent ( & mut self ) -> & mut Self {
51
- self . indent_with ( IndentOptions { indent_str : None } )
54
+ self . indent_with ( IndentOptions {
55
+ indent_str : None ,
56
+ ..Default :: default ( )
57
+ } )
52
58
}
53
59
54
60
/// Shortcut for `indent_with(IndentOptions { indent_str: Some(indent_str), ..Default::default() })`
55
61
pub fn indent_str ( & mut self , indent_str : & str ) -> & mut Self {
56
62
self . indent_with ( IndentOptions {
57
63
indent_str : Some ( indent_str) ,
64
+ ..Default :: default ( )
58
65
} )
59
66
}
60
67
@@ -116,33 +123,49 @@ impl<'text> MagicString<'text> {
116
123
for intro_frag in self . intro . iter_mut ( ) {
117
124
indent_frag ( intro_frag, & pattern, & mut indent_replacer)
118
125
}
119
-
126
+ let is_excluded = {
127
+ let mut is_excluded = FxHashSet :: default ( ) ;
128
+ let mut exclude = opts. exclude ;
129
+ exclude. sort ( ) ;
130
+ exclude. windows ( 2 ) . for_each ( |s| {
131
+ for i in s[ 0 ] ..s[ 1 ] {
132
+ is_excluded. insert ( i) ;
133
+ }
134
+ } ) ;
135
+ is_excluded
136
+ } ;
120
137
let mut next_chunk_id = Some ( self . first_chunk_idx ) ;
121
-
138
+ let mut char_index = 0u32 ;
122
139
while let Some ( chunk_idx) = next_chunk_id {
123
140
// Make sure the `next_chunk_id` is updated before we split the chunk. Otherwise, we
124
141
// might process the same chunk twice.
125
142
next_chunk_id = self . chunks [ chunk_idx] . next ;
126
143
if let Some ( edited_content) = self . chunks [ chunk_idx] . edited_content . as_mut ( ) {
127
- indent_frag ( edited_content, & pattern, & mut indent_replacer) ;
144
+ if !is_excluded. contains ( & char_index) {
145
+ indent_frag ( edited_content, & pattern, & mut indent_replacer) ;
146
+ }
128
147
} else {
129
148
let chunk = & self . chunks [ chunk_idx] ;
130
149
let mut line_starts = vec ! [ ] ;
131
- let mut char_index = chunk. start ( ) ;
150
+ char_index = chunk. start ( ) ;
151
+ let chunk_end = chunk. end ( ) ;
132
152
for char in chunk. span . text ( & self . source ) . chars ( ) {
133
153
debug_assert ! ( self . source. is_char_boundary( char_index as usize ) ) ;
134
- if char == '\n' {
135
- indent_replacer. should_indent_next_char = true ;
136
- } else if char != '\r' && indent_replacer. should_indent_next_char {
137
- indent_replacer. should_indent_next_char = false ;
138
- debug_assert ! ( !line_starts. contains( & char_index) ) ;
139
- line_starts. push ( char_index) ;
154
+ if !is_excluded. contains ( & char_index) {
155
+ if char == '\n' {
156
+ indent_replacer. should_indent_next_char = true ;
157
+ } else if char != '\r' && indent_replacer. should_indent_next_char {
158
+ indent_replacer. should_indent_next_char = false ;
159
+ debug_assert ! ( !line_starts. contains( & char_index) ) ;
160
+ line_starts. push ( char_index) ;
161
+ }
140
162
}
141
163
char_index += char. len_utf8 ( ) as u32 ;
142
164
}
143
165
for line_start in line_starts {
144
166
self . prepend_right ( line_start, indent_replacer. indent_str . clone ( ) ) ;
145
167
}
168
+ char_index = chunk_end;
146
169
}
147
170
}
148
171
0 commit comments