]> git.proxmox.com Git - rustc.git/blob - src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs
New upstream version 1.68.2+dfsg1
[rustc.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, PositionEncoding},
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 PositionEncoding::Utf8 => LineCol { line: position.line, col: position.character },
29 PositionEncoding::Utf16 => {
30 let line_col = LineColUtf16 { line: position.line, col: position.character };
31 line_index.index.to_utf8(line_col)
32 }
33 };
34 let text_size =
35 line_index.index.offset(line_col).ok_or_else(|| format_err!("Invalid offset"))?;
36 Ok(text_size)
37 }
38
39 pub(crate) fn text_range(line_index: &LineIndex, range: lsp_types::Range) -> Result<TextRange> {
40 let start = offset(line_index, range.start)?;
41 let end = offset(line_index, range.end)?;
42 match end < start {
43 true => Err(format_err!("Invalid Range").into()),
44 false => Ok(TextRange::new(start, end)),
45 }
46 }
47
48 pub(crate) fn file_id(snap: &GlobalStateSnapshot, url: &lsp_types::Url) -> Result<FileId> {
49 snap.url_to_file_id(url)
50 }
51
52 pub(crate) fn file_position(
53 snap: &GlobalStateSnapshot,
54 tdpp: lsp_types::TextDocumentPositionParams,
55 ) -> Result<FilePosition> {
56 let file_id = file_id(snap, &tdpp.text_document.uri)?;
57 let line_index = snap.file_line_index(file_id)?;
58 let offset = offset(&line_index, tdpp.position)?;
59 Ok(FilePosition { file_id, offset })
60 }
61
62 pub(crate) fn file_range(
63 snap: &GlobalStateSnapshot,
64 text_document_identifier: lsp_types::TextDocumentIdentifier,
65 range: lsp_types::Range,
66 ) -> Result<FileRange> {
67 file_range_uri(snap, &text_document_identifier.uri, range)
68 }
69
70 pub(crate) fn file_range_uri(
71 snap: &GlobalStateSnapshot,
72 document: &lsp_types::Url,
73 range: lsp_types::Range,
74 ) -> Result<FileRange> {
75 let file_id = file_id(snap, document)?;
76 let line_index = snap.file_line_index(file_id)?;
77 let range = text_range(&line_index, range)?;
78 Ok(FileRange { file_id, range })
79 }
80
81 pub(crate) fn assist_kind(kind: lsp_types::CodeActionKind) -> Option<AssistKind> {
82 let assist_kind = match &kind {
83 k if k == &lsp_types::CodeActionKind::EMPTY => AssistKind::None,
84 k if k == &lsp_types::CodeActionKind::QUICKFIX => AssistKind::QuickFix,
85 k if k == &lsp_types::CodeActionKind::REFACTOR => AssistKind::Refactor,
86 k if k == &lsp_types::CodeActionKind::REFACTOR_EXTRACT => AssistKind::RefactorExtract,
87 k if k == &lsp_types::CodeActionKind::REFACTOR_INLINE => AssistKind::RefactorInline,
88 k if k == &lsp_types::CodeActionKind::REFACTOR_REWRITE => AssistKind::RefactorRewrite,
89 _ => return None,
90 };
91
92 Some(assist_kind)
93 }
94
95 pub(crate) fn annotation(
96 snap: &GlobalStateSnapshot,
97 code_lens: lsp_types::CodeLens,
98 ) -> Result<Annotation> {
99 let data =
100 code_lens.data.ok_or_else(|| invalid_params_error("code lens without data".to_string()))?;
101 let resolve = from_json::<lsp_ext::CodeLensResolveData>("CodeLensResolveData", &data)?;
102
103 match resolve {
104 lsp_ext::CodeLensResolveData::Impls(params) => {
105 let pos @ FilePosition { file_id, .. } =
106 file_position(snap, params.text_document_position_params)?;
107 let line_index = snap.file_line_index(file_id)?;
108
109 Ok(Annotation {
110 range: text_range(&line_index, code_lens.range)?,
111 kind: AnnotationKind::HasImpls { pos, data: None },
112 })
113 }
114 lsp_ext::CodeLensResolveData::References(params) => {
115 let pos @ FilePosition { file_id, .. } = file_position(snap, params)?;
116 let line_index = snap.file_line_index(file_id)?;
117
118 Ok(Annotation {
119 range: text_range(&line_index, code_lens.range)?,
120 kind: AnnotationKind::HasReferences { pos, data: None },
121 })
122 }
123 }
124 }