@@ -616,22 +616,45 @@ impl ActionHandler {
616
616
pub fn deglob < O : Output > ( & self , id : usize , location : Location , out : O ) {
617
617
let t = thread:: current ( ) ;
618
618
let span = ls_util:: location_to_rls ( location. clone ( ) ) ;
619
- let span = ignore_non_file_uri ! ( span, & location. uri, "deglob" ) ;
619
+ let mut span = ignore_non_file_uri ! ( span, & location. uri, "deglob" ) ;
620
620
621
621
trace ! ( "deglob {:?}" , span) ;
622
622
623
623
// Start by checking that the user has selected a glob import.
624
624
if span. range . start ( ) == span. range . end ( ) {
625
- out. failure_message ( id, ErrorCode :: InvalidParams , "Empty selection" ) ;
626
- return ;
625
+ // search for a glob in the line
626
+ let vfs = self . vfs . clone ( ) ;
627
+ let line = match vfs. load_line ( & span. file , span. range . row_start ) {
628
+ Ok ( l) => l,
629
+ Err ( _) => {
630
+ out. failure_message ( id, ErrorCode :: InvalidParams , "Could not retrieve line from VFS." ) ;
631
+ return ;
632
+ }
633
+ } ;
634
+
635
+ // search for exactly one "::*;" in the line. This should work fine for formatted text, but
636
+ // multiple use statements could be in the same line, then it is not possible to find which
637
+ // one to deglob.
638
+ let matches: Vec < _ > = line. char_indices ( ) . filter ( |& ( _, chr) | chr == '*' ) . collect ( ) ;
639
+ if matches. len ( ) == 0 {
640
+ out. failure_message ( id, ErrorCode :: InvalidParams , "No glob in selection." ) ;
641
+ return ;
642
+ } else if matches. len ( ) > 1 {
643
+ out. failure_message ( id, ErrorCode :: InvalidParams , "Multiple globs in selection." ) ;
644
+ return ;
645
+ }
646
+ let index = matches[ 0 ] . 0 as u32 ;
647
+ span. range . col_start = span:: Column :: new_zero_indexed ( index) ;
648
+ span. range . col_end = span:: Column :: new_zero_indexed ( index+1 ) ;
627
649
}
628
650
629
651
// Save-analysis exports the deglobbed version of a glob import as its type string.
630
652
let vfs = self . vfs . clone ( ) ;
631
653
let analysis = self . analysis . clone ( ) ;
632
654
let out_clone = out. clone ( ) ;
655
+ let span_ = span. clone ( ) ;
633
656
let rustw_handle = thread:: spawn ( move || {
634
- match vfs. load_span ( span . clone ( ) ) {
657
+ match vfs. load_span ( span_ . clone ( ) ) {
635
658
Ok ( ref s) if s != "*" => {
636
659
out_clone. failure_message ( id, ErrorCode :: InvalidParams , "Not a glob" ) ;
637
660
t. unpark ( ) ;
@@ -646,7 +669,7 @@ impl ActionHandler {
646
669
_ => { }
647
670
}
648
671
649
- let ty = analysis. show_type ( & span ) ;
672
+ let ty = analysis. show_type ( & span_ ) ;
650
673
t. unpark ( ) ;
651
674
652
675
ty. map_err ( |_| {
@@ -675,7 +698,7 @@ impl ActionHandler {
675
698
let output = serde_json:: to_string (
676
699
& RequestMessage :: new ( out. provide_id ( ) ,
677
700
"workspace/applyEdit" . to_owned ( ) ,
678
- ApplyWorkspaceEditParams { edit : make_workspace_edit ( location , deglob_str) } )
701
+ ApplyWorkspaceEditParams { edit : make_workspace_edit ( ls_util :: rls_to_location ( & span ) , deglob_str) } )
679
702
) . unwrap ( ) ;
680
703
out. response ( output) ;
681
704
0 commit comments