qlue-ls 3.4.0

A language server for SPARQL
Documentation
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)
}