use std::rc::Rc;
use crate::{
Server,
server::{
lsp::{
ReferencesRequest, ReferencesResponse,
errors::{ErrorCode, LSPError},
textdocument::{Location, Range},
},
message_handler::common::find_variable_occurrences,
},
};
use futures::lock::Mutex;
use ll_sparql_parser::ast::{AstNode, Var};
pub(super) async fn handle_references_request(
server_rc: Rc<Mutex<Server>>,
request: ReferencesRequest,
) -> Result<(), LSPError> {
let server = server_rc.lock().await;
let document = server.state.get_document(request.get_document_uri())?;
let root = server
.state
.get_cached_parse_tree(request.get_document_uri())?
.tree;
let offset = request
.get_position()
.byte_index(&document.text)
.ok_or_else(|| {
LSPError::new(
ErrorCode::InvalidParams,
"The hover position is not inside the text document",
)
})?;
let seleced_token = root.token_at_offset(offset).left_biased().ok_or_else(|| {
LSPError::new(
ErrorCode::InvalidParams,
"The hover position is not inside the text document",
)
})?;
let mut response = ReferencesResponse::new(request.get_id());
if let Some(var) = seleced_token.parent().and_then(Var::cast) {
let vars = find_variable_occurrences(&var);
let locations: Vec<Location> = vars
.into_iter()
.map(|var| Location {
uri: document.uri.clone(),
range: Range::from_byte_offset_range(var.syntax().text_range(), &document.text)
.unwrap(),
})
.collect();
response.set_locations(locations);
}
server.send_message(response)
}