summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/definition.rs
blob: 7c9e6d4841d7bb677ca1570a02a313e4fb151876 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
mod command;
mod document;
mod entry;
mod label;
mod string;

use lsp_types::{GotoDefinitionResponse, LocationLink, Position, Url};
use rowan::TextRange;

use crate::{
    db::Document,
    util::{cursor::CursorContext, line_index_ext::LineIndexExt},
    Db,
};

pub fn goto_definition(
    db: &dyn Db,
    uri: &Url,
    position: Position,
) -> Option<GotoDefinitionResponse> {
    let context = CursorContext::new(db, uri, position, ())?;
    log::debug!("[Definition] Cursor: {:?}", context.cursor);

    let links: Vec<_> = command::goto_definition(&context)
        .or_else(|| document::goto_definition(&context))
        .or_else(|| entry::goto_definition(&context))
        .or_else(|| label::goto_definition(&context))
        .or_else(|| string::goto_definition(&context))?
        .into_iter()
        .map(|result| {
            let origin_selection_range = Some(
                context
                    .document
                    .contents(db)
                    .line_index(db)
                    .line_col_lsp_range(result.origin_selection_range),
            );

            let target_line_index = result.target.contents(db).line_index(db);
            let target_uri = result.target.location(context.db).uri(context.db).clone();
            let target_range = target_line_index.line_col_lsp_range(result.target_range);

            let target_selection_range =
                target_line_index.line_col_lsp_range(result.target_selection_range);

            LocationLink {
                origin_selection_range,
                target_uri,
                target_range,
                target_selection_range,
            }
        })
        .collect();

    Some(GotoDefinitionResponse::Link(links))
}

#[derive(Debug, Clone)]
struct DefinitionResult {
    origin_selection_range: TextRange,
    target: Document,
    target_range: TextRange,
    target_selection_range: TextRange,
}