Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit ca4569c

Browse files
authored
Merge pull request #445 from jonasbb/improve-deglob
Deglob: Allow to deglob a line without selecting the * character
2 parents 2e5ba48 + 85c0657 commit ca4569c

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

src/actions/mod.rs

+29-6
Original file line numberDiff line numberDiff line change
@@ -616,22 +616,45 @@ impl ActionHandler {
616616
pub fn deglob<O: Output>(&self, id: usize, location: Location, out: O) {
617617
let t = thread::current();
618618
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");
620620

621621
trace!("deglob {:?}", span);
622622

623623
// Start by checking that the user has selected a glob import.
624624
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);
627649
}
628650

629651
// Save-analysis exports the deglobbed version of a glob import as its type string.
630652
let vfs = self.vfs.clone();
631653
let analysis = self.analysis.clone();
632654
let out_clone = out.clone();
655+
let span_ = span.clone();
633656
let rustw_handle = thread::spawn(move || {
634-
match vfs.load_span(span.clone()) {
657+
match vfs.load_span(span_.clone()) {
635658
Ok(ref s) if s != "*" => {
636659
out_clone.failure_message(id, ErrorCode::InvalidParams, "Not a glob");
637660
t.unpark();
@@ -646,7 +669,7 @@ impl ActionHandler {
646669
_ => {}
647670
}
648671

649-
let ty = analysis.show_type(&span);
672+
let ty = analysis.show_type(&span_);
650673
t.unpark();
651674

652675
ty.map_err(|_| {
@@ -675,7 +698,7 @@ impl ActionHandler {
675698
let output = serde_json::to_string(
676699
&RequestMessage::new(out.provide_id(),
677700
"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) })
679702
).unwrap();
680703
out.response(output);
681704

0 commit comments

Comments
 (0)