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}
;
10 global_state
::GlobalStateSnapshot
,
11 line_index
::{LineIndex, OffsetEncoding}
,
13 lsp_utils
::invalid_params_error
,
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())
22 pub(crate) fn vfs_path(url
: &lsp_types
::Url
) -> Result
<vfs
::VfsPath
> {
23 abs_path(url
).map(vfs
::VfsPath
::from
)
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 }
31 OffsetEncoding
::Utf16
=> {
33 LineColUtf16 { line: position.line as u32, col: position.character as u32 }
;
34 line_index
.index
.to_utf8(line_col
)
38 line_index
.index
.offset(line_col
).ok_or_else(|| format_err
!("Invalid offset"))?
;
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
);
49 pub(crate) fn file_id(snap
: &GlobalStateSnapshot
, url
: &lsp_types
::Url
) -> Result
<FileId
> {
50 snap
.url_to_file_id(url
)
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 }
)
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 }
)
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
,
88 pub(crate) fn annotation(
89 snap
: &GlobalStateSnapshot
,
90 code_lens
: lsp_types
::CodeLens
,
91 ) -> Result
<Annotation
> {
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
)?
;
97 lsp_ext
::CodeLensResolveData
::Impls(params
) => {
98 let pos @ FilePosition { file_id, .. }
=
99 file_position(snap
, params
.text_document_position_params
)?
;
100 let line_index
= snap
.file_line_index(file_id
)?
;
103 range
: text_range(&line_index
, code_lens
.range
)?
,
104 kind
: AnnotationKind
::HasImpls { pos, data: None }
,
107 lsp_ext
::CodeLensResolveData
::References(params
) => {
108 let pos @ FilePosition { file_id, .. }
= file_position(snap
, params
)?
;
109 let line_index
= snap
.file_line_index(file_id
)?
;
112 range
: text_range(&line_index
, code_lens
.range
)?
,
113 kind
: AnnotationKind
::HasReferences { pos, data: None }
,