use super::*;
pub(crate) enum ReadJob {
Format {
id: RequestId,
path: PathBuf,
text: String,
style: FormatStyle,
sender: Sender<Message>,
},
FormatRange {
id: RequestId,
path: PathBuf,
text: String,
range: Range,
style: FormatStyle,
sender: Sender<Message>,
},
Hover {
id: RequestId,
path: PathBuf,
text: String,
position: Position,
sender: Sender<Message>,
},
Completion {
id: RequestId,
path: PathBuf,
text: String,
position: Position,
sender: Sender<Message>,
},
SignatureHelp {
id: RequestId,
path: PathBuf,
text: String,
position: Position,
sender: Sender<Message>,
},
ResolveCompletion {
id: RequestId,
item: Box<CompletionItem>,
sender: Sender<Message>,
},
Definition {
id: RequestId,
path: PathBuf,
uri: Uri,
text: String,
position: Position,
sender: Sender<Message>,
},
References {
id: RequestId,
path: PathBuf,
uri: Uri,
text: String,
position: Position,
include_declaration: bool,
sender: Sender<Message>,
},
Rename {
id: RequestId,
path: PathBuf,
uri: Uri,
text: String,
offset: usize,
new_name: String,
sender: Sender<Message>,
},
WillRenameFiles {
id: RequestId,
renames: Vec<(PathBuf, PathBuf)>,
sender: Sender<Message>,
},
WorkspaceSymbol {
id: RequestId,
query: String,
sender: Sender<Message>,
},
}
pub(crate) fn run_read(snapshot: Analysis, job: ReadJob) {
match job {
ReadJob::Format {
id,
path,
text,
style,
sender,
} => {
let result = format_edits_via_db(&snapshot, &path, &text, style);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::FormatRange {
id,
path,
text,
range,
style,
sender,
} => {
let result = format_range_edits_via_db(&snapshot, &path, &text, range, style);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::Hover {
id,
path,
text,
position,
sender,
} => {
let result = hover_via_db(&snapshot, &path, &text, position);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::Completion {
id,
path,
text,
position,
sender,
} => {
let result = completion_via_db(&snapshot, &path, &text, position);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::SignatureHelp {
id,
path,
text,
position,
sender,
} => {
let result = signature_help_via_db(&snapshot, &path, &text, position);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::ResolveCompletion { id, item, sender } => {
let result = resolve_completion(*item, &snapshot.library_data().unwrap_or_default());
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::Definition {
id,
path,
uri,
text,
position,
sender,
} => {
let result = definition_via_db(&snapshot, &path, &uri, &text, position);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::References {
id,
path,
uri,
text,
position,
include_declaration,
sender,
} => {
let result =
references_via_db(&snapshot, &path, &uri, &text, position, include_declaration);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::Rename {
id,
path,
uri,
text,
offset,
new_name,
sender,
} => {
let result = rename_via_db(&snapshot, &path, &uri, &text, offset, &new_name);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::WillRenameFiles {
id,
renames,
sender,
} => {
let result = will_rename_via_db(&snapshot, &renames);
let _ = sender.send(Message::Response(Response::new_ok(id, result)));
}
ReadJob::WorkspaceSymbol { id, query, sender } => {
let symbols = workspace_symbols_via_db(&snapshot, &query);
let response = WorkspaceSymbolResponse::Nested(symbols);
let _ = sender.send(Message::Response(Response::new_ok(id, response)));
}
}
}
pub(crate) fn dedup_locations(locations: &mut Vec<Location>) {
locations.sort_by(|a, b| {
(a.uri.as_str(), pos_key(a.range.start), pos_key(a.range.end)).cmp(&(
b.uri.as_str(),
pos_key(b.range.start),
pos_key(b.range.end),
))
});
locations.dedup();
}
pub(crate) fn pos_key(position: Position) -> (u32, u32) {
(position.line, position.character)
}
pub(crate) fn location_in(snapshot: &Analysis, path: &Path, range: TextRange) -> Option<Location> {
let file = snapshot.lookup_file(path)?;
let target_uri = uri::from_path(path)?;
let target_index = LineIndex::new(snapshot.file_text(file));
Some(Location {
uri: target_uri,
range: text_range_to_lsp_range(&target_index, range),
})
}
pub(crate) fn text_edit_in(
snapshot: &Analysis,
path: &Path,
range: TextRange,
new_name: &str,
) -> Option<(Uri, TextEdit)> {
let file = snapshot.lookup_file(path)?;
let target_uri = uri::from_path(path)?;
let target_index = LineIndex::new(snapshot.file_text(file));
Some((
target_uri,
TextEdit {
range: text_range_to_lsp_range(&target_index, range),
new_text: new_name.to_string(),
},
))
}
pub(crate) fn finalize_rename(mut changes: HashMap<Uri, Vec<TextEdit>>) -> Option<WorkspaceEdit> {
changes.retain(|_, edits| {
edits.sort_by_key(|a| (a.range.start, a.range.end));
edits.dedup();
!edits.is_empty()
});
(!changes.is_empty()).then(|| WorkspaceEdit {
changes: Some(changes),
..Default::default()
})
}