]>
Commit | Line | Data |
---|---|---|
064997fb FG |
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, | |
487cf647 | 11 | line_index::{LineIndex, PositionEncoding}, |
064997fb FG |
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 { | |
487cf647 | 28 | PositionEncoding::Utf8 => { |
064997fb FG |
29 | LineCol { line: position.line as u32, col: position.character as u32 } |
30 | } | |
487cf647 | 31 | PositionEncoding::Utf16 => { |
064997fb FG |
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)?; | |
487cf647 FG |
45 | match end < start { |
46 | true => Err(format_err!("Invalid Range").into()), | |
47 | false => Ok(TextRange::new(start, end)), | |
48 | } | |
064997fb FG |
49 | } |
50 | ||
51 | pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> { | |
52 | snap.url_to_file_id(url) | |
53 | } | |
54 | ||
55 | pub(crate) fn file_position( | |
56 | snap: &GlobalStateSnapshot, | |
57 | tdpp: lsp_types::TextDocumentPositionParams, | |
58 | ) -> Result<FilePosition> { | |
59 | let file_id = file_id(snap, &tdpp.text_document.uri)?; | |
60 | let line_index = snap.file_line_index(file_id)?; | |
61 | let offset = offset(&line_index, tdpp.position)?; | |
62 | Ok(FilePosition { file_id, offset }) | |
63 | } | |
64 | ||
65 | pub(crate) fn file_range( | |
66 | snap: &GlobalStateSnapshot, | |
67 | text_document_identifier: lsp_types::TextDocumentIdentifier, | |
68 | range: lsp_types::Range, | |
69 | ) -> Result<FileRange> { | |
70 | let file_id = file_id(snap, &text_document_identifier.uri)?; | |
71 | let line_index = snap.file_line_index(file_id)?; | |
72 | let range = text_range(&line_index, range)?; | |
73 | Ok(FileRange { file_id, range }) | |
74 | } | |
75 | ||
76 | pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> { | |
77 | let assist_kind = match &kind { | |
78 | k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::None, | |
79 | k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix, | |
80 | k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor, | |
81 | k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract, | |
82 | k if k == &lsp_types::CodeActionKind::REFACTOR_INLINE => AssistKind::RefactorInline, | |
83 | k if k == &lsp_types::CodeActionKind::REFACTOR_REWRITE => AssistKind::RefactorRewrite, | |
84 | _ => return None, | |
85 | }; | |
86 | ||
87 | Some(assist_kind) | |
88 | } | |
89 | ||
90 | pub(crate) fn annotation( | |
91 | snap: &GlobalStateSnapshot, | |
92 | code_lens: lsp_types::CodeLens, | |
93 | ) -> Result<Annotation> { | |
94 | let data = | |
95 | code_lens.data.ok_or_else(|| invalid_params_error("code lens without data".to_string()))?; | |
96 | let resolve = from_json::<lsp_ext::CodeLensResolveData>("CodeLensResolveData", &data)?; | |
97 | ||
98 | match resolve { | |
99 | lsp_ext::CodeLensResolveData::Impls(params) => { | |
2b03887a FG |
100 | let pos @ FilePosition { file_id, .. } = |
101 | file_position(snap, params.text_document_position_params)?; | |
064997fb FG |
102 | let line_index = snap.file_line_index(file_id)?; |
103 | ||
104 | Ok(Annotation { | |
105 | range: text_range(&line_index, code_lens.range)?, | |
2b03887a | 106 | kind: AnnotationKind::HasImpls { pos, data: None }, |
064997fb FG |
107 | }) |
108 | } | |
109 | lsp_ext::CodeLensResolveData::References(params) => { | |
2b03887a | 110 | let pos @ FilePosition { file_id, .. } = file_position(snap, params)?; |
064997fb FG |
111 | let line_index = snap.file_line_index(file_id)?; |
112 | ||
113 | Ok(Annotation { | |
114 | range: text_range(&line_index, code_lens.range)?, | |
2b03887a | 115 | kind: AnnotationKind::HasReferences { pos, data: None }, |
064997fb FG |
116 | }) |
117 | } | |
118 | } | |
119 | } |