squawk-server 2.45.0

LSP server for Squawk
Documentation
use anyhow::Result;
use lsp_types::{
    InlayHint, InlayHintKind, InlayHintLabel, InlayHintLabelPart, InlayHintParams, Location,
};
use squawk_ide::builtins::{builtins_line_index, builtins_url};
use squawk_ide::db::line_index;
use squawk_ide::inlay_hints::inlay_hints;

use crate::global_state::Snapshot;
use crate::lsp_utils;

pub(crate) fn handle_inlay_hints(
    snapshot: &Snapshot,
    params: InlayHintParams,
) -> Result<Option<Vec<InlayHint>>> {
    let uri = params.text_document.uri;

    let db = snapshot.db();
    let file = snapshot.file(&uri).unwrap();
    let line_index = line_index(db, file);

    let hints = inlay_hints(db, file);

    let lsp_hints: Vec<InlayHint> = hints
        .into_iter()
        .flat_map(|hint| {
            let line_col = line_index.line_col(hint.position);
            let position = lsp_types::Position::new(line_col.line, line_col.col);

            let uri = match hint.file {
                Some(squawk_ide::goto_definition::FileId::Current) | None => uri.clone(),
                Some(squawk_ide::goto_definition::FileId::Builtins) => builtins_url(db)?,
            };

            let line_index = match hint.file {
                Some(squawk_ide::goto_definition::FileId::Current) | None => &line_index,
                Some(squawk_ide::goto_definition::FileId::Builtins) => &builtins_line_index(db),
            };

            let kind: InlayHintKind = match hint.kind {
                squawk_ide::inlay_hints::InlayHintKind::Parameter => InlayHintKind::PARAMETER,
                squawk_ide::inlay_hints::InlayHintKind::Type => InlayHintKind::TYPE,
            };

            let label = if let Some(target_range) = hint.target {
                InlayHintLabel::LabelParts(vec![InlayHintLabelPart {
                    value: hint.label,
                    location: Some(Location {
                        uri: uri.clone(),
                        range: lsp_utils::range(line_index, target_range),
                    }),
                    tooltip: None,
                    command: None,
                }])
            } else {
                InlayHintLabel::String(hint.label)
            };

            Some(InlayHint {
                position,
                label,
                kind: Some(kind),
                text_edits: None,
                tooltip: None,
                padding_left: None,
                padding_right: None,
                data: None,
            })
        })
        .collect();

    Ok(Some(lsp_hints))
}