@@ -289,6 +289,19 @@ fn url_to_code_description(url: &Option<String>) -> Option<CodeDescription> {
289
289
Some ( CodeDescription { href } )
290
290
}
291
291
292
+ fn build_error_id_to_ranges ( diagnostics : Vec < Diagnostic > ) -> HashMap < String , Vec < Range > > {
293
+ let mut error_id_to_ranges = HashMap :: new ( ) ;
294
+ for diagnostic in diagnostics {
295
+ let rule_id = match diagnostic. code {
296
+ Some ( NumberOrString :: String ( rule) ) => rule,
297
+ _ => continue ,
298
+ } ;
299
+ let ranges = error_id_to_ranges. entry ( rule_id) . or_insert_with ( Vec :: new) ;
300
+ ranges. push ( diagnostic. range ) ;
301
+ }
302
+ error_id_to_ranges
303
+ }
304
+
292
305
impl < L : LSPLang > Backend < L > {
293
306
pub fn new ( client : Client , rules : std:: result:: Result < RuleCollection < L > , String > ) -> Self {
294
307
Self {
@@ -432,7 +445,7 @@ impl<L: LSPLang> Backend<L> {
432
445
let text_doc = params. text_document ;
433
446
let path = text_doc. uri . to_file_path ( ) . ok ( ) ?;
434
447
let diagnostics = params. context . diagnostics ;
435
- let error_id_to_ranges = Self :: build_error_id_to_ranges ( diagnostics) ;
448
+ let error_id_to_ranges = build_error_id_to_ranges ( diagnostics) ;
436
449
let mut response = CodeActionResponse :: new ( ) ;
437
450
438
451
let code_action = params. context . only . as_ref ( ) ?. first ( ) ?. clone ( ) ;
@@ -477,19 +490,6 @@ impl<L: LSPLang> Backend<L> {
477
490
Some ( response)
478
491
}
479
492
480
- fn build_error_id_to_ranges ( diagnostics : Vec < Diagnostic > ) -> HashMap < String , Vec < Range > > {
481
- let mut error_id_to_ranges = HashMap :: new ( ) ;
482
- for diagnostic in diagnostics {
483
- let rule_id = match diagnostic. code {
484
- Some ( NumberOrString :: String ( rule) ) => rule,
485
- _ => continue ,
486
- } ;
487
- let ranges = error_id_to_ranges. entry ( rule_id) . or_insert_with ( Vec :: new) ;
488
- ranges. push ( diagnostic. range ) ;
489
- }
490
- error_id_to_ranges
491
- }
492
-
493
493
// TODO: support other urls besides file_scheme
494
494
fn infer_lang_from_uri ( uri : & Url ) -> Option < L > {
495
495
let path = uri. to_file_path ( ) . ok ( ) ?;
@@ -525,7 +525,7 @@ impl<L: LSPLang> Backend<L> {
525
525
let versioned = VersionedAst { version, root } ;
526
526
527
527
let diagnostics = self . get_diagnostics ( & uri, & versioned) . await ?;
528
- let error_id_to_ranges = Self :: build_error_id_to_ranges ( diagnostics) ;
528
+ let error_id_to_ranges = build_error_id_to_ranges ( diagnostics) ;
529
529
self
530
530
. client
531
531
. log_message ( MessageType :: LOG , "Parsing doc." )
@@ -548,139 +548,3 @@ impl<L: LSPLang> Backend<L> {
548
548
}
549
549
}
550
550
}
551
-
552
- #[ cfg( test) ]
553
- mod test {
554
- use super :: * ;
555
- use ast_grep_config:: { from_yaml_string, GlobalRules } ;
556
- use ast_grep_language:: SupportLang ;
557
- use serde_json:: Value ;
558
- use tokio:: io:: { duplex, AsyncReadExt , AsyncWriteExt , DuplexStream } ;
559
-
560
- fn start_lsp ( ) -> ( DuplexStream , DuplexStream ) {
561
- let globals = GlobalRules :: default ( ) ;
562
- let config: RuleConfig < SupportLang > = from_yaml_string (
563
- r"
564
- id: no-console-rule
565
- message: No console.log
566
- severity: warning
567
- language: TypeScript
568
- rule:
569
- pattern: console.log($$$A)
570
- note: no console.log
571
- fix: |
572
- alert($$$A)
573
- " ,
574
- & globals,
575
- )
576
- . unwrap ( )
577
- . pop ( )
578
- . unwrap ( ) ;
579
- let rc: RuleCollection < SupportLang > = RuleCollection :: try_new ( vec ! [ config] ) . unwrap ( ) ;
580
- let rc_result: std:: result:: Result < _ , String > = Ok ( rc) ;
581
- let ( service, socket) = LspService :: build ( |client| Backend :: new ( client, rc_result) ) . finish ( ) ;
582
- let ( req_client, req_server) = duplex ( 1024 ) ;
583
- let ( resp_server, resp_client) = duplex ( 1024 ) ;
584
-
585
- // start server as concurrent task
586
- tokio:: spawn ( Server :: new ( req_server, resp_server, socket) . serve ( service) ) ;
587
-
588
- ( req_client, resp_client)
589
- }
590
-
591
- fn req ( msg : & str ) -> String {
592
- format ! ( "Content-Length: {}\r \n \r \n {}" , msg. len( ) , msg)
593
- }
594
-
595
- // A function that takes a byte slice as input and returns the content length as an option
596
- fn resp ( input : & [ u8 ] ) -> Option < & str > {
597
- let input_str = std:: str:: from_utf8 ( input) . ok ( ) ?;
598
- let mut splits = input_str. split ( "\r \n \r \n " ) ;
599
- let header = splits. next ( ) ?;
600
- let body = splits. next ( ) ?;
601
- let length_str = header. trim_start_matches ( "Content-Length: " ) ;
602
- let length = length_str. parse :: < usize > ( ) . ok ( ) ?;
603
- Some ( & body[ ..length] )
604
- }
605
-
606
- async fn test_lsp ( ) {
607
- let initialize = r#"{
608
- "jsonrpc":"2.0",
609
- "id": 1,
610
- "method": "initialize",
611
- "params": {
612
- "capabilities": {
613
- "textDocumentSync": 1
614
- }
615
- }
616
- }"# ;
617
- let ( mut req_client, mut resp_client) = start_lsp ( ) ;
618
- let mut buf = vec ! [ 0 ; 1024 ] ;
619
-
620
- req_client
621
- . write_all ( req ( initialize) . as_bytes ( ) )
622
- . await
623
- . unwrap ( ) ;
624
- let _ = resp_client. read ( & mut buf) . await . unwrap ( ) ;
625
-
626
- assert ! ( resp( & buf) . unwrap( ) . starts_with( '{' ) ) ;
627
-
628
- let save_file = r#"{
629
- "jsonrpc": "2.0",
630
- "id": 1,
631
- "method": "textDocument/codeAction",
632
- "params": {
633
- "range": {
634
- "end": {
635
- "character": 10,
636
- "line": 1
637
- },
638
- "start": {
639
- "character": 10,
640
- "line": 1
641
- }
642
- },
643
- "textDocument": {
644
- "uri": "file:///Users/codes/ast-grep-vscode/test.tsx"
645
- },
646
- "context": {
647
- "diagnostics": [
648
- {
649
- "range": {
650
- "start": {
651
- "line": 0,
652
- "character": 0
653
- },
654
- "end": {
655
- "line": 0,
656
- "character": 16
657
- }
658
- },
659
- "code": "no-console-rule",
660
- "source": "ast-grep",
661
- "message": "No console.log"
662
- }
663
- ],
664
- "only": ["source.fixAll"]
665
- }
666
- }
667
- }"# ;
668
-
669
- let mut buf = vec ! [ 0 ; 1024 ] ;
670
- req_client
671
- . write_all ( req ( save_file) . as_bytes ( ) )
672
- . await
673
- . unwrap ( ) ;
674
- let _ = resp_client. read ( & mut buf) . await . unwrap ( ) ;
675
-
676
- let json_val: Value = serde_json:: from_str ( resp ( & buf) . unwrap ( ) ) . unwrap ( ) ;
677
-
678
- // {"jsonrpc":"2.0","method":"window/logMessage","params":{"message":"run code action!","type":3}}
679
- assert_eq ! ( json_val[ "method" ] , "window/logMessage" ) ;
680
- }
681
-
682
- #[ test]
683
- fn actual_test ( ) {
684
- tokio:: runtime:: Runtime :: new ( ) . unwrap ( ) . block_on ( test_lsp ( ) ) ;
685
- }
686
- }
0 commit comments