@@ -12,7 +12,7 @@ use ast_grep_core::{language::Language, AstGrep, Doc, StrDoc};
12
12
use std:: collections:: HashMap ;
13
13
use std:: path:: { Path , PathBuf } ;
14
14
15
- use utils:: { convert_match_to_diagnostic, convert_node_to_range , diagnostic_to_code_action } ;
15
+ use utils:: { convert_match_to_diagnostic, diagnostic_to_code_action , RewriteData } ;
16
16
17
17
pub use tower_lsp:: { LspService , Server } ;
18
18
@@ -165,19 +165,6 @@ impl<L: LSPLang> LanguageServer for Backend<L> {
165
165
}
166
166
}
167
167
168
- fn build_error_id_to_ranges ( diagnostics : Vec < Diagnostic > ) -> HashMap < String , Vec < Range > > {
169
- let mut error_id_to_ranges = HashMap :: new ( ) ;
170
- for diagnostic in diagnostics {
171
- let rule_id = match diagnostic. code {
172
- Some ( NumberOrString :: String ( rule) ) => rule,
173
- _ => continue ,
174
- } ;
175
- let ranges = error_id_to_ranges. entry ( rule_id) . or_insert_with ( Vec :: new) ;
176
- ranges. push ( diagnostic. range ) ;
177
- }
178
- error_id_to_ranges
179
- }
180
-
181
168
impl < L : LSPLang > Backend < L > {
182
169
pub fn new (
183
170
client : Client ,
@@ -287,45 +274,32 @@ impl<L: LSPLang> Backend<L> {
287
274
fn compute_all_fixes (
288
275
& self ,
289
276
text_document : TextDocumentIdentifier ,
290
- error_id_to_ranges : HashMap < String , Vec < Range > > ,
291
- path : PathBuf ,
277
+ mut diagnostics : Vec < Diagnostic > ,
292
278
) -> Option < HashMap < Url , Vec < TextEdit > > >
293
279
where
294
280
L : ast_grep_core:: Language + std:: cmp:: Eq ,
295
281
{
296
- let uri = text_document. uri . as_str ( ) ;
297
- let versioned = self . map . get ( uri) ?;
298
- let mut edits = vec ! [ ] ;
299
- let rules = self . rules . as_ref ( ) . ok ( ) ?;
300
- for config in rules. for_path ( & path) {
301
- let ranges = match error_id_to_ranges. get ( & config. id ) {
302
- Some ( ranges) => ranges,
303
- None => continue ,
304
- } ;
305
- let matcher = & config. matcher ;
306
-
307
- for matched_node in versioned. root . root ( ) . find_all ( & matcher) {
308
- let range = convert_node_to_range ( & matched_node) ;
309
- if !ranges. contains ( & range) {
310
- continue ;
282
+ diagnostics. sort_by_key ( |d| ( d. range . start , d. range . end ) ) ;
283
+ let mut last = Position {
284
+ line : 0 ,
285
+ character : 0 ,
286
+ } ;
287
+ let edits: Vec < _ > = diagnostics
288
+ . into_iter ( )
289
+ . filter_map ( |d| {
290
+ if d. range . start < last {
291
+ return None ;
311
292
}
312
- let fixer = match & config. matcher . fixer {
313
- Some ( fixer) => fixer,
314
- None => continue ,
315
- } ;
316
- let edit = matched_node. replace_by ( fixer) ;
317
- let edit = TextEdit {
318
- range,
319
- new_text : String :: from_utf8 ( edit. inserted_text ) . unwrap ( ) ,
320
- } ;
321
-
322
- edits. push ( edit) ;
323
- }
324
- }
293
+ let rewrite_data = RewriteData :: from_value ( d. data ?) ?;
294
+ let edit = TextEdit :: new ( d. range , rewrite_data. fixed ) ;
295
+ last = d. range . end ;
296
+ Some ( edit)
297
+ } )
298
+ . collect ( ) ;
325
299
if edits. is_empty ( ) {
326
300
return None ;
327
301
}
328
- let mut changes: HashMap < Url , Vec < TextEdit > > = HashMap :: new ( ) ;
302
+ let mut changes = HashMap :: new ( ) ;
329
303
changes. insert ( text_document. uri , edits) ;
330
304
Some ( changes)
331
305
}
@@ -380,7 +354,6 @@ impl<L: LSPLang> Backend<L> {
380
354
let text_doc: TextDocumentItem =
381
355
serde_json:: from_value ( first) . map_err ( LspError :: JSONDecodeError ) ?;
382
356
let uri = text_doc. uri ;
383
- let path = uri. to_file_path ( ) . map_err ( |_| LspError :: InvalidFileURI ) ?;
384
357
let Some ( lang) = Self :: infer_lang_from_uri ( & uri) else {
385
358
return Err ( LspError :: UnsupportedFileType ) ;
386
359
} ;
@@ -392,10 +365,7 @@ impl<L: LSPLang> Backend<L> {
392
365
let Some ( diagnostics) = self . get_diagnostics ( & uri, & versioned) else {
393
366
return Err ( LspError :: NoActionableFix ) ;
394
367
} ;
395
- let error_id_to_ranges = build_error_id_to_ranges ( diagnostics) ;
396
-
397
- let changes =
398
- self . compute_all_fixes ( TextDocumentIdentifier :: new ( uri) , error_id_to_ranges, path) ;
368
+ let changes = self . compute_all_fixes ( TextDocumentIdentifier :: new ( uri) , diagnostics) ;
399
369
let workspace_edit = WorkspaceEdit {
400
370
changes,
401
371
document_changes : None ,
@@ -435,12 +405,6 @@ impl<L: LSPLang> Backend<L> {
435
405
)
436
406
. await ;
437
407
}
438
- LspError :: InvalidFileURI => {
439
- self
440
- . client
441
- . log_message ( MessageType :: ERROR , "Invalid URI format" )
442
- . await ;
443
- }
444
408
LspError :: UnsupportedFileType => {
445
409
self
446
410
. client
@@ -459,7 +423,6 @@ impl<L: LSPLang> Backend<L> {
459
423
460
424
enum LspError {
461
425
JSONDecodeError ( serde_json:: Error ) ,
462
- InvalidFileURI ,
463
426
UnsupportedFileType ,
464
427
NoActionableFix ,
465
428
}
0 commit comments