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, PositionEncoding}
,
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 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
)
35 line_index
.index
.offset(line_col
).ok_or_else(|| format_err
!("Invalid offset"))?
;
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
)?
;
43 true => Err(format_err
!("Invalid Range").into()),
44 false => Ok(TextRange
::new(start
, end
)),
48 pub(crate) fn file_id(snap
: &GlobalStateSnapshot
, url
: &lsp_types
::Url
) -> Result
<FileId
> {
49 snap
.url_to_file_id(url
)
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 }
)
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
)
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 }
)
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
,
95 pub(crate) fn annotation(
96 snap
: &GlobalStateSnapshot
,
97 code_lens
: lsp_types
::CodeLens
,
98 ) -> Result
<Annotation
> {
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
)?
;
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
)?
;
110 range
: text_range(&line_index
, code_lens
.range
)?
,
111 kind
: AnnotationKind
::HasImpls { pos, data: None }
,
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
)?
;
119 range
: text_range(&line_index
, code_lens
.range
)?
,
120 kind
: AnnotationKind
::HasReferences { pos, data: None }
,