5
5
//
6
6
//
7
7
8
+ use std:: borrow:: Cow ;
8
9
use std:: cmp:: Ordering ;
9
10
use std:: sync:: LazyLock ;
10
11
@@ -19,14 +20,7 @@ use crate::lsp::documents::Document;
19
20
pub fn folding_range ( document : & Document ) -> anyhow:: Result < Vec < FoldingRange > > {
20
21
let mut folding_ranges: Vec < FoldingRange > = Vec :: new ( ) ;
21
22
22
- // Activate the parser
23
- let mut parser = tree_sitter:: Parser :: new ( ) ;
24
- parser
25
- . set_language ( & tree_sitter_r:: LANGUAGE . into ( ) )
26
- . unwrap ( ) ;
27
-
28
- let ast = parser. parse ( & document. contents . to_string ( ) , None ) . unwrap ( ) ;
29
-
23
+ let ast = & document. ast ;
30
24
if ast. root_node ( ) . has_error ( ) {
31
25
tracing:: error!( "Folding range service: Parse error" ) ;
32
26
return Err ( anyhow:: anyhow!( "Parse error" ) ) ;
@@ -88,15 +82,18 @@ fn parse_ts_node(
88
82
}
89
83
90
84
// Nested comment section handling
91
- let comment_line = get_line_text ( document, start. row , None , None ) ;
92
-
93
- if let Err ( err) =
94
- nested_processor ( comment_stack, folding_ranges, start. row , & comment_line)
95
- {
96
- lsp:: log_error!( "Can't process comment: {err:?}" ) ;
85
+ if let Some ( comment_line) = document. contents . get_line ( start. row ) {
86
+ // O(n) if comment overlaps rope chunks, O(1) otherwise
87
+ let comment_line: Cow < ' _ , str > = comment_line. into ( ) ;
88
+
89
+ if let Err ( err) =
90
+ nested_processor ( comment_stack, folding_ranges, start. row , & comment_line)
91
+ {
92
+ lsp:: log_error!( "Can't process comment: {err:?}" ) ;
93
+ } ;
94
+ region_processor ( folding_ranges, region_marker, start. row , & comment_line) ;
95
+ cell_processor ( folding_ranges, cell_marker, start. row , & comment_line) ;
97
96
} ;
98
- region_processor ( folding_ranges, region_marker, start. row , & comment_line) ;
99
- cell_processor ( folding_ranges, cell_marker, start. row , & comment_line) ;
100
97
} ,
101
98
_ => ( ) ,
102
99
}
@@ -145,28 +142,20 @@ fn bracket_range(
145
142
white_space_count : usize ,
146
143
) -> FoldingRange {
147
144
let mut end_line: u32 = end_line as u32 ;
148
- let mut end_char : Option < u32 > = Some ( end_char as u32 ) ;
145
+ let mut end_character = Some ( end_char as u32 ) ;
149
146
150
- let adjusted_end_char = end_char. and_then ( |val| val. checked_sub ( white_space_count as u32 ) ) ;
151
-
152
- match adjusted_end_char {
153
- Some ( 0 ) => {
147
+ if let Some ( val) = end_char. checked_sub ( white_space_count) {
148
+ if val == 0 {
154
149
end_line -= 1 ;
155
- end_char = None ;
156
- } ,
157
- Some ( _) => { } ,
158
- None => {
159
- tracing:: error!(
160
- "Folding Range (bracket_range): adjusted_end_char should not be None here"
161
- ) ;
162
- } ,
150
+ end_character = None ;
151
+ }
163
152
}
164
153
165
154
FoldingRange {
166
155
start_line : start_line as u32 ,
167
156
start_character : Some ( start_char as u32 ) ,
168
157
end_line,
169
- end_character : end_char ,
158
+ end_character,
170
159
kind : Some ( FoldingRangeKind :: Region ) ,
171
160
collapsed_text : None ,
172
161
}
@@ -183,39 +172,14 @@ fn comment_range(start_line: usize, end_line: usize) -> FoldingRange {
183
172
}
184
173
}
185
174
186
- fn get_line_text (
187
- document : & Document ,
188
- line_num : usize ,
189
- start_char : Option < usize > ,
190
- end_char : Option < usize > ,
191
- ) -> String {
192
- let text = & document. contents ;
193
- // Split the text into lines
194
- let lines: Vec < & str > = text. lines ( ) . filter_map ( |line| line. as_str ( ) ) . collect ( ) ;
195
-
196
- // Ensure the start_line is within bounds
197
- if line_num >= lines. len ( ) {
198
- return String :: new ( ) ; // Return an empty string if out of bounds
199
- }
200
-
201
- // Get the line corresponding to start_line
202
- let line = lines[ line_num] ;
203
-
204
- // Determine the start and end character indices
205
- let start_idx = start_char. unwrap_or ( 0 ) ; // Default to 0 if None
206
- let end_idx = end_char. unwrap_or ( line. len ( ) ) ; // Default to the line's length if None
207
-
208
- // Ensure indices are within bounds for the line
209
- let start_idx = start_idx. min ( line. len ( ) ) ;
210
- let end_idx = end_idx. min ( line. len ( ) ) ;
211
-
212
- // Extract the substring and return it
213
- line[ start_idx..end_idx] . to_string ( )
214
- }
215
-
216
175
fn count_leading_whitespaces ( document : & Document , line_num : usize ) -> usize {
217
- let line_text = get_line_text ( document, line_num, None , None ) ;
218
- line_text. chars ( ) . take_while ( |c| c. is_whitespace ( ) ) . count ( )
176
+ let Some ( line) = document. contents . get_line ( line_num) else {
177
+ return 0 ;
178
+ } ;
179
+
180
+ line. bytes ( )
181
+ . take_while ( |& b| b == b' ' || b == b'\t' )
182
+ . count ( )
219
183
}
220
184
221
185
pub static RE_COMMENT_SECTION : LazyLock < Regex > =
0 commit comments