]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
Rollup merge of #102044 - ChrisDenton:BCrypt-system-rand, r=thomcc
[rust.git] / src / tools / rust-analyzer / crates / rust-analyzer / src / from_proto.rs
1 //! Conversion lsp_types types to rust-analyzer specific ones.
2 use anyhow::format_err;
3 use ide::{Annotation, AnnotationKind, AssistKind, LineCol, LineColUtf16};
4 use ide_db::base_db::{FileId, FilePosition, FileRange};
5 use syntax::{TextRange, TextSize};
6 use vfs::AbsPathBuf;
7
8 use crate::{
9     from_json,
10     global_state::GlobalStateSnapshot,
11     line_index::{LineIndex, OffsetEncoding},
12     lsp_ext,
13     lsp_utils::invalid_params_error,
14     Result,
15 };
16
17 pub(crate) fn abs_path(url: &lsp_types::Url) -> Result<AbsPathBuf> {
18     let path = url.to_file_path().map_err(|()| "url is not a file")?;
19     Ok(AbsPathBuf::try_from(path).unwrap())
20 }
21
22 pub(crate) fn vfs_path(url: &lsp_types::Url) -> Result<vfs::VfsPath> {
23     abs_path(url).map(vfs::VfsPath::from)
24 }
25
26 pub(crate) fn offset(line_index: &LineIndex, position: lsp_types::Position) -> Result<TextSize> {
27     let line_col = match line_index.encoding {
28         OffsetEncoding::Utf8 => {
29             LineCol { line: position.line as u32, col: position.character as u32 }
30         }
31         OffsetEncoding::Utf16 => {
32             let line_col =
33                 LineColUtf16 { line: position.line as u32, col: position.character as u32 };
34             line_index.index.to_utf8(line_col)
35         }
36     };
37     let text_size =
38         line_index.index.offset(line_col).ok_or_else(|| format_err!("Invalid offset"))?;
39     Ok(text_size)
40 }
41
42 pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Result<TextRange> {
43     let start = offset(line_index, range.start)?;
44     let end = offset(line_index, range.end)?;
45     let text_range = TextRange::new(start, end);
46     Ok(text_range)
47 }
48
49 pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
50     snap.url_to_file_id(url)
51 }
52
53 pub(crate) fn file_position(
54     snap: &GlobalStateSnapshot,
55     tdpp: lsp_types::TextDocumentPositionParams,
56 ) -> Result<FilePosition> {
57     let file_id = file_id(snap, &tdpp.text_document.uri)?;
58     let line_index = snap.file_line_index(file_id)?;
59     let offset = offset(&line_index, tdpp.position)?;
60     Ok(FilePosition { file_id, offset })
61 }
62
63 pub(crate) fn file_range(
64     snap: &GlobalStateSnapshot,
65     text_document_identifier: lsp_types::TextDocumentIdentifier,
66     range: lsp_types::Range,
67 ) -> Result<FileRange> {
68     let file_id = file_id(snap, &text_document_identifier.uri)?;
69     let line_index = snap.file_line_index(file_id)?;
70     let range = text_range(&line_index, range)?;
71     Ok(FileRange { file_id, range })
72 }
73
74 pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
75     let assist_kind = match &kind {
76         k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::None,
77         k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix,
78         k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor,
79         k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract,
80         k if k == &lsp_types::CodeActionKind::REFACTOR_INLINE => AssistKind::RefactorInline,
81         k if k == &lsp_types::CodeActionKind::REFACTOR_REWRITE => AssistKind::RefactorRewrite,
82         _ => return None,
83     };
84
85     Some(assist_kind)
86 }
87
88 pub(crate) fn annotation(
89     snap: &GlobalStateSnapshot,
90     code_lens: lsp_types::CodeLens,
91 ) -> Result<Annotation> {
92     let data =
93         code_lens.data.ok_or_else(|| invalid_params_error("code lens without data".to_string()))?;
94     let resolve = from_json::<lsp_ext::CodeLensResolveData>("CodeLensResolveData", &data)?;
95
96     match resolve {
97         lsp_ext::CodeLensResolveData::Impls(params) => {
98             let file_id =
99                 snap.url_to_file_id(&params.text_document_position_params.text_document.uri)?;
100             let line_index = snap.file_line_index(file_id)?;
101
102             Ok(Annotation {
103                 range: text_range(&line_index, code_lens.range)?,
104                 kind: AnnotationKind::HasImpls { file_id, data: None },
105             })
106         }
107         lsp_ext::CodeLensResolveData::References(params) => {
108             let file_id = snap.url_to_file_id(&params.text_document.uri)?;
109             let line_index = snap.file_line_index(file_id)?;
110
111             Ok(Annotation {
112                 range: text_range(&line_index, code_lens.range)?,
113                 kind: AnnotationKind::HasReferences { file_id, data: None },
114             })
115         }
116     }
117 }